BUILT FOR YOUR APPLICATION

# SMS API. Right on time.

Send updates and reminders, receive replies, and track delivery with the Bird SMS API. Build messaging into your application with a few lines of code.

[Start now](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Fsms%2Fonboarding)

[Talk to sales](/demo?product=sms)

[See the code ↓](#implementation)

[Check your destination ↗](/products/sms/destinations)

## Preview an SMS customer experience

Write a reminder and see it in a native text-message conversation. Try the emoji example to see how Unicode changes the estimated segment count. The browser demo is an illustration: it makes no API request and sends no message.

Follow an illustrative delivery, permanent failure, reply or pending outcome in the [message inspector](/sms-api#experience). A carrier delivery receipt does not establish that someone read the message. Replies need a supported two-way sender, and your application owns changes to the customer's booking.

[Run your first SMS](/docs/get-started/send-your-first-sms) · [SMS segment calculator](/tools/sms-segment-calculator)

Companies that trust Bird across their communications.

- [Airwallex](/customers/airwallex)
- Uber
- [Zillow](/customers/zillow)
- [Glovo](/customers/glovo)
- PayPal
- Adobe

30 — New countries for SMS in two months

Reported by Airwallex in its customer story on international SMS expansion.

[Read Airwallex’s story](/customers/airwallex)

WHAT IT MEANS FOR YOUR CUSTOMER

## A small message. A much better day.

Keep the customer close to what is happening. From the first confirmation to the last delivery update, make every message earn its place.

01 / Keep them informed

### The order is on its way.

A timely update answers the question before your customer has to ask it.

[Transactional SMS ↗](/sms-api)

02 / Make the next step easy

### A reminder, with a reason.

Bring the appointment or collection back into view. For sign-in codes and account recovery, use a verification flow.

[Verification flows ↗](/verification-api)

03 / Keep the conversation going

### A reply that reaches you.

Where your sender supports replies, bring the answer into the application or team that can help.

[Two-way SMS ↗](/products/sms/two-way)

READY WHEN YOU ARE

## Start with a controlled test.

[Start now](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Fsms%2Fonboarding)

[Talk to sales](/demo?product=sms)

01

[Create your account ↗ Create a workspace and server-side API key for its region.](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Fsms%2Fonboarding)

02

[Check destination and sender ↗ Enable each country, then check sender registration and two-way support for the message category.](/products/sms/destinations)

03

[Send and follow ↗ Use a sandbox recipient first. Then verify delivery and replies with an eligible production sender.](/docs/guides/sms/sending-sms)

SMS API / FOR DEVELOPERS

## From your code to their phone.

Use the REST API, an SDK or the CLI. Send one message, keep its ID and follow delivery through signed webhook events. Your API key stays on your server.

Send with bird sms send or the sms_send MCP tool, then inspect the message and its delivery events. Keep the message ID to reconcile an uncertain result.

[CLI send reference ↗](/docs/cli/reference/sms-send)

[Connect an MCP client ↗](/ai/mcp-client)

### Node.js

```ts
const msg = await bird.sms.send({
  from: "+15557654321",
  to: "+14155550100",
  text: "Your verification code is 123456.",
  category: "authentication",
});
console.log(msg.id, msg.status);
```

### Python

```py
msg = client.sms.send(
    from_="+15557654321",
    to="+15551234567",
    text="Your verification code is 123456.",
    category="authentication",
)
print(msg.id, msg.status)
```

### Go

```go
msg, err := client.Sms.Send(context.Background(), bird.SmsSendParams{
	From:     "+15557654321",
	To:       "+15551234567",
	Text:     "Your verification code is 123456.",
	Category: bird.SMSCategoryAuthentication,
})
if err != nil {
	log.Fatal(err)
}
fmt.Println(msg.Id, *msg.Status)
```

### PHP

```php
$message = $bird->sms->send(
    from: '+15557654321',
    to: '+15551234567',
    text: 'Your verification code is 123456.',
    category: 'authentication',
);
echo $message->getId(), ' ', $message->getStatus();
```

### CLI

```sh
bird sms send --body-file - <<'JSON'
{
  "to": "+14155550100",
  "from": "+15557654321",
  "text": "Your verification code is 123456.",
  "category": "authentication",
  "options": {
    "smart_encoding": true
  },
  "tags": [
    {
      "name": "campaign",
      "value": "signup"
    }
  ],
  "metadata": {
    "user_id": "usr_12345"
  }
}
JSON
```

### MCP

```json
{
  "name": "sms_send",
  "arguments": {
    "category": "authentication",
    "from": "+15557654321",
    "metadata": {
      "user_id": "usr_12345"
    },
    "options": {
      "smart_encoding": true
    },
    "tags": [
      {
        "name": "campaign",
        "value": "signup"
      }
    ],
    "text": "Your verification code is 123456.",
    "to": "+14155550100"
  }
}
```

### cURL

```sh
curl -X POST "https://us1.platform.bird.com/v1/sms/messages" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155550100",
    "from": "+15557654321",
    "text": "Your verification code is 123456.",
    "category": "authentication",
    "options": {
      "smart_encoding": true
    },
    "tags": [
      {
        "name": "campaign",
        "value": "signup"
      }
    ],
    "metadata": {
      "user_id": "usr_12345"
    }
  }'
```

[Run your first SMS ↗](/docs/get-started/send-your-first-sms)

[Send endpoint reference ↗](/docs/api/reference/create-sms-message)

## Send your first request before you write any code.

[The whole public API as a Postman collection](https://god.gw.postman.com/run-collection/20940851-8026901b-b1c8-4490-a3e6-b755bfbed32a?action=collection%2Ffork): every endpoint with an example request and response, converted from the same OpenAPI specification the SDKs are generated from. Fork it into your own workspace, set an API key, and send a live request.

Use a key for your workspace region, enable the destination and prepare an eligible sender. Recipient +15005550006 simulates delivery. These sends use normal credentials, are billed and still require an eligible sender. [Simulated SMS destinations ↗](/docs/guides/sms/migrate#6-test-against-simulated-destinations)

[Node.js SDK ↗](/docs/sdks/typescript)

[Python SDK ↗](/docs/sdks/python)

[Go SDK ↗](/docs/sdks/go)

[PHP SDK ↗](/docs/sdks/php)

### Inspect segments, batches and signed events

### Inspect the accepted encoding and segment count

GSM-7 capacity is 160 units for one segment or 153 per multipart segment; Unicode capacity is 70 or 67 UTF-16 units. GSM extensions and surrogate pairs can consume two units. Inspect the accepted response, then price the applicable carrier and destination separately.

**segments.ts**

```typescript
const { data, error } = await bird.sms.send({
  from:     "Bird",
  to:       "+31612345678",
  text:     "Your code is 123456.",
  category: "authentication",
}).safe();
if (error) throw error;

console.log(data.segments);
// → { characters: 20, count: 1, encoding: "GSM_7BIT" }
```

### Batch independent messages

Batch up to 100 messages. Invalid input rejects the request before enqueueing. After a 202 response, individual messages can succeed or fail separately. Use one idempotency key per logical request and reuse it for an identical retry within the documented retention window.

**reminders.ts**

```typescript
const { data: batch, error } = await bird.sms
  .sendBatch(
    users.map((u) => ({
      from: "Bird",
      to:   u.phone,
      text: `Hi ${u.name}, your appointment is tomorrow at ${u.time}.`,
    })),
    { idempotencyKey: `reminders-${runId}` },
  )
  .safe();

if (error) throw error;
console.log(`queued ${batch.data.length} messages`);
```

### Follow acceptance through the reported outcome

A 202 response records acceptance. Charging and carrier submission happen later and can still fail. Verify webhook signatures, deduplicate by webhook-id and use the event timestamp when events arrive out of order.

Accepted by the API and queued for carrier handoff.

Submitted to the destination carrier.

Carrier delivery receipt received.

Refused during processing, before delivery was attempted.

The carrier reported non-delivery or stopped trying.

Terminal failure for this attempt; inspect the reason and timeline.

**app/api/webhooks/bird/route.ts**

```typescript
import { bird } from "@/lib/bird";

export async function POST(req: Request) {
  const event = bird.webhooks.unwrap(
    await req.text(),
    Object.fromEntries(req.headers),
  );

  switch (event.type) {
    case "sms.delivered":
      await markDelivered(event.data.sms_id);
      break;
    case "sms.failed":
      await flag(event.data.to, event.data.error?.description);
      break;
  }

  return new Response(null, { status: 204 });
}
```

Supported STOP keywords and carrier opt-outs create suppressions. Other delivery failures do not automatically establish an opt-out.

[Webhook verification](/docs/guides/webhooks)

[Idempotency and retry window](/docs/guides/idempotency)

[Error reference](/docs/guides/errors)

### Map an existing sending integration

Map request fields, sender registrations and event handling. Reconcile opt-outs and compare a controlled test before changing production routing.

**twilio.ts**

```typescript
import twilio from "twilio";

const client = twilio(accountSid, authToken);

await client.messages.create({
  from: "+14155550172",
  to:   "+15005550006",
  body: "Your code is 123456.",
});
```

**bird.ts**

```typescript
import { BirdClient } from "@messagebird/sdk";

const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });

await bird.sms.send({
  from:     "+14155550172",
  to:       "+15005550006",
  text:     "Your code is 123456.",
  category: "authentication",
});
```

[Plan the migration ↗](/docs/guides/sms/migrate)

SMS / INTERNATIONAL EXPANSION

AIRWALLEX / CUSTOMER STORY

## Local requirements, with a path through.

Airwallex’s story describes how Bird helped its engineering team navigate country requirements, replacing lengthy forms and vendor back-and-forth with a shorter SMS onboarding process.

SMS deliverability

89.6% → 94.4%

Average country onboarding

About 7 days

[Read Airwallex’s story ↗](/customers/airwallex)

A reported customer result; outcomes vary.

## Follow an SMS outcome

The initial example illustrates a delivered SMS. Edit the draft, choose an outcome, then inspect it. Editing the draft or selecting another outcome clears the previous inspection. The browser estimate does not establish billing or send admission.

- Delivered: a carrier receipt is transport evidence; it does not confirm a read or booking.
- Permanent failure: inspect the error and sender/destination setup before a retry.
- Reply: correlate the inbound sender with the customer using a supported two-way number.
- Pending: no terminal event has been observed. Read the message and inspect its log before deciding what to do.

[Compose a message](/sms-api#pr-sms-message) · [Event contract](/docs/guides/sms/events) · [SMS log](/docs/guides/sms/sms-log)

READY FOR PRODUCTION

## A clear path into your next market.

SENDER & COUNTRY READINESS

### Build around the destinations you serve.

Start with the countries you serve. Check the destination allowlist, sender type, registration, reply support, and message category before following delivery events.

[Check country requirements ↗](/products/sms/destinations)

MIGRATION & SCALE

### Keep the customer journey intact.

Map numbers, sender IDs, callbacks and consent before switching. Plan a measured rollout with representative traffic and a rollback path.

[Plan the migration ↗](/docs/guides/sms/migrate)

### The details behind your setup

#### Choose the destination first.

Enable each country in your workspace allowlist, then check sender type, registration, reply support, and message category there. A US application long code follows 10DLC; an alphanumeric sender cannot receive replies.

#### Count segments, not just messages.

GSM-7 extension characters use two units; Unicode and multipart headers reduce capacity. The local composer estimates segments only. Bird rejects more than 12 segments; check current destination rates and carrier fees separately.

#### Keep consent and opt-outs connected.

Supported STOP keywords create sender-and-subscriber suppressions. Keep consent records, marketing permissions and suppression handling in your application’s sending flow.

[Opt-outs and keyword handling ↗](/docs/guides/sms/opt-outs-and-keywords)

SMS / PRICING

## The right reach. A clear cost.

Pay for the segments you send. Compare the destination and sender you need, then include carrier fees, number rental and registration in your rollout budget.

[Start now](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Fsms%2Fonboarding)

[Talk to sales](/demo?product=sms)

[See SMS rates ↗](/pricing/sms)

### Published pay-as-you-go rates

Outbound SMS, USD per segment.

| Destination | Sender | USD / segment |
| --- | --- | --- |
| United States | Long code | $0.0035 |
| United Kingdom | Alphanumeric | $0.050 |
| Netherlands | Alphanumeric | $0.085 |

Carrier fees, number rental and registration are additional. These examples are destination rates, not a worldwide price.

[All destinations and currencies](/pricing/sms) · [Carrier and registration fees](/pricing/sms/fees)

THE COMPLETE BIRD PLATFORM

## One booking. Keep the context.

Send the detailed receipt by email, the timely update by SMS, and handle a question on WhatsApp. Your application connects the steps around the same customer.

[f. Fieldnotes To: Alex Lee ⌄ 9:41 AM Your studio visit. All in one place. fieldnotes. BOOKING FN–1042 Your studio visit. All in one place. Alex Lee · Friday, 14:00 Clay workshop · One guest View your booking ↗](/email-api)

01

### [Email ↗](/email-api)

Alex receives the full receipt for booking FN–1042.

Today · 9:41

Your studio visit is tomorrow at 14:00. Booking FN–1042.

Thank you. See you there!

02

### SMS This step

The same booking becomes a timely reminder, with SMS permission.

[Today · 9:41 Can we move booking FN–1042 to Friday afternoon? I’ll check with the studio. Your booking details are here.](/whatsapp)

03

### [WhatsApp ↗](/whatsapp)

A question continues as a conversation. Your app preserves the booking context.

BUILD YOUR BIRD SETUP

A useful next connection.

[Verify ↗ Protect the next action Use a verification flow for signup or account recovery.](/verification-api)

[Lookup ↗ Check the destination Understand a phone number before choosing the next step.](/lookup)

[RCS ↗ Explore a richer message Discuss RCS reach and availability for your markets.](/rcs-business-messaging)

[eSIM & connectivity ↗ Connect the whole journey Bring onboarding and service updates around a mobile plan.](/esim)

Keep the confirmation, reminder, and reply around the same booking. Your application joins the context; Bird supplies the channels, so adding the next experience does not mean starting with another communications vendor.

[Plan your complete Bird setup ↗](/demo?product=sms)

LEARN / BUILD / OPERATE

## Go further with SMS.

[FIELD GUIDE The right sender. The right economics. A practical path through setup, implementation, and the choices that matter. Read the field guide →](/guides/plan-an-sms-integration)

[01 Compare SMS providers Evaluate sender support, delivery visibility and the cost of your actual traffic.](/products/sms/compare)

[02 Move from Twilio to Bird Map requests, registrations, callbacks and opt-outs before changing production traffic.](/docs/guides/sms/migrate/twilio)

[03 Check your message length See how Unicode, emoji and long messages affect SMS segments.](/tools/sms-segment-calculator)

[04 Find your next SMS guide A library for first sends, country rollout, delivery diagnosis and migration.](/sms/resources)

A FEW USEFUL ANSWERS

## SMS API, answered.

## SMS API questions

### What is an SMS API?

An SMS API lets your application send text messages, receive replies on supported numbers and read delivery events. Use it for order updates, reminders or service conversations. Bird also offers campaign tools when your team needs to manage an audience and schedule a broadcast. [Explore SMS campaigns ↗](/products/sms/marketing)

### Can I test the API before sending to a real phone?

Yes. Simulated recipients produce documented delivery, failure and opt-out outcomes. They use your normal API credentials and are billed. Destination enablement and sender validation still apply. A simulation does not establish real carrier performance or handset delivery. [Use simulated SMS destinations ↗](/docs/guides/sms/migrate#6-test-against-simulated-destinations)

### How much does the SMS API cost?

Outbound SMS is priced per segment, with rates depending on destination and sender type. Include applicable carrier fees, number rental and registration. A long message or an emoji can change the segment count. Check your actual markets and traffic mix when comparing providers. [See current SMS pricing ↗](/pricing/sms)

### Which countries and sender types can I use?

Check the country reference for supported sender types, registration, message categories and reply support. Enable the destination in your workspace before sending. US application long codes follow A2P 10DLC registration; an alphanumeric sender ID cannot receive replies. [Check country requirements ↗](/products/sms/destinations)

### Can customers reply to my SMS?

Yes, with a supported two-way number in an eligible destination. Bird emits sms.received with the incoming message. Match the sender to your customer and route the reply into your application. An inbound reply is a separate message with its own ID. [Build a two-way SMS flow ↗](/products/sms/two-way)

### Does delivered mean the customer read the message?

A delivery event reports a carrier receipt. It does not establish reading or completion of an action in your app. If no final receipt arrives, keep the outcome pending and inspect the message log before applying your retry policy. [Read the delivery event contract ↗](/docs/guides/sms/events)

### Can I send SMS in bulk?

The batch endpoint accepts up to 100 independent messages per request. After acceptance, each message can succeed or fail separately. For an audience campaign, use the broadcast tools. Consent, sender requirements and opt-outs apply to the messages you send. [Read batch sending ↗](/docs/guides/sms/sending-sms#batch-sending)

### How are STOP replies and opt-outs handled?

Supported stop keywords record a sender-and-subscriber suppression and still emit an incoming-message event. Keep those signals connected to your consent records and sending flow. A delivery failure alone does not establish an opt-out. [Read opt-outs and keyword rules ↗](/docs/guides/sms/opt-outs-and-keywords)

### Can Bird support an enterprise rollout or migration?

Work with sales on your destinations, sender registrations, volumes and rollout plan. Review security, data handling and the support terms for your agreement. Confirm any throughput or service commitments for your specific setup before launch. [Review security and trust ↗](https://trust.bird.com)

YOUR NEXT CONNECTION

## Your first message. Your next market.

Start building with your API key. For a production rollout, bring your destinations, sender types and volumes to our team.

[Start now](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Fsms%2Fonboarding)

[Talk to sales](/demo?product=sms)

[Find SMS setup and delivery guides ↗](/sms/resources)