Receiving SMS and MMS

Receive incoming messages, access MMS attachments, and send automatic replies using TextGrid webhooks

Receive incoming SMS and MMS messages at your application's webhook endpoint, read message text and media, and optionally send an automatic reply.

1. Configure your receiving endpoint

Use a TextGrid phone number with the messaging capabilities you need. You can configure its callbacks when purchasing the number or update them later:

POST https://api.textgrid.com/2010-04-01/Accounts/YOUR_ACCOUNT_SID/IncomingPhoneNumbers/YOUR_PHONE_NUMBER_SID.json
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer YOUR_BASE64_ENCODED_CREDENTIALS

Supply these form fields:

FieldExample value
smsUrlhttps://example.com/webhooks/incoming-messages
smsMethodPOST

Use your own public endpoint in place of the fictitious URL. smsMethod defaults to POST and also supports GET. See Managing Phone Numbers for configuration and authentication details.

2. Verify the incoming request

Before processing a message, verify the X-TextGrid-Signature header using your account's Webhook Secret. This is separate from your API Auth Token.

For POST, capture the unchanged raw request body before parsing form fields. For GET, preserve the exact public request URL, including its encoded query string.

See Verifying Webhook Signatures for the complete algorithm and code samples.

3. Read the message fields

TextGrid sends POST callbacks as application/x-www-form-urlencoded, not JSON. If you configure GET, read the fields from query parameters instead.

Common fields include:

FieldDescription
MessageSidMessage identifier. Save it to identify the message and detect duplicates.
SmsMessageSid, SmsSidAdditional message identifier fields in the callback.
AccountSidAccount receiving the message.
FromSender's phone number.
ToYour receiving TextGrid phone number.
BodyMessage text. It can be empty for a media-only message.
SmsStatusreceived.
NumMediaNumber of media attachments.
NumSegmentsMessage segment count.
ApiVersion2010-04-01.

Query and form values arrive as text; parse count fields as integers after signature verification. Keep phone numbers and identifiers as strings. Null fields can be omitted.

An incoming-message callback is distinct from an outgoing delivery-status callback. Use separate endpoints or route the events appropriately. See Messaging Webhooks for both contracts.

4. Read MMS attachments

When media is present, the callback includes zero-based field pairs:

FieldDescription
MediaUrl0URL for the first attachment.
MediaContentType0Content type of the first attachment.
MediaUrl1URL for the second attachment, when present.
MediaContentType1Content type of the second attachment, when present.

Read NumMedia, then process the matching MediaUrlN and MediaContentTypeN fields for each attachment. Do not assume an MMS contains only one attachment or that Body contains text.

The callback supplies media URLs, not inline Base64 file content. Retrieve and process media separately from the initial webhook acknowledgment so lengthy processing does not delay your response.

5. Acknowledge without replying

To acknowledge the message without sending an automatic reply, return HTTP 200 with Content-Type: application/xml and:

<?xml version="1.0" encoding="UTF-8"?>
<Response />

An empty successful response also produces no automatic reply. Incoming-message acknowledgments accept HTTP 200, 201, 202, or 204; use 200 when returning TwiML content.

Save or durably queue the message before acknowledging it, then perform longer processing separately.

6. Send an automatic reply

To reply immediately, return HTTP 200 with Content-Type: application/xml and a messaging TwiML response:

<?xml version="1.0" encoding="UTF-8"?>
<Response>
  <Message>
    <Body>Thanks for your message. Our team will respond shortly.</Body>
  </Message>
</Response>

Escape dynamic text correctly for XML, including characters such as & and <.

The reply is an outgoing message, so applicable sending eligibility and charges still apply. Returning TwiML does not confirm that the reply was delivered.

If you need to reply later, acknowledge the webhook without an automatic reply and send the message separately through the API. See Sending SMS and MMS. Avoid sending the same reply through both paths.

Handle opt-outs and subscription keywords

With standard keyword handling enabled, TextGrid processes opt-out and resubscription keywords and can send automatic confirmations. Keyword messages will still reach your incoming-message webhook. Record the recipient's preference and acknowledge the callback without returning a generic automatic reply for these messages.

TextGrid recognizes STOP, STOP!, STOPALL, UNSUBSCRIBE, END, QUIT, and QUIT! for opt-out; START and UNSTOP for resubscription; and HELP for help. Matching ignores letter case and surrounding whitespace and checks the entire message, not words within a longer sentence.

Automatic confirmation text and handling depend on account settings. If TextGrid has already sent an automatic response, it does not process your webhook's reply TwiML for that request. Do not rely on that suppression to prevent a separate API send from your application.

Handle duplicate callbacks and failures

Make message processing idempotent. Store MessageSid with the receiving account so that receiving the same message again does not repeat business actions or send another automatic reply. For an already processed message, acknowledge it without repeating the reply TwiML.

The primary incoming-message request is attempted at most twice. A retry occurs only for a transport result with status code zero, with a one-second delay. A nonzero HTTP response stops that retry loop, including an HTTP error response. Do not rely on returning HTTP 500 to trigger another primary attempt.

If delivery is unsuccessful and no automatic reply was already sent, TextGrid can invoke a configured smsFallbackUrl once. Configure smsFallbackMethod to match that endpoint. This behavior applies to incoming messages; outgoing delivery-status notifications have different delivery behavior.

The incoming-message timeout defaults to 15 seconds and can be configured. Respond promptly and do not rely on exactly-once delivery or unlimited retries.

Test your integration

Send an SMS to your TextGrid number and confirm that your endpoint verifies the signature, records the message, and returns the intended acknowledgment or reply.

Then test an MMS with media and a duplicate callback. Confirm that media fields are handled correctly and duplicate processing does not create another reply or repeat other side effects.


Did this page help you?