textoptionalstringPlain text message. May be combined with attachments (sent as media with a caption) — except a lone audio file, which is sent as a standalone voice memo and cannot carry a caption.
/channels/{channel}/messagesChannel-scoped equivalent of POST /messages with an explicit from: :channel accepts the same phone number (URL-encode + as %2B), alias, or ch_... value from accepts, and the body omits from. Multiple recipients on a group-capable channel (blooio/whatsapp) form a single group thread; on other channels they fan out to individual sends (max 100).
channelRequiredstringThe channel reference — the same three forms from accepts: a phone number (URL-encode + as %2B), a channel alias, or the exact channel id (ch_...).
AuthorizationRequiredstringYour API key, sent as a bearer token: Authorization: Bearer <api_key>. Editing this stays in sync with the API key box on the right.
Idempotency-KeyoptionalstringOptional key for safe retries. Replaying the same key with an identical body returns the original result; a different body returns 409. Use a unique value (such as a UUID) per logical request.
textoptionalstringPlain text message. May be combined with attachments (sent as media with a caption) — except a lone audio file, which is sent as a standalone voice memo and cannot carry a caption.
attachmentsoptionalstring[]Public https media URLs. May be combined with text. On Blooio iMessage, two or more image/video URLs are grouped into one photo/video carousel/collage bubble by default; set carousel: false to send them as separate bubbles. **Voice memos:** a single audio file (.mp3, .m4a, .wav, .aac, .opus, .ogg) is automatically sent as a voice memo (the native waveform/scrubber bubble), not a plain audio-file attachment — no extra field is needed. A voice memo is a standalone bubble, so it cannot be combined with text or any other attachment; do that and the send is rejected with 422 invalid_content. To send audio with a message, send the voice memo and the text as two separate requests.
rich_linkoptionalobjectA tappable rich link bubble (Blooio /).
urlRequiredstringtitleoptionalstringapp_clipoptionalobjectAn App Clip bubble (Blooio p2p iMessage only). Sends an App Clip launch URL that Messages renders as a native App Clip card (app icon + name + Open button); tapping it launches the instant App Clip experience without an install. Provide either a ready-made url (Apple's https://appclip.apple.com/id?p=<bundleID> launcher, or an app's own associated-domain App Clip link) or the bundle_id convenience field, which is expanded into the canonical Apple launch URL. Tip: App-Clip availability is region/OS gated by Apple; an unavailable clip renders a card that falls back to the App Store. To deep-link into an already-installed app instead (e.g. open a specific screen in a downloaded app), send that app's universal link via rich_link.
urloptionalstringThe App Clip launch URL (https). Mutually exclusive with bundle_id; if both are given, url wins.
bundle_idoptionalstringApp Clip bundle identifier (e.g. com.example.app.Clip), expanded to https://appclip.apple.com/id?p=<bundle_id>. Used when url is absent.
titleoptionalstringOptional preview title override.
imessage_appoptionalobjectBring-your-own iMessage App Extension bubble (Blooio p2p iMessage only). Blooio is the transport, NOT the renderer: you point at YOUR OWN signed iMessage app extension and we assemble the MSMessage app balloon and send it. Recipients who have your app installed render its interactive overlay (its MSMessagesAppViewController reads url on tap); recipients who don't see the native template card (from caption/image_url) plus Apple's built-in App Store fallback. Identify your extension with bundle_id + team_id (used to form the com.apple.messages.MSMessageExtensionBalloonPlugin:<team_id>:<bundle_id> plugin id) and pass the app-state url your extension understands. This does NOT ship or host a renderer — the recipient must have your app for the interactive experience. (For instant, no-install experiences use app_clip; to deep-link into an already-installed app use rich_link.)
bundle_idRequiredstringYour iMessage app extension's bundle identifier (e.g. com.acme.app.MessagesExtension).
team_idRequiredstringYour Apple Developer Team ID. Combined with bundle_id to form the balloon plugin id.
urlRequiredstringThe app-state URL your extension reads on tap (its MSMessage.url). Carries the state to reconstruct on the recipient device.
app_nameoptionalstringDisplay name shown for the app (the an field). Defaults to a generic label.
captionoptionalstringTemplate-card caption shown to everyone (including recipients without the app).
subcaptionoptionalstringOptional template-card subcaption.
image_urloptionalstringOptional https image used as the fallback template card thumbnail. Fetched best-effort (≤256KB); a fetch failure never fails the send.
app_store_idoptionalintegerOptional App Store id (adam id) for your app. When the recipient doesn't have the extension installed, Messages uses it to deep-link the App Store "get this app" fallback to the correct listing. Omitting it leaves the send unchanged.
polloptionalobjectA native Blooio poll. Routed sends automatically consider only poll-capable channels.
titleRequiredstringoptionsRequiredstring[]interactiveoptionalobjectInteractive content (WhatsApp Business / RCS). Requires kind.
kindRequiredstringtemplateoptionalobjectTemplate content (WhatsApp Business).
template_idoptionalstringpartsoptionalobject[]Ordered text/media parts sent as one multipart message (Blooio only). When every part is an image/video (two or more, no text parts) Messages renders them as a photo/video carousel/collage by default; set carousel: false to opt out.
Array of object
textoptionalstringurloptionalstringreply_tooptionalstringMessage id to reply to. Applies to the whole outgoing message.
effectoptionalstringiMessage screen/bubble effect (Blooio, text only).
link_previewoptionalLinkPreviewimageUrloptionalstringtitleoptionalstringbadgeoptionalstringOptional attribution badge shown under the bubble: sent_with_siri renders "Sent with Siri" and sent_with_facetime renders "Sent with FaceTime", the way a message dictated to Siri or sent during a FaceTime call appears. Omit for no badge. Any other value is rejected with 422 invalid_content. Applies to text, attachments (media), parts (multipart), rich_link, and app_clip sends on Blooio iMessage channels only; rejected with 422 invalid_content on other content types. No effect on non-Blooio channels.
"sent_with_siri""sent_with_facetime"carouseloptionalbooleanGroup image/video attachments into ONE message that Messages renders as a swipeable photo/video carousel/collage, instead of separate bubbles (Blooio p2p iMessage only). DEFAULTS ON: a Blooio send whose attachments (via attachments or parts) are two or more image/video URLs is grouped automatically — set carousel: false to send them as independent bubbles instead. Set carousel: true explicitly to also enforce the visual-only rule (a known non-visual extension like .pdf, a text part, or fewer than two attachments then returns 422 invalid_carousel); left unset, a non-qualifying send simply isn't grouped. Image extensions: jpg/jpeg/png/gif/heic/heif/webp/bmp/tiff/avif; video: mov/mp4/m4v/qt/3gp/avi/mkv/webm; a URL with no extension is allowed (its real type resolves on the device). An optional text is carried as the carousel's caption. Only valid on Blooio iMessage channels (422 carousel_unsupported_for_channel_type if set on another channel type).
toRequiredRecipientA recipient: a raw identifier string (phone/email/opaque provider id), an array of identifier strings (multiple recipients), an existing { group_id } with an exact or hybrid owner sender, or (for routed sends) a { contact_id }. A contact_id enables cross-channel-type routing via the contact's identities; a bare identifier reaches phone/email-addressable channels only.
dry_runoptionalbooleanValidate and route only; do not send.
idoptionalstringchat_idoptionalstringchannel_idoptionalstringchannel_typeoptionalstring"blooio""twilio""whatsapp""whatsapp_business""rcs_business"protocoloptionalstringTransport state or resolved wire service; never null. pending = accepted and dispatched, wire service not resolved yet; imessage / rcs / sms = the device-confirmed transport (iMessage blue bubble, RCS, or SMS/MMS green bubble); whatsapp = sent over WhatsApp; unknown = accepted but the transport could not be resolved before the tracking window closed (see error).
"pending""unknown""imessage""sms""rcs""whatsapp"fromoptionalstring | nullThe resolved sender as a human value: the sending channel's phone number (numbered channels) or alias (non-numbered channels). This is the primary sender reference; channel_id remains available for exact follow-up and audit.
directionoptionalstring"inbound""outbound"typeoptionalstringstatusoptionalstringInitial lifecycle state for the send: normally queued (accepted for delivery), or failed if rejected before dispatch. Later transitions (sent → delivered / read, or failed) are reported via the message status endpoint and message.* webhooks.
group_idoptionalstringExisting group id for a group-targeted send.
hybridoptionalobjectHybrid routing phase and optional transition placement.
erroroptionalobject | nullfallbackoptionalobjectPresent when a send could not be delivered on the requested channel and a different channel should be tried.
recommendedoptionalbooleanTrue when falling back to another channel is recommended.
reasonoptionalstringtooptionalstringRecipient identifier. Present only on per-recipient items inside a fan-out (FanOutResult) response.
dry_runoptionalbooleanwould_sendoptionalbooleanpreviewoptionalobjectpolloptionalobjecttitleoptionalstringoptionsoptionalstring[]routingoptionalRoutingMetadataHow Blooio selected the concrete sender channel.
modeoptionalstring"explicit""priority""hybrid"channel_typeoptionalstring"blooio""twilio""whatsapp""whatsapp_business""rcs_business"numberoptionalstringaliasoptionalstringpriority_idoptionalstringpriorityoptionalintegerSends a live request with your values and shows the real response below. Your key is stored only in this browser.
curl -X POST https://api.blooio.com/v4/channels/string/messages \{ "id": "obj_a1b2c3d4", "chat_id": "chat_a1b2c3d4", "channel_id": "ch_a1b2c3d4", "channel_type": "blooio", "protocol": "pending", "from": "+15551234567", "direction": "inbound", "type": "string", "status": "active", "group_id": "grp_a1b2c3d4", "hybrid": {}, "error": {}, "fallback": { "recommended": false, "reason": "string" }, "to": "+15551234567", "dry_run": false, "would_send": false, "preview": {}, "poll": { "title": "Example title", "options": [ "string" ] }, "routing": { "mode": "explicit", "channel_type": "blooio", "number": "+15551234567", "alias": "string", "priority_id": "obj_a1b2c3d4", "priority": 0 }}