Skip to main content
When the same person sends and receives multiple messages over time, Surge tracks them as a conversation thread. Understanding how conversations and contacts work helps you build two-way messaging flows, surface message history, and manage opt-out state correctly.

Contacts and conversations

A contact represents a phone number in the context of a specific account. When someone messages your number for the first time, or when you first message them, Surge creates a contact record and a conversation thread. A conversation is the thread of all messages between your number and a contact. Every message you send or receive includes a conversation.id in the response.

When to use contacts vs raw messaging

Raw messaging (passing a phone number directly in the to field) is fine for simple one-way notifications where you don’t need to track who sent what or manage opt-out state per person. Blast sends work this way. Contacts become useful when:
  • You’re building two-way messaging and need to correlate inbound replies with specific customers
  • You need to check or manage opt-out state for an individual
  • You want to associate metadata (name, account ID in your system) with a phone number
  • You’re building embeddable UI components that need to show a contact’s message history
Create a contact explicitly to attach metadata before the first message:
Contacts support these fields: phone_number (required), first_name, last_name, email, date_of_birth, and metadata.
All contact PII is encrypted at rest. first_name, last_name, email, date_of_birth, phone_number, and metadata are stored encrypted in the database. You can safely store customer-identifying information here without it being readable if the database is compromised.
Surge also automatically populates carrier data (phone_carrier, phone_carrier_name, phone_country) on contacts based on carrier lookups. This data is populated asynchronously after the first message send or verification — it is not available at contact creation time.

Following a conversation

When a contact sends you an inbound message, the message.received webhook event includes the conversation ID. Use that ID to fetch the full thread or send a reply into the same conversation.
When you send into a conversation, Surge routes the message from the same number the contact previously reached.

Conversation status

A conversation has one of three statuses: The opted_out_at timestamp is set when the conversation moves to opted_out status.

Opt-out state

Opt-out state lives on the conversation (one contact might opt out of one number but remain active on another). When a contact replies STOP, the conversation.opted_out_at timestamp is set and the contact.opted_out webhook event fires. Sending to an opted-out conversation returns an opted_out error.
Do not attempt to send around opt-outs. Doing so violates carrier policies and can result in your campaign being deactivated.
A contact re-opts in by texting START, YES, or UNSTOP to the same number. When that happens, contact.opted_in fires and the conversation status returns to active.

Audiences

If you want to group contacts into named lists for repeated sends, use audiences. An audience is a collection of contacts that you blast together. See Send to Many People for the full pattern.

Cross-channel tracking (roadmap)

Conversations and contacts today are SMS-specific. As Surge adds RCS, WhatsApp, and other channels, the contact model will extend to track communication history across all channels in a single thread. See Channels Roadmap.