Dokumentation
Schnellstart. Basis-URL ist https://tell.edv.sg, alle Antworten sind
JSON, alle Zeitangaben UTC im ISO-8601-Format.
Anmeldung
Jede Anfrage trägt deinen API-Schlüssel im Authorization-Kopf.
Schlüssel beginnen mit tell_live_ (Produktion) oder
tell_test_ (Testkanal).
Authorization: Bearer tell_live_…
Der Schlüssel wird beim Anlegen einmal im Klartext angezeigt und danach nur noch als Prüfsumme gespeichert. Verloren heisst neu erzeugen.
1. Kanal anlegen
curl -X POST https://tell.edv.sg/v1/channels \
-H "Authorization: Bearer tell_live_…" \
-H "Content-Type: application/json" \
-d '{"name":"Werkstatt St. Gallen"}'
{
"channel_id": "ch_8fa2c1d40b7e",
"name": "Werkstatt St. Gallen",
"status": "qr_pending",
"created_at": "2026-08-20T16:04:11Z"
}
2. Nummer verknüpfen
Der Kanal steht auf qr_pending. Hol den QR-Code ab und scanne ihn in
WhatsApp unter Einstellungen → Verknüpfte Geräte → Gerät verknüpfen.
# PNG (Vorgabe)
curl https://tell.edv.sg/v1/channels/ch_8fa2c1d40b7e/qr \
-H "Authorization: Bearer tell_live_…" > qr.png
# oder den rohen Verknüpfungs-Link, wenn du selbst zeichnen willst
curl "https://tell.edv.sg/v1/channels/ch_8fa2c1d40b7e/qr?format=raw" \
-H "Authorization: Bearer tell_live_…"
Der Code ist rund 60 Sekunden gültig und wird danach automatisch erneuert — hol
ihn bei Ablauf einfach neu ab. Sobald das Handy den Code gescannt hat, wechselt
der Kanal auf connected.
3. Status abfragen
curl https://tell.edv.sg/v1/channels/ch_8fa2c1d40b7e \
-H "Authorization: Bearer tell_live_…"
| Status | Bedeutung |
|---|---|
qr_pending | Kanal angelegt, wartet auf das Scannen des QR-Codes. |
connected | Verknüpft und sendebereit. |
disconnected | Verbindung unterbrochen — meist, weil die Verknüpfung im Handy entfernt oder das Gerät zu lange offline war. Neu scannen. |
banned | WhatsApp hat die Nummer gesperrt. Der Kanal nimmt keine Aufträge mehr an. Wir melden uns in diesem Fall bei dir. |
4. Nachricht senden
curl -X POST https://tell.edv.sg/v1/messages \
-H "Authorization: Bearer tell_live_…" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "ch_8fa2c1d40b7e",
"to": "41791234567",
"type": "text",
"text": "Ihr Fahrzeug ist bereit zur Abholung."
}'
{
"message_id": "msg_2b91ee7c",
"status": "queued",
"queued_at": "2026-08-20T16:07:52Z"
}
Die Empfängernummer wird im internationalen Format ohne + und ohne
Leerzeichen erwartet: 41791234567.
5. Webhooks empfangen
Eingehende Nachrichten und Statuswechsel schickt Tell als POST an
deine URL. Jede Zustellung ist signiert.
POST /dein/endpunkt
X-Tell-Event: message.received
X-Tell-Timestamp: 1755705*** (Unix-Sekunden)
X-Tell-Signature: sha256=4f2b…
{
"event": "message.received",
"channel_id": "ch_8fa2c1d40b7e",
"from": "41791234567",
"type": "text",
"text": "Passt, ich komme morgen vorbei.",
"received_at": "2026-08-20T16:12:03Z"
}
Signatur prüfen
Die Signatur ist ein HMAC-SHA256 über <timestamp>.<roher Body>
mit deinem Webhook-Geheimnis. Prüfe sie vor dem Verarbeiten und
vergleiche zeitkonstant. Verwirf Zustellungen, deren Zeitstempel mehr als fünf
Minuten abweicht — das schliesst Wiedereinspielungen aus.
// Node
import crypto from "node:crypto";
function pruefen(rohBody, kopf, zeitstempel, geheimnis) {
const erwartet = "sha256=" + crypto
.createHmac("sha256", geheimnis)
.update(zeitstempel + "." + rohBody)
.digest("hex");
const a = Buffer.from(kopf), b = Buffer.from(erwartet);
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
Antworte innerhalb von zehn Sekunden mit 2xx. Andernfalls wiederholen
wir die Zustellung mit wachsendem Abstand — nach 1 min, 5 min, 30 min, 2 h und 6 h.
Danach gilt das Ereignis als unzustellbar und wird im Kundenkonto vermerkt.
Durchsatzgrenzen
Wird eine Grenze erreicht, antwortet die API mit 429 und einem
Retry-After-Kopf in Sekunden. Die Nachricht wurde dann
nicht angenommen — schick sie nach Ablauf erneut.
HTTP/1.1 429 Too Many Requests
Retry-After: 34
X-Tell-Limit-Reset: 2026-08-20T16:15:00Z
{
"error": "rate_limited",
"message": "Tagesgrenze der Aufwärmphase erreicht (Tag 3 von 14).",
"retry_after": 34
}
Aufwärmkurve
Eine frisch verknüpfte Nummer, die sofort hunderte Nachrichten verschickt, ist das auffälligste Muster überhaupt. Neue Kanäle starten deshalb gedrosselt und steigern sich automatisch. Das ist die Standardkurve:
| Zeitraum | Nachrichten pro Tag | Pro Minute |
|---|---|---|
| Tag 1–2 | 20 | 5 |
| Tag 3–4 | 50 | 8 |
| Tag 5–7 | 120 | 10 |
| Tag 8–14 | 300 | 15 |
| ab Tag 15 | 1'000 | 20 |
Antworten auf eingehende Nachrichten zählen milder als Erstkontakte — ein Chat, den die Gegenseite begonnen hat, ist unverdächtig. Braucht dein Anwendungsfall dauerhaft mehr, sprich mit uns: Wir heben die Grenze an, wenn das Versandmuster es trägt. Nicht angehoben wird sie für Werbung an Empfängerlisten — siehe Nutzungsordnung.
Fehlercodes
| HTTP | error | Bedeutung |
|---|---|---|
| 401 | unauthorized | Schlüssel fehlt, ist falsch oder wurde widerrufen. |
| 402 | subscription_required | Testphase abgelaufen oder Zahlung offen. |
| 404 | channel_not_found | Kanal existiert nicht oder gehört nicht zu deinem Konto. |
| 409 | channel_not_connected | Kanal ist qr_pending, disconnected oder banned. |
| 422 | invalid_recipient | Nummer ist ungültig oder nicht bei WhatsApp registriert. |
| 429 | rate_limited | Durchsatzgrenze erreicht, siehe Retry-After. |
| 451 | blocked_by_policy | Versandmuster verstösst gegen die Nutzungsordnung. |
Im Aufbau. Diese Dokumentation beschreibt die Schnittstelle, wie sie gebaut wird. Bis zur Freigabe können sich Details ändern; Änderungen kündigen wir an. Fragen an [email protected].