Aller au contenu principal

Webhook SMS

Recevez les SMS de votre téléphone
en webhook, sur votre propre numéro.

Les API de réception SMS commencent en général par la location d'un nouveau numéro. Installez plutôt une application Android gratuite : chaque SMS reçu par votre SIM arrive sur votre URL en JSON signé, et vous répondez depuis ce même numéro.

Pressé ? Résumez cet article avec une IA

La réponse courte

Peut-on recevoir les SMS de son propre numéro par webhook ?

Oui, avec un téléphone Android. L'application gratuite Unlimited Messaging relie la SIM de votre téléphone à votre compte, et chaque SMS reçu après la connexion est envoyé à votre URL sous forme d'événement JSON signé, message.received. Vos clients écrivent toujours au numéro qu'ils connaissent, et vous ne payez rien par SMS reçu. Contrairement à Twilio, aucun numéro à louer. Les webhooks sont inclus dans les offres payantes Medium et Max.

La voie classique pour recevoir des SMS par API, c'est un fournisseur A2P. Chez Twilio, vous louez un numéro (1,15 $ par mois pour un numéro local américain), vous pointez son webhook vers votre serveur, et vous payez 0,0083 $ par segment reçu plus des frais d'opérateur, 0,0035 $ venant d'AT&T ou 0,0025 $ de T-Mobile. Le numéro est nouveau, vos clients doivent l'apprendre, et Twilio envoie des paramètres form-encoded signés en HMAC-SHA1.

Une passerelle Android évite la location. Unlimited Messaging pour Android est gratuite et open source (MIT) : vous installez l'APK, vous vous connectez, et chaque SIM devient un compte SMS (double SIM, deux comptes). Le téléphone garde une connexion ouverte avec l'API, envoie chaque SMS reçu, et l'API l'annonce à votre webhook dans la même enveloppe JSON que pour WhatsApp et l'email. Un envoi répété du même SMS est reconnu et jamais annoncé deux fois.

La contrepartie est matérielle : le téléphone doit rester allumé, connecté et autorisé à tourner en arrière-plan. Il absorbe les SMS d'une entreprise à un rythme humain, pas le trafic entrant d'un numéro court national.

À comparer d'abord : les quatre applications de passerelle SMS Android, et ce que coûte vraiment une API SMS gratuite.

Illustration : un téléphone avec des bulles de SMS et une étiquette SMS, avec le titre « Les SMS reçus, droit dans votre code ».

Les événements

Quels événements SMS le webhook envoie-t-il ?

Le SMS utilise les mêmes types d'événements que les autres canaux. Un endpoint ne reçoit que les types de sa liste eventTypes.

  1. message.received

    Un SMS est arrivé sur l'une de vos SIM. data.channel.type vaut SMS, content contient le texte, sender le numéro au format +E.164. Un expéditeur que l'opérateur affiche par un nom (une banque, un transporteur) arrive avec sender à null et ce nom dans senderId.

  2. message.sent

    Un SMS envoyé par l'API a quitté le téléphone. Il porte le texte et le destinataire, émis une seule fois : votre boîte de réception montre les deux côtés.

  3. message.status

    Un SMS envoyé est passé à SENT, DELIVERED (quand l'opérateur renvoie des accusés), FAILED ou UNDELIVERABLE, avec error pour la raison. Le SMS n'a pas d'accusé de lecture : jamais READ.

  4. account.status_changed

    Un compte SIM a changé de statut, par exemple déconnecté quand l'application a été déconnectée. Abonnez-vous-y pour savoir quand le téléphone ne relaie plus.

POST https://example.com/webhooks/umJSON
{
  "type": "message.received",
  "eventId": "whd_2b9e7c41-0d3a-4f6e-8c52-91a7d4e0b6f3",
  "occurredAt": "2026-11-09T08:42:06.000Z",
  "data": {
    "message": {
      "id": "msg_7d2c9a10-5e4b-4b8f-a1c3-0f6e2d9b8a47",
      "externalId": "c1f4a9e27b3d4e6f9a0b",
      "direction": "IN",
      "fromMe": false,
      "content": "Running 10 min late for my 9:00, sorry!",
      "sentAt": "2026-11-09T08:42:03.000Z",
      "receivedAt": "2026-11-09T08:42:06.000Z",
      "sender": "+447700900456",
      "senderId": "+447700900456",
      "senderName": null,
      "participant": null,
      "replyTo": null,
      "transcript": null
    },
    "channel": {
      "type": "SMS",
      "account": { "id": "acc_5e8d1f2a-3c4b-4d6e-9f70-1a2b3c4d5e6f", "name": "Front desk SIM" },
      "conversation": { "id": null, "isGroup": false, "address": "+447700900456" }
    }
  }
}
Un vrai corps message.received pour un SMS, construit d'après le schéma publié. conversation.id vaut null pour le SMS : regroupez la conversation par sender. Seuls les SMS reçus après la connexion de l'application sont envoyés ; ceux déjà présents sur le téléphone ne sont jamais lus.

Mise en place

Comment recevoir les SMS entrants en Node.js ?

Installez l'application, enregistrez un endpoint, vérifiez chaque POST. Le même handler servira pour WhatsApp et l'email.

  1. 01

    Installez l'application Android

    Téléchargez l'APK sur GitHub (Android 8.0 ou plus récent), connectez-vous, accordez l'accès aux SMS et une batterie sans restriction. Chaque SIM apparaît comme un compte SMS.

  2. 02

    Enregistrez l'endpoint

    POST /webhooks avec votre URL et vos eventTypes, ou ajoutez-le sur la page Webhooks du tableau de bord. Le secret (whsec_...) n'est affiché qu'une fois.

  3. 03

    Vérifiez, acquittez, agissez

    Contrôlez l'en-tête webhook-signature, renvoyez un 2xx en moins de 10 secondes, dédupliquez sur eventId, puis répondez ou enregistrez.

POST /webhookscurl
curl https://api.unlimitedmessaging.app/webhooks \
  -H "Authorization: Bearer $UM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/webhooks/um",
    "eventTypes": ["message.received", "message.status"],
    "description": "Incoming SMS"
  }'

