Receiving SMS

Learn how to handle inbound SMS messages and replies.

Inbound Messages

When someone replies to your SMS messages, the reply is captured and stored. You can access inbound messages via API or webhooks.

Viewing Inbound Messages

Using TypeScript SDK

// List recent inbound messages
const inbound = await client.sms.listInbound({
  count: 50,
});
 
for (const message of inbound.messages) {
  console.log(`From: ${message.from}`);
  console.log(`To: ${message.to}`);
  console.log(`Body: ${message.body}`);
  console.log(`Received: ${message.receivedAt}`);
}

Using cURL

curl "https://api.usetransactional.com/v1/sms/inbound?count=50" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "totalCount": 50,
  "messages": [
    {
      "messageId": "sms_inb_abc123",
      "from": "+14155551234",
      "to": "+18005551234",
      "body": "Thanks for the update!",
      "receivedAt": "2024-01-01T12:30:00.000Z"
    },
    {
      "messageId": "sms_inb_def456",
      "from": "+14155555678",
      "to": "+18005551234",
      "body": "STOP",
      "receivedAt": "2024-01-01T12:25:00.000Z"
    }
  ]
}

Filtering Inbound Messages

By Sender Number

const messages = await client.sms.listInbound({
  fromNumber: '+14155551234',
});

By Receiving Number

const messages = await client.sms.listInbound({
  toNumber: '+18005551234',
});

By Date Range

const messages = await client.sms.listInbound({
  fromDate: '2024-01-01T00:00:00Z',
  toDate: '2024-01-31T23:59:59Z',
});

Webhook Notifications

For real-time notifications, set up webhooks to receive inbound messages instantly.

Setting Up Webhooks

  1. Go to SMS > Webhooks in your dashboard
  2. Click Add Webhook
  3. Enter your endpoint URL
  4. Select the sms.inbound event
  5. Save the webhook

Webhook Payload

{
  "event": "sms.inbound",
  "timestamp": "2024-01-01T12:30:00.000Z",
  "data": {
    "messageId": "sms_inb_abc123",
    "from": "+14155551234",
    "to": "+18005551234",
    "body": "Thanks for the update!",
    "receivedAt": "2024-01-01T12:30:00.000Z",
    "providerMessageId": "SM12345"
  }
}

Processing Inbound Webhooks

// Express.js example
app.post('/webhooks/sms', (req, res) => {
  const { event, data } = req.body;
 
  if (event === 'sms.inbound') {
    console.log(`Received SMS from ${data.from}: ${data.body}`);
 
    // Process the message
    handleInboundSms(data);
  }
 
  res.status(200).send('OK');
});

Automatic Opt-Out Handling

We automatically process standard opt-out keywords:

KeywordAction
STOPAdd to suppression list
UNSUBSCRIBEAdd to suppression list
CANCELAdd to suppression list
ENDAdd to suppression list
QUITAdd to suppression list

When a user sends one of these keywords:

  1. They are added to your suppression list
  2. Future messages to this number will be blocked
  3. A confirmation message is sent automatically

Opt-In Keywords

Users can opt back in with:

KeywordAction
STARTRemove from suppression list
YESRemove from suppression list
UNSTOPRemove from suppression list

Custom Keyword Handling

Beyond opt-out keywords, you can process custom keywords:

app.post('/webhooks/sms', (req, res) => {
  const { event, data } = req.body;
 
  if (event === 'sms.inbound') {
    const body = data.body.toUpperCase().trim();
 
    switch (body) {
      case 'HELP':
        // Send help information
        sendHelpMessage(data.from);
        break;
      case 'STATUS':
        // Send order status
        sendOrderStatus(data.from);
        break;
      case 'BALANCE':
        // Send account balance
        sendAccountBalance(data.from);
        break;
      default:
        // Unknown command
        sendUnknownCommandResponse(data.from);
    }
  }
 
  res.status(200).send('OK');
});

Two-Way Conversations

For conversational use cases, you can build two-way SMS flows:

async function handleInboundSms(data: InboundSms) {
  const { from, body } = data;
 
  // Get conversation context
  const context = await getConversationContext(from);
 
  // Process based on conversation state
  let response;
  switch (context.state) {
    case 'awaiting_confirmation':
      if (body.toUpperCase() === 'YES') {
        response = 'Great! Your order has been confirmed.';
        await confirmOrder(context.orderId);
      } else if (body.toUpperCase() === 'NO') {
        response = 'Order cancelled. Let us know if you need help.';
        await cancelOrder(context.orderId);
      }
      break;
 
    case 'awaiting_feedback':
      response = 'Thanks for your feedback!';
      await saveFeedback(from, body);
      break;
 
    default:
      response = 'Reply HELP for assistance.';
  }
 
  // Send response
  await client.sms.send({
    to: from,
    templateAlias: 'generic-response',
    templateModel: { message: response },
  });
}

Best Practices

1. Respond Promptly

Users expect quick responses to SMS. Process inbound messages and respond within seconds when possible.

2. Always Handle HELP

Provide a HELP keyword that explains available commands:

Reply with:
STOP - Unsubscribe
STATUS - Check order status
HELP - Show this message

3. Confirm Important Actions

For critical actions, ask for confirmation:

You're about to cancel order #123. Reply YES to confirm or NO to keep the order.

4. Use Webhooks for Real-Time

The API is great for batch processing, but webhooks provide instant notifications for time-sensitive conversations.

Next Steps