IOSOR Learn
Inbound SMS webhooks: retries, event order, and idempotency on receive
A build guide for B2B teams handling inbound SMS: why retries happen, why event order is not guaranteed, and how to make your receive endpoint idempotent instead of duplicating conversations and STOP handling.
Every inbound message handler eventually meets the same three surprises: the same webhook fires twice, a "delivered" event arrives after the "failed" one it superseded, and a customer's STOP reply gets processed twice because two servers picked up the same retry. None of these are bugs in the platform sending you the webhook — they are the normal behavior of any at-least-once delivery system, and your receive endpoint has to be built for that reality from day one.
IOSOR delivers inbound SMS, STOP/HELP keywords, and delivery events as white-label prepaid webhooks — the retry and ordering behavior below is what any serious B2B integration should assume regardless of which platform sits behind it.
Why webhooks retry at all
A webhook platforms cannot know for certain that your endpoint processed a delivery. Your server might return a 200 after committing to a database that then rolls back; a load balancer might drop the response on the way back even though your handler succeeded; a deploy might restart your process mid-request. Because "silently lose the event" is worse than "occasionally send it twice," every serious webhook system chooses at-least-once delivery: it retries on timeout, on 5xx, and often on ambiguous network errors, accepting that duplicates will happen.
The three failure modes you must design for
| Failure mode | What happens | What breaks if you ignore it |
|---|---|---|
| Duplicate delivery | Same event ID arrives 2+ times | Double-counted replies, doubled STOP processing, duplicate conversation threads |
| Out-of-order events | A later-timestamped event arrives before an earlier one | A "delivered" status gets overwritten back to "sent" |
| Partial/ambiguous failure | Your handler processed the event but the ack was lost | platforms retries something you already did |
Idempotency: the one property that fixes all three
An idempotent receive endpoint produces the same end state no matter how many times the same event is delivered. The mechanism is simple and well-understood: every inbound event carries a unique event ID; before processing, you check whether you've already recorded that ID; if you have, you return success immediately without reprocessing. 1.
Event ordering: why "last write wins" is dangerous
Webhook events for the same message are not guaranteed to arrive in the order they occurred.
Red flags
- No unique event ID in the webhook payload, or your integration ignores the one that's there
- Status updates applied with a plain overwrite and no timestamp comparison
- STOP handling that isn't behind the same dedupe logic as regular inbound messages
- Webhook handler doing synchronous downstream calls (email, CRM, agent routing) before acknowledging
- No logs showing how many duplicate event IDs arrived last month — meaning nobody is watching
Start with IOSOR
Pull last week’s inbound webhook logs and count event IDs that arrived more than once. Replay one duplicate and one out-of-order pair (failed, then delivered). The receiver must keep one effect: one inbox row, one STOP write, one wallet touch. Last-write-wins that undoes STOP fails this job. This is receive-side idempotency and retry order, not signature validation and not a gateway lock before the queue.
Related: inbound auto-reply loops · Buffer Inbound Webhook Processing Against Carrier Latency Spikes · Prepaid hold before first debit.
IOSOR takeaway
Inbound webhooks retry. Idempotency on receive is the only safe answer; order is not a promise.
Do: key the event and ignore the twin. Don't: apply last-write-wins to STOP or debit the same event twice.
Was this guide helpful?
Related guides
- Configuring Inbound Voice Missed Call Fallback to SMS Triggers
Set up automated missed call text follow-ups on your white-label telecom platform to capture leads instantly when voice routes fail.
- Buffer Inbound Webhook Processing Against Carrier Latency Spikes
Configure IOSOR white-label CPaaS queue buffers to prevent downstream application timeouts during high-volume carrier delivery delays and batch spikes.
- Synchronizing Inbound Opt-Out Keywords Across Multi-Tenant Accounts
Master multi-tenant opt-out synchronization in IOSOR. Learn how inbound stop keywords manage global suppressions while isolating sub-accounts.