Blooio
Community Blooio adapter for Chat SDK. Send and receive iMessage, RCS, and SMS through Blooio's hosted gateway, with native tapback reactions, typing indicators, and capability checks.
Install
pnpm add chat-adapter-blooioQuick start
import { Chat } from "chat";
import { createBlooioAdapter } from "chat-adapter-blooio";
const chat = new Chat({
userName: "my-bot",
adapters: {
blooio: createBlooioAdapter(),
},
});createBlooioAdapter() reads credentials from environment variables by default:
| Variable | Required | Description |
|---|---|---|
BLOOIO_API_KEY | Yes | Blooio API key (Bearer token) |
BLOOIO_FROM_NUMBER | No | Default sending phone number (E.164) for multi-number accounts |
BLOOIO_WEBHOOK_SECRET | No | Webhook signing secret for HMAC-SHA256 verification |
BLOOIO_BASE_URL | No | Override the API base URL (default: https://backend.blooio.com/v2/api) |
Or pass them explicitly:
createBlooioAdapter({
apiKey: "your-api-key",
defaultFromNumber: "+14155551234",
webhookSecret: "whsec_...",
});Webhooks
Point your Blooio webhook URL at your server. The adapter handles these event types:
message.received— incoming iMessage/RCS/SMS routed to your botmessage.sent/message.delivered/message.failed/message.read— delivery lifecyclemessage.reaction— tapback reactions on messages
import { chat } from "@/lib/bot";
export async function POST(request: Request) {
await chat.initialize();
return chat.webhooks.blooio(request);
}Signature verification
Blooio signs webhooks with HMAC-SHA256. The adapter verifies the X-Blooio-Signature header automatically when webhookSecret is configured. The signature format is:
X-Blooio-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>Stale timestamps are rejected with a default tolerance of 300 seconds. Customize with:
createBlooioAdapter({
webhookSecret: "whsec_...",
timestampToleranceSec: 600, // 10 minutes
});Sending messages
Outbound messages flow through Chat SDK's standard postMessage interface. Markdown is automatically stripped to plain text since iMessage does not render it.
await chat.send("blooio", threadId, "Hello from the bot!");Attachments
Send media via sendMediaMessage:
import type { BlooioAdapter } from "chat-adapter-blooio";
const adapter = chat.getAdapter("blooio") as BlooioAdapter;
await adapter.sendMediaMessage(
threadId,
"https://example.com/photo.jpg",
"Check this out"
);Inbound attachment URLs from Blooio webhooks are parsed into Chat SDK attachment objects with auto-detected MIME types.
Reactions (tapbacks)
iMessage tapbacks are supported via addReaction and removeReaction. The adapter maps common emoji names to Blooio's six tapback types:
| Tapback | Aliases |
|---|---|
love | heart |
like | thumbs_up, thumbsup, +1 |
dislike | thumbs_down, thumbsdown, -1 |
laugh | haha |
emphasize | exclamation, !! |
question | ? |
Unlike some platforms, Blooio supports removing reactions too.
Typing indicators
startTyping() sends the animated "..." bubble to the recipient. Works for both 1:1 and group conversations.
Message history
fetchMessages() retrieves conversation history from the Blooio API with cursor-based pagination (backed by offset/limit).
Read receipts
Send read receipts for a conversation:
import type { BlooioAdapter } from "chat-adapter-blooio";
const adapter = chat.getAdapter("blooio") as BlooioAdapter;
await adapter.markRead(threadId);Contact capabilities
Check whether a contact supports iMessage or SMS:
const adapter = chat.getAdapter("blooio") as BlooioAdapter;
const result = await adapter.checkCapabilities("+15551234567");
// { contact: "+15551234567", capabilities: { imessage: true, sms: true } }Direct API access
Reach any Blooio v2 endpoint that isn't covered by the adapter interface:
const adapter = chat.getAdapter("blooio") as BlooioAdapter;
const client = adapter.getClient();
await client.request("GET", "/contacts", undefined, { limit: "50" });
await client.request("POST", "/groups", {
name: "Team",
members: ["+15551234567"],
});Protocol filtering
By default the adapter processes inbound messages from all protocols (iMessage, RCS, SMS). To restrict:
createBlooioAdapter({
allowedProtocols: ["imessage"],
});Thread ID format
Thread IDs encode the Blooio device number and chat target so conversations are sticky to a specific phone line:
blooio:<internalId_base64url>:<chatId_base64url> # 1:1
blooio:<internalId_base64url>:g:<groupId_base64url> # groupUse encodeThreadId / decodeThreadId to work with them programmatically.
Limitations
- No message editing — iMessage does not support editing sent messages via API.
editMessagethrows. - No unsend —
deleteMessageis a no-op; iMessage messages cannot be unsent via API. - Inbound media — attachment URLs from webhooks may expire. Persist them if you need them long-term.
Feature support
Messaging
| Feature | Supported |
|---|---|
| Post message | |
| Edit message | |
| Delete message | |
| File uploads | |
| Streaming | |
| Scheduled messages |
Rich content
| Feature | Supported |
|---|---|
| Card format | |
| Buttons | |
| Link buttons | |
| Select menus | |
| Tables | |
| Fields | |
| Images in cards | |
| Modals |
Conversations
| Feature | Supported |
|---|---|
| Slash commands | |
| Mentions | |
| Add reactions | Tapbacks |
| Remove reactions | Tapbacks |
| Typing indicator | |
| DMs | |
| Ephemeral messages | |
| User lookup | checkCapabilities |
| Parent subject | |
| Native client | |
| Custom API endpoint | baseUrl |
Message history
| Feature | Supported |
|---|---|
| Fetch messages | |
| Fetch single message | |
| Fetch thread info | |
| Fetch channel messages | |
| List threads | |
| Fetch channel info | |
| Post channel message |