Skip to main content
Two-way messaging means your application can both send messages to users and receive replies from them. Here’s how to set it up and handle the common failure modes.

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 a message.received event.
The first time a contact messages your number, Surge also fires a 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 the conversation 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 fires contact.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:
  1. Verify your webhook URL is saved in Settings → Webhooks in the dashboard
  2. Confirm the URL is publicly accessible (not localhost or behind a firewall)
  3. Check that your endpoint returns 2xx within the timeout. If it returns 4xx or 5xx, Surge retries but logs the failure
  4. Look at the webhook delivery logs in the dashboard for error details
Inbound messages arriving but replies not delivering:
  1. Confirm the conversation ID you’re replying to matches the one from the event
  2. Check that the phone number associated with the conversation is still active and attached to an approved campaign
Duplicate event delivery: Surge retries failed webhook deliveries, which means your handler may receive the same event more than once. Make your handler idempotent — use the message ID as a deduplication key before processing.

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.