# The response carries "secret": "whsec_..." once. Store it as UM_WEBHOOK_SECRET.
Ajoutez accountIds pour limiter l'endpoint à une SIM ; sans lui, tous vos comptes sont couverts, y compris les SIM ajoutées plus tard.
handler du webhookNode.js / Express
import crypto from 'node:crypto';
import express from 'express';
import { UnlimitedMessagingApiClient } from '@unlimited-messaging/sdk';

const um = new UnlimitedMessagingApiClient({ token: process.env.UM_API_KEY! });
const key = Buffer.from(process.env.UM_WEBHOOK_SECRET!.replace(/^whsec_/, ''), 'base64');
const seen = new Set<string>(); // use your database in production

// Standard Webhooks: HMAC-SHA256 of "id.timestamp.rawBody", base64.
function verify(raw: string, id: string, ts: string, header: string) {
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const expected = crypto.createHmac('sha256', key).update(`${id}.${ts}.${raw}`).digest('base64');
  return header.split(' ').some((entry) => {
    const sig = entry.startsWith('v1,') ? entry.slice(3) : '';
    return sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
  });
}

const app = express();
app.post('/webhooks/um', express.raw({ type: 'application/json' }), async (req, res) => {
  const raw = req.body.toString('utf8');
  const ok = verify(raw, req.get('webhook-id') ?? '', req.get('webhook-timestamp') ?? '',
    req.get('webhook-signature') ?? '');
  if (!ok) return res.sendStatus(401);
  res.sendStatus(200); // answer within 10 s, work afterwards

  const event = JSON.parse(raw);
  if (seen.has(event.eventId)) return; // at-least-once delivery
  seen.add(event.eventId);

  if (event.type === 'message.received' && event.data.channel.type === 'SMS') {
    const { sender, content } = event.data.message;
    if (content?.trim().toUpperCase() === 'C') {
      // Texts back from the same SIM that received the SMS.
      await um.messages.messageSend({
        to: { phone: sender },
        channels: [{ channel: 'SMS', accountId: event.data.channel.account.id }],
        text: 'Thanks, your appointment is confirmed.',
      });
    }
  }
});
app.listen(3000);
La vérification suit le schéma Standard Webhooks documenté (HMAC-SHA256 sur id.timestamp.rawBody). La réponse désigne la SIM qui a reçu le SMS : elle part du même numéro.

Vibe coding

Vous codez avec Cursor, Claude Code, Lovable ou Bolt ? Collez ceci

Votre éditeur IA reçoit la route, le schéma de signature et la forme de l'événement SMS en une fois.

Prompt à copier
Add an Unlimited Messaging webhook to this app so it receives the SMS my own Android phone receives.

1. Create a POST route at /webhooks/um that reads the RAW request body.
2. Verify the Standard Webhooks signature: key = base64-decode(UM_WEBHOOK_SECRET without "whsec_"); expected = base64(HMAC-SHA256(key, `${webhook-id}.${webhook-timestamp}.${rawBody}`)); accept if any space-separated entry of the webhook-signature header equals `v1,${expected}` (constant-time compare); reject timestamps more than 5 minutes off; return 401 otherwise.
3. Return 200 at once, then process. Deduplicate on body.eventId.
4. On type "message.received" with data.channel.type "SMS", save data.message.sender (+E164, or null with the name in senderId), data.message.content and data.message.sentAt. conversation.id is null for SMS: group by sender.
5. To reply by SMS, install @unlimited-messaging/sdk, read UM_API_KEY from env, and call `client.messages.messageSend({ to: { phone: sender }, channels: [{ channel: 'SMS', accountId: data.channel.account.id }], text })`.
6. Put UM_API_KEY and UM_WEBHOOK_SECRET in .env and .env.example, never in code.

