Bird

Migrate SMS from Azure Communication Services to Bird

Keep your Azure application and replace its SMS integration. The work covers senders, per-recipient send results and event consumers. Moving the messaging client does not require moving your Azure Functions, hosting or application identity system.

1. Inventory the Azure SMS resource

Record the Communication Services resource endpoint, sending numbers, destinations and the SmsClient calls in your application. Identify whether the client uses a connection string, an Azure key credential or a token credential. Bird uses a separate workspace API key; keep Azure credentials for the Azure services that still need them. See the Azure JavaScript SMS client for the source authentication and send shapes.
Include Event Grid subscriptions, delivery-report settings, incoming-message handlers and the application records keyed by Azure messageId. If your integration also uses Azure Calling, Email or Messaging Connect, inventory those interfaces separately; this guide maps the Communication Services SMS client.

2. Prepare Bird senders

Use Bird sender setup to choose a sender valid for the recipient's country. Complete the required registration and destination enablement before testing. A number attached to the Azure resource is not automatically available in Bird. Arrange its supported transfer process if you need to keep it, and verify replies separately from outbound sending.
Reconcile application preferences with the opt-out handling configured for the Azure sender. Microsoft's SMS opt-out API and SMS FAQ describe the available behavior. Preserve a customer's refusal when rebuilding sender-and-subscriber pairs in Bird suppressions. Include preferences received through your website and support team; a callback history may not contain them.

3. Implement the adapter

Map the application message to an individual Bird send, and retain both providers' message IDs during the transition.
Azure SMS clientBird implementation
Resource endpoint and SmsClient credentialsBirdClient with a workspace key; the SDK selects its region.
from, to[], messagefrom, one to, text, and the required free-text category.
Per-recipient successful and messageIdSave the returned message id and status; request acceptance does not establish delivery.
enableDeliveryReportSubscribe a workspace webhook to the relevant SMS events.
tag stringPut correlation context in metadata; Bird tags require structured name/value pairs.
Azure returns an array of send results. A resolved SDK call can still contain a failed recipient, so preserve your per-recipient checks when migrating a multi-recipient job. Bird's batch endpoint contains independent message requests and validates the batch before queueing. It is not the Azure result array with renamed fields. Start with individual sends when you need to manage each attempt separately.
For the Bird example, install @messagebird/sdk and tsx. Set BIRD_API_KEY, BIRD_SMS_FROM, SMS_TO and MESSAGE_KEY in your server environment. Use a configured sender and a permitted test recipient. Save this as send.mts and run npx tsx send.mts; executing it sends an SMS.
Code example
import { BirdClient } from "@messagebird/sdk";

function required(name: string): string {
  const value = process.env[name];
  if (!value) throw new Error(`Set ${name} before running this example.`);
  return value;
}

const bird = new BirdClient({ apiKey: required("BIRD_API_KEY") });
const messageKey = required("MESSAGE_KEY");
const message = await bird.sms.send(
  {
    from: required("BIRD_SMS_FROM"),
    to: required("SMS_TO"),
    text: "Your studio visit is tomorrow at 14:00.",
    category: "transactional",
    metadata: { notification_id: messageKey },
  },
  { idempotencyKey: messageKey },
);
console.log(JSON.stringify({ id: message.id, status: message.status }));
Persist the returned ID in your application's notification record. The example prints the API result and does not wait for handset delivery. Keep the same request and key for a retry within Bird's idempotency window. A correlation tag alone does not provide request deduplication. For a complete server entry point, continue with Next.js or FastAPI.

4. Connect delivery and replies

Azure's SMS event schema uses Microsoft.Communication.SMSDeliveryReportReceived for reports and Microsoft.Communication.SMSReceived for incoming messages. A report includes data.messageId and data.deliveryStatus; the Event Grid envelope has its own event identity. Preserve both kinds of identity in the historical records.
Bird sends a signed JSON event containing type, timestamp and data. Correlate data.sms_id to the message record and deduplicate webhook deliveries using the webhook-id header. A single message can have several distinct events, so its message ID is not the deduplication key for the receiver. Implement signature verification on the raw body before processing it.
Translate the outcome your application needs. Azure's reported Delivered and Failed do not cover Bird's full event catalog. Handle sms.rejected, sms.failed, sms.undelivered and sms.expired according to their documented meanings, and retain an unresolved state when no final observation exists. Use the receipt handler and reply worker for persistent examples. An incoming Bird SMS needs a separate send operation to reply.

5. Cut over by route

Test sender eligibility, a recipient refusal, Unicode content and an incoming reply on the intended number. Exercise duplicate and out-of-order events, then repeat a send after an uncertain response with the same key. Check that a failed recipient remains failed when other recipients in the original Azure job succeeded.
Assign each new logical message to one provider. Keep both event consumers running while earlier Azure sends finish, and preserve Azure IDs for support investigations. If you roll back, route new messages back deliberately; do not resend uncertain accepted attempts simply because the provider selection changed.
Compare the same destinations, encoding and observation window. Check delivery results and the applicable billing records separately. An API acceptance count or a missing receipt cannot stand in for a completed delivery count.

References and next steps

Start now to set up SMS, or talk to sales about number transfers and migration planning.

Related resources

Continue with the documentation, guides and examples for this topic. Resources are in English.