Envoyer des SMS

Une seule API pour chaque texto que vous envoyez.

Mise en place en :
Cursor

Envoyez un message ou une centaine via la même API SMS. Le SDK compte les segments avant l'envoi, choisit GSM-7 ou Unicode à votre place, et chaque envoi est idempotent avec un webhook à chaque état de livraison.

send-otp.ts
200 · 0.4s
import { BirdClient } from "@messagebird/sdk";

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

const code = generateOtp();

const { data, error } = await bird.sms.send({
  from: "Bird",
  to:   "+15005550006",
  text: `Your Bird verification code is ${code}. Reply STOP to opt out.`,
}).safe();

if (error) throw error;
console.log(data.id);
// → "sms_4kT01Lq2m..."

Today at 2:14 PM

Hey Ada — your Bird sign-in code is 482917. It'll expire in 10 minutes. Don't share it with anyone.
482917
Delivered

Envoyez votre premier SMS en cinq minutes.

Depuis le langage que vous utilisez déjà.

L'envoi est le cœur de l'API SMS de Bird. Le premier envoi part vers un destinataire de test autorisé (+15005550006), vous pouvez donc livrer un contrôle CI et câbler des webhooks avant de provisionner un numéro.

1
2
3
4
5
6
7
8
9
import { BirdClient } from "@messagebird/sdk";

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

const { data, error } = await bird.sms.send({
  from: "Bird",
  to:   "+15005550006",
  text: "Hello from Node.",
}).safe();

Cinq choses que vous ne construisez pas vous-même.

Le même contrat sur chaque canal Bird.

  1. 01

    Comptage des segments avant l'envoi.

    Le SDK mesure la longueur encodée et vous indique combien de segments coûte un message, de sorte qu'un caractère égaré ne scinde jamais silencieusement un texto en trois.

  2. 02

    GSM-7 et Unicode, décidés à votre place.

    Le texte brut passe en GSM-7 ; un emoji ou une écriture non latine bascule tout le message en UCS-2. Bird choisit l'encodage et vous avertit lorsqu'un seul caractère modifie le coût.

  3. 03

    Le lot en un seul appel.

    Envoyez de nombreux messages indépendants en une seule requête, chacun avec son propre destinataire et son propre texte, validés comme une unité pour que vous n'envoyiez jamais à moitié.

  4. 04

    Idempotent par contrat.

    Chaque envoi accepte une clé d'idempotence, de sorte qu'une requête réessayée après un délai d'attente renvoie le résultat d'origine au lieu d'envoyer un texto deux fois à quelqu'un.

  5. 05

    Un webhook à chaque changement d'état.

    Mis en file d'attente, envoyé, délivré, échoué. Chacun signé HMAC, protégé contre le rejeu, idempotent, la même enveloppe sur chaque canal.

Vous envoyez déjà ailleurs ? Changez de client, gardez l'appel.

La forme change à peine : remplacez le client, gardez vos from, to et text, pointez vos webhooks vers un seul endpoint. Le même modèle d'authentification que vos envois e-mail, voix et WhatsApp.

twilio.ts
Twilio
import twilio from "twilio";

const client = twilio(accountSid, authToken);

await client.messages.create({
  from: "+14155550172",
  to:   "+15005550006",
  body: "Your code is 123456.",
});
bird.ts
Bird
import { BirdClient } from "@messagebird/sdk";

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

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

Connaissez le coût avant l'opérateur.

Un message GSM-7 tient en 160 caractères par segment ; un seul emoji ou caractère non latin bascule tout le message en UCS-2 et réduit cela à 70. Le SDK indique l'encodage et le nombre de segments à chaque envoi, de sorte que la facturation ne soit jamais une surprise et qu'un message concaténé soit toujours un choix délibéré.

segments.ts
200 · 1 segment
const { data } = await bird.sms.send({
  from: "Bird",
  to:   "+15005550006",
  text: "Your code is 123456.",
}).safe();

console.log(data.encoding); // → "GSM-7"
console.log(data.segments); // → 1

Un message ou une centaine, un seul appel.

Regroupez en lot des messages indépendants en une seule requête, chacun avec son propre destinataire et son propre texte. Le lot est validé comme une unité : un seul mauvais numéro rejette l'appel avec un 422, vous n'envoyez donc jamais à moitié. Une seule clé d'idempotence rend toute la requête sûre à réessayer.

reminders.ts
202 · batch
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`);

Suivez chaque message tout au long de sa vie.

Un envoi renvoie 202 immédiatement ; le résultat arrive sous forme de webhook. Vérifiez une signature, branchez sur le type : la même enveloppe que vous gérez déjà pour l'e-mail, la voix et WhatsApp.

app/api/webhooks/bird/route.ts
signed
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.reason);
      break;
  }

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

Les envois échoués et les réponses STOP mettent à jour votre liste de suppression automatiquement, de sorte qu'un mauvais numéro ne vous coûte jamais deux fois.

  • sms.queuedAccepté par l'API et mis en file d'attente pour la transmission à l'opérateur.
  • sms.sentSoumis au SMSC de l'opérateur de destination.
  • sms.deliveredAccusé de réception reçu de l'opérateur (DLR).
  • sms.failedÉchec permanent — rejet par l'opérateur, numéro invalide ou suppression atteinte.

Approfondissez dans la documentation.

Câblez des webhooks, rendez chaque envoi sûr à réessayer avec des clés d'idempotence, et lisez la référence des erreurs pour gérer chaque échec de la bonne façon.

FAQ sur l'envoi de SMS

Quelle longueur un SMS peut-il avoir ?+
Un message GSM-7 tient en 160 caractères par segment ; passer en Unicode (UCS-2) pour des emoji ou des écritures non latines réduit cela à 70. Les messages plus longs sont concaténés sur plusieurs segments, et le SDK indique le nombre avant l'envoi.
Puis-je envoyer à de nombreux destinataires en une seule requête ?+
Oui. Regroupez en lot des messages indépendants dans un seul appel, chacun avec son propre destinataire et son propre texte. Le lot est validé comme une unité, et une seule clé d'idempotence couvre toute la requête.
Que se passe-t-il si je réessaie un envoi après un délai d'attente ?+
Transmettez une clé d'idempotence et une requête réessayée renvoie le résultat d'origine au lieu d'envoyer deux fois. Sans clé, un nouvel essai est traité comme un nouveau message.
Comment savoir si un message a été délivré ?+
Chaque changement d'état déclenche un webhook signé HMAC — mis en file d'attente, envoyé, délivré ou échoué — portant l'accusé de réception de l'opérateur et le nombre de segments.

Environ 40 % du SMS commercial mondial passe déjà par Bird.

L'envoi est l'une des capacités de l'API SMS de Bird : les numéros, la réception bidirectionnelle, la conformité, le routage et l'analyse sont livrés avec lui, sur une infrastructure que nous exploitons depuis une décennie.

Commencez avec un seul canal.
Ajoutez les autres quand vous êtes prêt.

Une clé API de test est disponible immédiatement. L'accès production se débloque dès que vous ajoutez un moyen de paiement et vérifiez un expéditeur.

Vous utilisez Claude Code, Cursor ou Codex ? Copiez un prompt de configuration et votre agent installe la CLI Bird et les compétences pour vous. Choisissez le vôtre :

Cursor