How inbound messages arrive
When a contact texts your number, Surge receives the message from the carrier and forwards it to your webhook endpoint as amessage.received event.
conversation.created event. Use that event to initialize a conversation record in your system.
Reply in the same thread
Reply into the same conversation by passing the conversation ID as theconversation field in your outbound message. Surge routes the reply from the same number the contact previously reached.
Handle opt-outs inline
When a contact replies STOP (or any recognized opt-out keyword), Surge firescontact.opted_out before the next inbound message arrives. Update your database and stop sending to that contact.
Surge automatically blocks sends to opted-out contacts — you’ll get an
opted_out error if you try. Tracking the state in your own system is still good practice so you don’t attempt sends unnecessarily.Common setup failures
No inbound messages arriving:- Verify your webhook URL is saved in Settings → Webhooks in the dashboard
- Confirm the URL is publicly accessible (not localhost or behind a firewall)
- Check that your endpoint returns
2xxwithin the timeout. If it returns 4xx or 5xx, Surge retries but logs the failure - Look at the webhook delivery logs in the dashboard for error details
- Confirm the conversation ID you’re replying to matches the one from the event
- Check that the phone number associated with the conversation is still active and attached to an approved campaign
Handling concurrent inbound messages
If your system creates records on inbound messages and a burst of messages arrives simultaneously, you may see duplicate conversation records. Use the
conversation.id from the webhook event (not the contact phone number) as your primary key for deduplication. Surge guarantees a single conversation ID per thread.