Docs: https://docs.unlimitedmessaging.app (Webhooks). Register the URL with POST https://api.unlimitedmessaging.app/webhooks and eventTypes ["message.received", "message.status"].

Ce que l'on construit

Que faire des SMS reçus sur votre propre numéro ?

Tout ce qui commence par un client qui écrit au numéro inscrit sur votre camion, votre flyer ou votre facture.

Rappels avec confirmation par réponse

Envoyez un rappel par SMS, lisez le C ou le R qui revient, mettez à jour le rendez-vous et confirmez, le tout depuis votre numéro habituel.

Les SMS dans votre CRM

Rattachez chaque SMS reçu au contact par sender, à côté de ses WhatsApp et emails : les trois arrivent dans la même enveloppe.

  1. Gestion du STOP

    Repérez STOP dans content et marquez le contact avant votre prochain envoi.

  2. Première réponse par IA

    Confiez le texte à un LLM pour un brouillon, renvoyez-le par SMS ou passez la main à un humain.

  3. Alertes de machines et de services

    Transférez les SMS d'une alarme, d'une SIM de capteur ou d'un fournisseur vers Slack ou par email.

  4. Flux no-code

    Pointez le webhook vers n8n, Make ou Zapier et aiguillez selon content, sans serveur.

Le tableau

Recevoir des SMS par webhook : Twilio, passerelles Android et Unlimited Messaging

Un numéro loué chez un fournisseur, ou la SIM déjà dans votre téléphone.

Recevoir des SMS par webhook : Twilio, passerelles Android et Unlimited Messaging
TwilioNuméro loué (États-Unis)SMSGate / httpSMSPasserelles Android open sourceUnlimited MessagingApp Android, offres payantes
Numéro qui reçoitUn numéro loué chez TwilioLa SIM de votre téléphoneLa SIM de votre téléphone
Coût mensuel du numéro1,15 $ local, 2,15 $ numéro gratuit (toll-free)Rien au-delà de votre forfaitRien au-delà de votre forfait ; webhooks avec Medium ou Max
Coût par SMS reçu0,0083 $ par segment plus frais d'opérateurAucunAucun côté Unlimited Messaging
PayloadForm-encoded, X-Twilio-Signature (HMAC-SHA1)Webhook ou URL de callback (SMSGate : événement sms:received)JSON, signature Standard Webhooks (HMAC-SHA256)
MatérielAucunUn téléphone Android alluméUn téléphone Android 8.0+ allumé
WhatsApp et email dans le même webhookWhatsApp via un expéditeur enregistré ; email via SendGrid, séparémentSMS uniquementOui, même enveloppe, même signature
VolumeConçu pour le gros volumeLe rythme d'un téléphoneLe rythme d'un téléphone

Vérifié le 9 novembre 2026 sur les tarifs SMS américains de Twilio, sa documentation des messages entrants et de la sécurité des webhooks, et les dépôts SMSGate et httpSMS (liens dans les sources). Les frais d'opérateur varient selon l'opérateur de l'expéditeur.

Les contreparties

Quelles sont les limites d'un webhook SMS depuis votre téléphone ?

Pas de numéro loué ni de frais par SMS, mais un téléphone reste un téléphone.

  1. Les webhooks sont payants

    Avec l'offre Free, les SMS reçus s'affichent dans la boîte de réception de l'application web. Les pousser vers votre serveur demande Medium (19 € par mois, ou 17 € par mois en annuel) ou Max.

  2. Le téléphone doit rester allumé et connecté

    Éteint, sans réseau ou coupé par l'économiseur de batterie, il ne relaie plus rien jusqu'à son retour. Laissez la batterie de l'application sans restriction, et autorisez le démarrage auto sur Samsung, Xiaomi, Huawei, Oppo et Vivo.

  3. Android uniquement, hors Google Play

    Google Play n'accorde les permissions SMS qu'à l'application SMS par défaut : l'application est donc distribuée en APK signé sur GitHub. Il n'existe pas de version iPhone.

  4. Texte uniquement, à partir de la connexion

    Le SMS est en texte seul (pas de MMS). Seuls les messages reçus après la connexion de l'application sont envoyés : les SMS déjà sur le téléphone ne sont jamais lus.

  5. Une ligne personnelle, un rythme personnel

    Les forfaits grand public sont vendus pour un usage entre personnes, et vos réponses comptent sur votre forfait. Pour des milliers de SMS entrants par heure ou un numéro court, prenez un fournisseur A2P.

FAQ

Questions sur les webhooks SMS

Ilian, ingénieur logiciel senior

Écrit par

· Senior Software Engineer

Ingénieur logiciel senior, il fonde et dirige plusieurs sociétés tech. Il conçoit des produits autour des API de messagerie, de l’automatisation et de l’intégration de l’IA, et partage ici ce qu’il apprend en construisant.

Voir le profil LinkedInMis à jour le

Votre propre numéro, branché sur votre code.

Créez un compte, installez l'application Android gratuite, et activez les webhooks avec Medium ou Max. L'envoi de SMS reste gratuit sur toutes les offres.