message.inbound event to your webhook endpoint. This guide shows what that event contains, how to handle attachments and STOP replies, and a complete auto-reply receiver that’s safe to run in production.
You need a webhook subscription that includes message.inbound. The Quickstart creates one, and Test webhooks locally shows how to point one at your laptop.
The message.inbound event
Only messages from your contacts fire
message.inbound. Messages your line sends, whether through the API or the dashboard, fire message.queued, message.sent and the other status events instead, never message.inbound.
Group messages
In a group,conversation_kind is "group", sender_phone is the participant who posted, and participants lists the group. The event doesn’t carry the group’s chat_guid: to reply into the group, call GET /v1/messages/{message_id} with the inbound message_id and send with the chat_guid it returns. See Group conversations.
Attachments
When the contact sends images, GIFs, videos, audio or files, the event fires once, after every attachment has been fetched, andattachments lists them:
urlis a signed link that expires after 24 hours (expires_at). If you need the file, download it and store it yourself as soon as the event arrives; a retried delivery carries the same URL, so a late retry may already be expired.- An attachment iBubbl couldn’t fetch has
"unavailable": trueand nourl. Don’t treat it as an error; the text (if any) is still inbody. kindisimage,gif,video,audioorfile. Unsupported types are left out of the array.
STOP and opt-outs
If the whole message is a STOP keyword (stop, unsubscribe and the others on Suppression and opt-outs), iBubbl records the opt-out before it fires message.inbound, and fires a separate contact.opted_out event with source: "auto_keyword". You receive both events, in either order.
- Mark the contact do-not-contact in your system when
contact.opted_outarrives. - Any send to them after that returns
422 contact_opted_out(in a group,422 group_outbound_blocked_suppression). Treat it as final.
An auto-reply that cannot loop
An auto-reply is where most messaging integrations go wrong: a reply triggers an event, which triggers a reply, and the line sends hundreds of messages. The receiver below avoids that with five rules:- Verify the signature on the raw body, before parsing it. See Signature verification.
- De-duplicate on the event
id, and acknowledge at once. Deliveries are at-least-once; return200before doing slow work. See Retries and deduplication. - Act only on
message.inbound. Never send because ofmessage.sent,message.delivered,message.read,message.failedor any other event about your own messages: that is the classic loop. - Use a deterministic
idempotency_key:"auto-reply-" + message_id. However many times the same inbound event reaches you, iBubbl sends that reply at most once. - Reply at most once per conversation per cooldown. If the other side is also a bot, it answers your auto-reply and you answer back. A contact’s reply resets iBubbl’s unanswered limit, so that limit won’t stop a bot-to-bot exchange; your cooldown will.
GET /v1/messages/{id}, so an Apple ID email in from_number or a group conversation never breaks the send, and it treats every 4xx as final.
- Why both de-duplication and a deterministic key? The event-
idcheck skips work you’ve already done. The key is the guarantee: even if two instances of your app process the same event at the same moment, iBubbl sends that reply once. The Idempotency page explains replays. - STOP needs no special case. The opt-out is recorded before
message.inboundfires, so a reply to a STOP comes back422 contact_opted_outand the code stops. - Working hours still apply. An auto-reply sent outside the contact’s sending hours waits as
pendinguntil they open. The one thing allowed to answer straight away outside sending hours is the built-in after-hours auto-reply workflow; use it for “we’re closed” replies instead of building your own. - Missed webhooks. If your endpoint is down for longer than the ~37-minute retry window, those events are gone. Recover from downtime lists the messages you missed with
GET /v1/messagesand runs them through the same de-duplication. - Groups. The sample replies into groups too. Many integrations prefer to auto-reply only in
one_to_oneconversations: return early whenconversation_kindis"group".
Next
Signature verification
The
verifySignature used above, with a test vector.Test webhooks locally
Run this receiver on your laptop with a tunnel.
Retries and deduplication
The retry schedule and why events arrive twice or out of order.
Webhook events
Every event type and its payload.

