Relaying voice texts through your own SMS provider

A Voice AI Agent texts callers during a call. By default, those text messages leave from the Twilio number configured for your AI Agent. This guide shows how to send them through your own SMS provider and phone number instead, and how to bring the caller’s text reply back into the live call.

A Conversations API channel with the sms modality carries the text messages. Your relay sends each one with your own SMS provider. When the caller replies by text, your relay posts the reply to Ada, and the AI Agent answers by voice on the call.

Your relay is a service you run. It receives each of the AI Agent’s text messages from Ada as a webhook and sends it through your SMS provider. It receives the caller’s reply from your provider and posts it to Ada.

The flow during a call:

  1. The caller talks to the AI Agent on the call.
  2. The AI Agent sends a text message. Ada publishes it to your relay as a v1.conversation.message webhook.
  3. Your relay sends the text message to the caller through your provider.
  4. The caller replies by text. Your provider delivers the reply to your relay.
  5. Your relay posts the reply to Ada with the Accept the caller’s SMS reply endpoint.
  6. The AI Agent answers by voice on the call.

Ada cannot confirm delivery of a text message on this channel. Your provider holds the delivery record. Ada receives the caller’s texts only when your relay posts them. If the caller replies STOP, handle the opt-out in your relay and do not post it as a reply. Carrier registration and compliance for your number are yours.

Before you start

You need an API key and a webhook endpoint. If you have not built a Conversations API integration before, read Creating a custom channel first. It covers API keys, webhook endpoints, and signing secrets.

The Use your own SMS channel toggle in the Ada dashboard controls this feature. It is under Config > CHANNELS > Voice > Configuration. While the toggle is off, the AI Agent sends its text messages from the Twilio number configured for your AI Agent.

The toggle appears only while Allow AI Agent to send and receive SMS is enabled. You can turn it on only after the SMS channel exists. See Send texts from your own SMS channel.

Ada’s APIs include rate limits. Handle HTTP 429 Too Many Requests responses with retry logic. See Conversations API rate limits.

Create the SMS channel

Set "modality": "sms" on the Create a new channel request:

http
POST https://<handle>.ada.support/api/v2/channels
Authorization: Bearer <your-api-key>
Content-Type: application/json
{
"name": "My SMS Provider",
"description": "Relays the AI Agent's voice text messages through our own carrier",
"modality": "sms"
}

Create this channel once. You cannot delete a channel or change its modality. If a second SMS channel exists, Ada keeps using the first.

Subscribe your endpoint

Subscribe an endpoint to v1.conversation.message before you turn on Use your own SMS channel. Scope that endpoint to the new channel ID with channel filtering. Ada tags every event from this channel with the channel ID.

If the toggle is on and no enabled endpoint subscribes to v1.conversation.message, Ada drops the text message. Ada does not send it from the Twilio number instead.

Ada checks only that an enabled endpoint subscribes to the event type. It does not read the endpoint’s Channels field. If every subscribed endpoint is scoped to other channel IDs, Ada still publishes the event, and channel filtering delivers it to no endpoint. The caller does not receive the text message. If you set the Channels field, include the SMS channel ID.

What your relay receives

Ada sends one v1.conversation.message webhook for each text message. data.channel is an object. Its id is the ID that Create a new channel returned, and its modality is sms.

A text message with no image arrives with content.type set to text:

json
"content": {
"type": "text",
"body": "Your order ships today. Track it at https://example.com/track"
}

A text message with an image arrives with content.type set to link. The url field holds the image. The link_text field holds the caption:

json
"content": {
"type": "link",
"url": "https://example.com/media/receipt.png",
"link_text": "Here is your receipt."
}

Map url to your provider’s media parameter. Map link_text to your provider’s message body.

Ada publishes each text message as one body. It does not split a long text message into SMS segments. Your relay handles segmentation for a text message longer than one SMS.

An endpoint scoped to your SMS channel receives the AI Agent’s text messages only. It does not receive the caller’s spoken turns or any other event from the call. When the call ends, the 400 response to a reply is your relay’s only signal.

Resolve the recipient

The payload carries no phone number. Read the caller’s number from the end user:

  1. Take data.end_user_id from the webhook payload.
  2. Call Get an end user.
  3. Read profile.metadata.phone_number.

Send the text message to that number. If the end user has no profile.metadata.phone_number, Ada drops the text message. Ada does not send it from the Twilio number instead.

This channel can send text messages to the caller only. If the AI Agent names another number, Ada drops the text message. Ada does not redirect it to the caller.

Ada cannot confirm delivery

Your 2xx response to the webhook is the last thing Ada observes. Ada has no endpoint for a delivery receipt.

  • When Ada sends a text message from the Twilio number, Ada receives a delivery status. With this channel, Ada receives none.
  • Report delivery and failure in your own relay. Keep data.message_id to match each text message to your provider’s own record.

Accept the caller’s reply

The caller can reply to a text message during the call. Your provider delivers the reply to your relay. Your relay then posts the reply to the Accept the caller’s SMS reply endpoint. The reply becomes the caller’s next turn. The AI Agent answers by voice on the live call.

Post each reply as soon as your provider delivers it. The caller is on the live call while your relay works. If the caller stays silent, the AI Agent ends the call after the caller silence limit. That limit is your relay’s time budget.

If the caller replies STOP, handle the opt-out in your relay. Do not post STOP as a reply, or the AI Agent treats it as the caller’s answer.

