Entwickler
Von der Sinch SMS-API zur Conversation API migrieren
Wenn Ihr Code an https://us.sms.api.sinch.com/xms/v1/{service_plan_id}/batches sendet oder sms.batches.send in einem Sinch-SDK aufruft, verwendet er die eigenständige Sinch-SMS-API, die manchmal auch als XMS bezeichnet wird. Der Verkauf der SMS-API wurde am 15. April 2026 eingestellt. Integrationen, die bereits darauf aufbauen, funktionieren weiterhin, aber neue Integrationen sollten die Sinch Conversation API verwenden, selbst für ein Konto, das die SMS-API zuvor genutzt hat. Die Conversation API sendet dieselbe SMS über dasselbe Abonnement und dieselbe Nummer, und dasselbe Anfrageformat deckt RCS, WhatsApp und die anderen Kanäle ab. Dieser Beitrag bildet eine SMS-API-Integration Stück für Stück auf die Conversation API ab, mit Anfragen, die ich für dasselbe Abonnement an beide APIs gesendet habe. Wenn Sie stattdessen ganz von vorn anfangen, SMS mit der Sinch Conversation API in curl, Node.js und Python versenden ist der kürzere Weg.
Sie benötigen Folgendes:
- Ihr bestehendes SMS-API-Abonnement und die dazugehörigen Nummern
- Zugang zur Conversation API im Sinch-Dashboard (Öffnen Sie Conversation API im linken Menü und klicken Sie auf GET ACCESS, falls Sie das noch nicht getan haben)
curlundjqfür die Shell-Beispiele oder Node.js 20 bzw. neuer mit@sinch/sdk-corefür die Node.js-Beispiele
Abonnement mit einer Conversation API-App verknüpfen
Sie benötigen keine neue Nummer. Die Conversation API sendet SMS über eine App, und der SMS-Kanal der App verweist auf ein SMS-Abonnement. Richten Sie diesen auf das Abonnement, das Sie bereits haben.
Die Verknüpfung ändert das Ziel der Callbacks des Abonnements. Die Callback-URLs des Abonnements müssen entfernt werden, bevor Sie es verknüpfen können. Danach gehen eingehende Nachrichten an den Conversation API-Webhook der App, und Zustellungsberichte für Batches, die Sie noch über die SMS-API senden, erreichen Sie nur, wenn der Batch eine eigene callback_url festlegt. Richten Sie zunächst den Webhook der App ein und testen Sie ihn mit einem Test-Abonnement, bevor Sie ihn produktiv nutzen, sofern Sie eines haben.
Die Schritte:
- Gehen Sie zu Conversation API, dann zu Apps, und erstellen Sie eine App in derselben Region wie Ihr Abonnement. Die Conversation API ist in den USA, der EU und Brasilien verfügbar. Wenn sich Ihr Abonnement in einer anderen SMS-API-Region wie Australien oder Kanada befindet, fragen Sie Ihren Sinch-Account-Manager, welche Conversation API-Region Sie verwenden sollten, bevor Sie beginnen.
- Klicken Sie in der App in der Zeile SMS auf SET UP CHANNEL und wählen Sie Ihr bestehendes Abonnement aus. Wenn für das Abonnement Callback-URLs festgelegt sind, wird es vom Dashboard erst verknüpft, wenn Sie diese unter SMS, Service APIs, Callback URLs entfernen. Dies schließt die Überschreibung der Incoming URL ein, nicht nur die Default URL. Richten Sie vorher den Webhook der App ein (siehe Zustellungsberichte), da das Abonnement ab diesem Zeitpunkt keine Callbacks mehr an Ihren alten Endpunkt sendet.
- Navigieren Sie zu Einstellungen, dann Zugriffsschlüssel, und erstellen Sie einen Zugriffsschlüssel. Kopieren Sie die Key-ID und das Secret. Das Secret wird nur einmal angezeigt.
Kopieren Sie die App-ID aus der App und die Projekt-ID unter Settings, Project Settings. Diese ersetzen die Abonnement-ID und das API-Token in Ihrem Code:
| SMS-API | Conversation API |
|---|---|
https://{region}.sms.api.sinch.com | https://{region}.conversation.api.sinch.com |
| Abonnement-ID im Pfad | Projekt-ID im Pfad, App-ID im Body |
| API-Token als Bearer-Token | Access Key (Key-ID und Secret), der gegen ein OAuth 2.0-Token eingetauscht wird |
Das Token stammt aus einer Anfrage und ist etwa eine Stunde lang gültig:
export SINCH_ACCESS_TOKEN=$(curl --silent --show-error --fail-with-body \
https://auth.sinch.com/oauth2/token \
--user "$SINCH_KEY_ID:$SINCH_KEY_SECRET" \
--data grant_type=client_credentials | jq -r .access_token)
Die SDKs fordern das Token für Sie an und aktualisieren es.
Eine Nachricht senden
Hier ist ein typischer SMS-API-Aufruf: ein Empfänger, ein Zustellungsbericht pro Empfänger und eine Referenz, um den Bericht einer Bestellung zuzuordnen.
curl --silent --show-error --fail-with-body \
"https://us.sms.api.sinch.com/xms/v1/$SINCH_SERVICE_PLAN_ID/batches" \
--header "Authorization: Bearer $SINCH_API_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"from": "+12025550123",
"to": ["+15551234567"],
"body": "Your order has shipped",
"delivery_report": "per_recipient",
"client_reference": "order-1042"
}'
{"body":"Your order has shipped","canceled":false,"client_reference":"order-1042","created_at":"2026-10-28T11:57:15.529Z","delivery_report":"per_recipient","expire_at":"2026-10-31T11:57:15.529Z","flash_message":false,"from":"46765106280","id":"01M615Y8W9CRFH0SVQBS9KVK7F","modified_at":"2026-10-28T11:57:15.529Z","to":["46706855785"],"type":"mt_text"}
Dieselbe Nachricht mit der Conversation API:
curl --silent --show-error --fail-with-body \
"https://us.conversation.api.sinch.com/v1/projects/$SINCH_PROJECT_ID/messages:send" \
--header "Authorization: Bearer $SINCH_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"app_id": "YOUR_APP_ID",
"recipient": {
"identified_by": {
"channel_identities": [{ "channel": "SMS", "identity": "+15551234567" }]
}
},
"message": { "text_message": { "text": "Your order has shipped" } },
"channel_properties": { "SMS_SENDER": "+12025550123" },
"message_metadata": "order-1042"
}'
{"message_id":"01M613S632MAAMWRVFEHPQ4YMA","accepted_time":"2026-10-28T11:19:31.682Z"}
Vier Dinge haben sich geändert. from wurde zur Kanaleigenschaft SMS_SENDER. to wurde zu einem einzigen recipient, wobei der Kanal neben der Nummer angegeben ist. client_reference wurde zu message_metadata, das im Zustellungsbericht zurückgegeben wird. delivery_report ist aus der Anfrage verschwunden: Zustellungsberichte stammen von einem Webhook in der App, was weiter unten behandelt wird.
Die Antwort hat sich ebenfalls geändert. Die SMS-API gibt einen Batch mit einer id zurück. Die Conversation API gibt eine message_id für die einzelne Nachricht zurück, und auf diese ID beziehen sich die Zustellungsberichte.
In Node.js liegt die Änderung in den Client-Optionen und der Methode. Vorher, mit der SMS-API:
import { SinchClient } from "@sinch/sdk-core";
// Before: the standalone SMS API, authenticated with a service plan ID and API token.
const sinchClient = new SinchClient({
servicePlanId: process.env.SINCH_SERVICE_PLAN_ID ?? "",
apiToken: process.env.SINCH_API_TOKEN ?? "",
smsRegion: "us",
});
const batch = await sinchClient.sms.batches.sendTextMessage({
sendSMSRequestBody: {
from: "+12025550123",
to: ["+15551234567"],
body: "Your order has shipped",
delivery_report: "per_recipient",
client_reference: "order-1042",
},
});
console.log(`Sent batch ${batch.id}`);
Nachher, mit der Conversation API:
import { SinchClient } from "@sinch/sdk-core";
// After: the Conversation API, authenticated with a project ID and access key.
const sinchClient = new SinchClient({
projectId: process.env.SINCH_PROJECT_ID ?? "",
keyId: process.env.SINCH_KEY_ID ?? "",
keySecret: process.env.SINCH_KEY_SECRET ?? "",
conversationRegion: "us",
});
const response = await sinchClient.conversation.messages.sendTextMessage({
sendMessageRequestBody: {
app_id: process.env.SINCH_APP_ID ?? "",
recipient: {
identified_by: {
channel_identities: [{ channel: "SMS", identity: "+15551234567" }],
},
},
message: { text_message: { text: "Your order has shipped" } },
channel_properties: { SMS_SENDER: "+12025550123" },
message_metadata: "order-1042",
},
});
console.log(`Sent message ${response.message_id}`);
Beide verwenden @sinch/sdk-core, sodass Sie sie in einer Codebasis nebeneinander ausführen können, während Sie Workflows umstellen. Die Beispiele überspringen die Eingabevalidierung, damit der Vergleich besser lesbar bleibt. Die Der Beitrag zum SMS-Versand enthält die Vollversion mit Umgebungsprüfungen und Nummernvalidierung.
Feld für Feld
Die Felder, die die meisten SMS-API-Integrationen verwenden, und wo sie eingefügt werden:
| SMS-API-Feld | Conversation API |
|---|---|
from | channel_properties.SMS_SENDER oder der Standard-Absender des Abonnements |
to (Array) | recipient (einer pro Anfrage) oder die Batch-API für viele Empfänger |
body | message.text_message.text |
client_reference | message_metadata, zurückgegeben in Zustellungsberichten. correlation_id erreicht auch eingehende Antworten |
delivery_report | Ein MESSAGE_DELIVERY-Webhook in der App |
callback_url | callback_url in der Anfrage. Das Python-SDK nennt es event_destination_target |
parameters | Batch-API recipient_and_params[].parameters |
send_at | Batch-API send_after, bis zu sieben Tage im Voraus |
flash_message | channel_properties.SMS_FLASH_MESSAGE: "true" |
max_number_of_message_parts | channel_properties.SMS_MAX_NUMBER_OF_MESSAGE_PARTS |
Batch-id | message_id pro Nachricht oder batch_id aus der Batch-API |
Kanaleigenschaftswerte sind Strings. Daher akzeptiert SMS_FLASH_MESSAGE "true" und nicht true. Wenn Sie binäre SMS mit type: mt_binary und einem UDH senden, prüfen Sie die Eigenschaften des SMS-Kanals für Ihren Anwendungsfall, bevor Sie diesen Workflow umstellen.
An viele Empfänger senden
Die SMS-API akzeptiert bis zu 1.000 Nummern in to und füllt die parameters pro Empfänger aus. Bei der Conversation API akzeptiert messages:send einen einzigen Empfänger. Durchlaufen Sie für eine Handvoll Nachrichten Ihre Empfänger und senden Sie jeweils eine Anfrage. Verwenden Sie für eine echte Liste die Conversation Batch API: Eine Nachricht, bis zu 1.000 Empfänger, jeder mit seinen eigenen Parametern.
#!/usr/bin/env bash
# Send one templated SMS to several recipients with the Conversation Batch API.
# Requires SINCH_ACCESS_TOKEN from https://auth.sinch.com/oauth2/token.
set -euo pipefail
: "${SINCH_ACCESS_TOKEN:?Set SINCH_ACCESS_TOKEN}"
: "${SINCH_PROJECT_ID:?Set SINCH_PROJECT_ID}"
: "${SINCH_APP_ID:?Set SINCH_APP_ID}"
: "${SINCH_SMS_SENDER:?Set SINCH_SMS_SENDER}"
region="${SINCH_REGION:-us}"
body=$(jq -n \
--arg app_id "$SINCH_APP_ID" \
--arg sender "$SINCH_SMS_SENDER" \
'{
app_id: $app_id,
message: { text_message: { text: "Hi ${name}, your order has shipped" } },
channel_properties: { SMS_SENDER: $sender },
recipient_and_params: [
{
recipient: { identified_by: { channel_identities: [{ channel: "SMS", identity: "+15551234567" }] } },
parameters: { name: "Ana" }
},
{
recipient: { identified_by: { channel_identities: [{ channel: "SMS", identity: "+15557654321" }] } },
parameters: { name: "Sam" }
}
]
}')
curl --silent --show-error --fail-with-body \
"https://$region.conversationbatch.api.sinch.com/v1/projects/$SINCH_PROJECT_ID/messages" \
--header "Authorization: Bearer $SINCH_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data "$body"
echo
{"batch_id":"01M613S8XFQAP5EAX93J9QHX1W","send_after":"2026-10-28T11:19:34Z"}
Die Platzhalter-Syntax lautet ${name}, genau wie bei den SMS-API-Parametern. Die Batch-API hat einen eigenen Host, conversationbatch.api.sinch.com. Fügen Sie send_after mit einer UTC-Zeit bis zu sieben Tage im Voraus hinzu, um den Batch zu planen. Die Nachricht jedes Empfängers erhält eine eigene message_id und einen eigenen Zustellungsbericht, wobei die Batch-ID in den metadata des Berichts enthalten ist.
Verwenden Sie den Pfad /v1/. Die Batch-API-Endpunkte v1alpha und v1beta werden am 16. Dezember 2026 eingestellt, sodass Code, der für sie geschrieben wurde, ebenfalls auf /v1/ umgestellt werden muss.
Zustellungsberichte
In der SMS-API legen Sie delivery_report für jeden Batch fest und erhalten Berichte an der Callback-URL des Abonnements. Bei der Conversation API gehen Berichte an die Webhooks in der App, und Sie wählen diese per Trigger aus. Fügen Sie einen mit MESSAGE_DELIVERY für Berichte und MESSAGE_INBOUND für Antworten hinzu:
curl --silent --show-error --fail-with-body \
"https://us.conversation.api.sinch.com/v1/projects/$SINCH_PROJECT_ID/webhooks" \
--header "Authorization: Bearer $SINCH_ACCESS_TOKEN" \
--header "Content-Type: application/json" \
--data '{
"app_id": "YOUR_APP_ID",
"target": "https://example.com/sinch/callbacks",
"target_type": "HTTP",
"triggers": ["MESSAGE_DELIVERY", "MESSAGE_INBOUND"]
}'
Ein Zustellungsbericht sieht wie folgt aus:
{
"app_id": "YOUR_APP_ID",
"project_id": "YOUR_PROJECT_ID",
"message_delivery_report": {
"message_id": "01M613S632MAAMWRVFEHPQ4YMA",
"conversation_id": "",
"status": "DELIVERED",
"channel_identity": {
"channel": "SMS",
"identity": "46706855785",
"app_id": "",
"nrs_data": { "mcc": "240", "mnc": "07", "country": "SE" }
},
"contact_id": "",
"metadata": "order-1042",
"processing_mode": "DISPATCH"
}
}
Die Statusliste ist kürzer als die der SMS-API. Eine SMS wechselt von QUEUED_ON_CHANNEL zu DELIVERED oder FAILED. Ein FAILED-Bericht enthält eine reason mit einem Code und einer Beschreibung zur Angabe des Grundes. Ihre Suche nach client_reference wird zu einer Suche nach metadata.
Die Telefonnummer in channel_identity.identity wird ohne führendes + zurückgegeben, selbst wenn Sie an +46706855785 gesendet haben. Die SMS-API macht das Gleiche in ihren Berichten. Code, der bereits mit recipient abgleicht, funktioniert also weiterhin, sobald er aus dem neuen Feld liest. contact_id und conversation_id sind leer, da die App im Dispatch-Modus läuft.
Sinch wiederholt einen Webhook, der keine 2xx zurückgibt. Halten Sie den Handler also idempotent: Verwenden Sie message_id und status, um bereits verarbeitete Berichte zu überspringen.
Eingehende Nachrichten
Antworten auf Ihre Nummer kommen am Webhook der App mit dem Trigger MESSAGE_INBOUND an. Der Text befindet sich unter message.contact_message.text_message.text und die Nummer des Absenders unter message.channel_identity.identity. Wenn Ihr SMS-API-Code body und from aus einem eingehenden Callback liest, sind dies die beiden Pfade, die geändert werden müssen.
Sobald das Abonnement verknüpft ist, verweist seine Standard-Callback-URL auf die Conversation API, und Antworten auf seine Nummern gehen an den Conversation-API-Webhook der App. Sie erscheinen weiterhin in der Inbound-Liste der SMS-API (GET /xms/v1/{service_plan_id}/inbounds). Code, der diese Liste liest, funktioniert also während der Umstellung weiter.
Workflows einzeln umstellen
Einige Entscheidungen machen die Umstellung weniger riskant.
Mit ausgehenden Benachrichtigungen beginnen
Einseitige Benachrichtigungen wie Versandaktualisierungen und Erinnerungen erfordern die wenigsten Änderungen: einen Sendevorgang und einen Zustellungsbericht. Stellen Sie diese zuerst um und belassen Sie bidirektionale Workflows auf der SMS-API, bis der Webhook eingerichtet und getestet ist. Während der Umstellung arbeiten beide APIs mit demselben Abonnement.
SMS-API-Sendevorgängen während der Umstellung eine eigene callback_url zuweisen
Sobald das Abonnement verknüpft ist, gehört seine Standard-Callback-URL zur Conversation API. Zustellungsberichte für Nachrichten, die Sie noch über die SMS-API senden, erreichen den Webhook Ihrer App nicht, und das Abonnement hat keine andere Callback-URL, an die sie gesendet werden könnten. Legen Sie callback_url für jeden SMS-API-Batch fest, der noch Berichte benötigt. Diese kommen dann weiterhin im SMS-API-Format an Ihrem Endpunkt an. Sie können sie auch mit GET /xms/v1/{service_plan_id}/batches/{batch_id}/delivery_report abrufen.
Werte für client_reference in message_metadata beibehalten
Wenn Ihr Reporting, Ihre Datenbank oder ein Support-Tool auf client_reference basiert, fügen Sie denselben Wert in message_metadata ein. Berichte von beiden APIs werden während der Umstellung dann denselben Datensätzen zugeordnet, und nachgelagerte Systeme müssen nicht wissen, welche API die Nachricht gesendet hat.
Mit identified_by an Telefonnummern senden
Neue Apps der Conversation API laufen im Dispatch-Modus, in dem keine Kontakte gespeichert werden. Das entspricht der Funktionsweise der SMS-API: Sie senden an eine Nummer und erhalten einen Bericht für diese Nummer. identified_by mit der Telefonnummer funktioniert in beiden Modi, sodass Sie Ihr Datenmodell für die Umstellung nicht ändern müssen.
Fehlerbehebung
404von der Conversation API. Die Region in der URL stimmt nicht mit der Region der App überein. Die App ist nur in der Region erreichbar, in der Sie sie erstellt haben.
- Der SMS-Kanal meldet Fehler. Die App und das Abonnement müssen sich in derselben Region befinden. Wenn sie sich unterscheiden, erstellen Sie die App in der Region des Abonnements erneut und richten Sie den SMS-Kanal dort ein.
- Es kommen keine Callbacks mehr an Ihrem alten Endpunkt an. Durch die Verknüpfung wurden die Callback-URLs des Abonnements entfernt. Überprüfen Sie bei eingehenden Nachrichten und Sendevorgängen über die Conversation API, ob die App über einen Webhook mit den Triggern
MESSAGE_DELIVERYundMESSAGE_INBOUNDverfügt und dieser eine2xxzurückgibt. Legen Sie für Batches, die Sie weiterhin über die SMS-API senden,callback_urlfür den Batch fest, wie beschrieben in Workflows einzeln umstellen. Um zu sehen, worauf das Abonnement verweist, öffnen Sie SMS, Service APIs, wählen Sie das Abonnement aus und suchen Sie unter Callback URLs.
- Sendevorgänge mit
contact_idschlagen fehl. Die App befindet sich im Dispatch-Modus, in dem keine Kontakte gespeichert werden. Senden Sie stattdessen mitidentified_byund der Telefonnummer.
400von der Batch-API bezüglich Parametern. Ein Platzhalter in der Nachricht hat für einen der Empfänger keinen Wert. Jeder${name}im Text benötigt einen passenden Schlüssel in denparametersdes jeweiligen Empfängers.
Die nächsten Schritte
Sobald die App bereitsteht, können Sie derselben App RCS oder WhatsApp hinzufügen, dem Empfänger in channel_identities eine Identität für jeden Kanal zuweisen, die Kanäle in channel_priority_order auflisten und für Empfänger, die über diese Kanäle nicht verfügen, auf SMS zurückgreifen. Die Seite zu Schlüsselkonzepten erklärt, wie der Fallback funktioniert.