Rich messaging and native signals
Media attachments, iMessage effects, native voice memos, tapback reactions, the typing bubble, and read state.
Everything on this page is what makes a Blue Reacher line feel like a person on an iPhone rather than a gateway.
Media
Attach 1 to 10 files to any send with media_urls on POST /v1/messages: public https:// URLs, max 2048 characters each. Works on both drip and instant. message becomes optional when media is present.
Message effects
Instant sends can carry a native iMessage effect via message_effect:
| Full screen | Bubble |
|---|---|
confetti, balloons, love, lasers, fireworks, celebration, echo, spotlight | slam, loud, gentle, invisibleink |
Effects require send_mode: "instant"; a drip send with an effect returns 400 effect_requires_instant rather than quietly delivering plain. Effects degrade by design: a message carrying media sends plain, and an SMS recipient always gets plain text.
Voice memos
POST https://api.bluereacher.com/v1/voice-memosRequires write. Fetches your audio (public HTTPS URL, up to 25 MB, mp3 / m4a / wav / aac) and delivers it as a native Apple voice bubble when possible, falling back to a media attachment otherwise. The response tells you which happened.
curl -X POST https://api.bluereacher.com/v1/voice-memos \
-H "Authorization: Bearer brk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "to": "+16465550119", "audio_url": "https://example.com/clips/intro.m4a" }'{ "success": true, "message_id": "vm_882", "queued": true, "memo_format": "native_bubble" }422 audio_url_unreachable means the URL did not resolve to a fetchable audio file. Rate limit: 10/min per key.
Tapback reactions
POST https://api.bluereacher.com/v1/reactions
DELETE https://api.bluereacher.com/v1/reactionsSend a native tapback on a message you identify by message_id, or by phone plus external_id (the iMessage GUID carried on inbound webhook events). The six classic tapbacks are supported: ❤️ 👍 👎 😂 ‼️ ❓. Any other emoji, or a word or phrase, is rejected 422 not_deliverable.
curl -X POST https://api.bluereacher.com/v1/reactions \
-H "Authorization: Bearer brk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "emoji": "❤️", "message_id": "m_312" }'POST is idempotent: re-sending an already-delivered tapback returns already_delivered: true without re-sending. DELETE has two outcomes and says which occurred: a still-queued tapback is cancelled before the recipient ever sees it (cancelled_before_delivery: true), and an already-delivered one is genuinely taken back off the recipient's device (removal_queued: true). SMS bubbles cannot take tapbacks. Rate limit: 30/min.
Inbound reactions from contacts arrive as the reaction.received webhook.
Typing indicator
POST https://api.bluereacher.com/v1/typingLights the native "…" bubble on the recipient's device from your line. Window defaults to about 10 seconds; override with duration_ms (3000 to 60000). The response returns expires_at and keepalive_interval_ms; re-POST at that cadence to hold the bubble while composing. is_typing: false clears immediately.
curl -X POST https://api.bluereacher.com/v1/typing \
-H "Authorization: Bearer brk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "phone": "+16465550119", "device_id": "8c9a4f2e-1d3b-4a6c-9e8f-2b7c5d1a9e3f", "is_typing": true }'The natural agent pattern: typing on, wait a human-plausible beat, send instant, typing clears itself.
Read state
POST https://api.bluereacher.com/v1/readClears the connected CRM conversation's unread badge for a contact (graceful no-op without a CRM). With native: true plus device_id, a native mark-thread-read is queued for the line, which shows the contact their message was read.
curl -X POST https://api.bluereacher.com/v1/read \
-H "Authorization: Bearer brk_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "phone": "+16465550119", "native": true, "device_id": "8c9a4f2e-1d3b-4a6c-9e8f-2b7c5d1a9e3f" }'