Ada accepts a reply only when all of these conditions are true:

  • The conversation is a voice call.
  • Use your own SMS channel is turned on for your AI Agent.
  • Your AI Agent has an SMS channel.
  • The AI Agent has already sent a text message on this conversation over that channel.
  • The call is still live.
  • author.id is the caller’s end user ID.

What to include in the request

The request body has the same shape as Create a new message. Read the IDs from the v1.conversation.message webhook that carried the AI Agent’s text message:

  • Path conversation_id: Read it from data.conversation_id.
  • author.role: Set it to end_user.
  • author.id: The caller’s end user ID. Read it from data.end_user_id.
  • content.type: Set it to text.
  • content.body: The text the caller sent.

Replace <handle>, <conversation_id>, <your-api-key>, and <end_user_id> with your actual values.

http
POST https://<handle>.ada.support/api/v2/conversations/<conversation_id>/sms/
Authorization: Bearer <your-api-key>
Content-Type: application/json
{
"author": {
"role": "end_user",
"id": "<end_user_id>"
},
"content": {
"type": "text",
"body": "ABC123"
}
}

What Ada returns

When Ada accepts the reply, it returns 201 with the message. The content.body in the response is the text exactly as your relay sent it.

json
{
"id": "6789abcd1234ef567890",
"conversation_id": "5df263b7db5a7e6ea03fae9b",
...
}

Example abbreviated for clarity. See the full response here.

Ada does not publish the reply as a v1.conversation.message event. Your relay already has the text.

Ada stores the reply on the conversation. Get conversation messages returns it as an end_user text message. When the AI Agent answered the reply itself, the stored content.body starts with sms:. When a Process captured the reply as an input, the body is the bare text. The endpoint does not return the AI Agent’s own text messages. If you need a text message later, keep the webhook payload.

Ada does not detect a repeated reply. If your relay posts the same reply twice, the AI Agent answers twice. Retry a reply only after a 429 or a 503 response. When Ada returns either response, it does not store the reply. If the request times out with no response, do not retry. Ada may have accepted the reply.

When Ada refuses a reply

Ada does not store a refused reply, and the AI Agent does not answer it. Ada returns the standard error body:

json
{
"errors": [
{
"type": "bad_request",
"message": "The call has ended, so this conversation no longer accepts SMS replies.",
"details": null
}
]
}

Fix the request. Ada refused the request itself. Correct it, then post the reply again.

StatusmessageWhat to do
400Only end user messages are accepted as SMS repliesSet author.role to end_user.
400Only text messages are accepted as SMS repliesSet content.type to text.
400content.body must not be emptySend the text the caller wrote, not an empty body.
400invalid message data, type validation_errorKeep the text to 10,000 characters or fewer.
400Request body validation error, type validation_errorFix the field that details names. See Errors.
400Invalid path parameter: conversation_id, type validation_errorSend the conversation ID from data.conversation_id.
400author.id is required for end user messages or author.id is invalidSend the end user ID from data.end_user_id.
400author.id is not the caller on this conversationSend the end user ID from data.end_user_id.
404Conversation with id <conversation_id> not foundCheck the conversation ID.
404... with end_user_id <end_user_id> not found, type resource_not_foundSend the end user ID from data.end_user_id. Your AI Agent has no end user with this ID.
422SMS replies can only be added to voice conversationsCheck the conversation ID. The conversation is not a voice call.
422SMS replies are not enabled for this AI Agent.Create an SMS channel.
422This AI Agent is not set to use its own SMS channel.Turn on Use your own SMS channel in Config > CHANNELS > Voice > Configuration.

Stop. The call cannot take this reply. Do not post it again.

StatusmessageWhy
400The call has ended, so this conversation no longer accepts SMS replies.The call is over.
400Message dropped: conversation exceeds message limitThe conversation has more messages than Ada allows.
422The AI Agent has not sent an SMS on this conversation, so there is nothing to reply to.The AI Agent has not texted on this call. Do not forward the text.

Retry. Ada did not store the reply. Post it again later.

StatusmessageWhat to do
429429 Too Many Requests: <limit>, type rate_limit_exceededWait, then retry. See Conversations API rate limits.
503The SMS channel could not be resolved. Retry the request.Retry later.

Test the relay

Use a test AI Agent before you turn the toggle on for a live one.

  1. Create the SMS channel. Subscribe an endpoint to v1.conversation.message, scoped to the channel ID.
  2. Turn on Use your own SMS channel in Config > CHANNELS > Voice > Configuration.
  3. Call the test AI Agent and trigger a Speech and SMS capture. See Voice call capture options.
  4. Confirm that your relay receives the webhook and that the text message arrives on your phone.
  5. Reply by text. Confirm that your relay posts the reply and receives 201, and that the AI Agent answers by voice on the call.

Important notes

  • Ada sends each text message as its own webhook, so two text messages in one turn can arrive out of order. Sort the events by data.created_at.
  • Ada retries a webhook your relay does not accept, so the same text message can arrive twice. Drop a repeated data.message_id.
  • The AI Agent still speaks to the caller on the voice channel. This channel carries the text messages only.
  • When the AI Agent ends the call, it can send the CSAT survey link as a text message. That text message also goes over this channel.
  • The Allow AI Agent to send and receive SMS toggle controls whether the AI Agent can text at all. While it is disabled, the AI Agent sends no text messages over this channel or from the Twilio number. See Control whether your AI Agent can send SMS.
  • To send text messages from the Twilio number again, turn off Use your own SMS channel. Ada then refuses SMS replies with 422. A change to the toggle takes effect within a minute, and it can apply to a call that is in progress.