Tell von edv.sg

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_…"
StatusBedeutung
qr_pendingKanal angelegt, wartet auf das Scannen des QR-Codes.
connectedVerknüpft und sendebereit.
disconnectedVerbindung unterbrochen — meist, weil die Verknüpfung im Handy entfernt oder das Gerät zu lange offline war. Neu scannen.
bannedWhatsApp 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:

ZeitraumNachrichten pro TagPro Minute
Tag 1–2205
Tag 3–4508
Tag 5–712010
Tag 8–1430015
ab Tag 151'00020

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

HTTPerrorBedeutung
401unauthorizedSchlüssel fehlt, ist falsch oder wurde widerrufen.
402subscription_requiredTestphase abgelaufen oder Zahlung offen.
404channel_not_foundKanal existiert nicht oder gehört nicht zu deinem Konto.
409channel_not_connectedKanal ist qr_pending, disconnected oder banned.
422invalid_recipientNummer ist ungültig oder nicht bei WhatsApp registriert.
429rate_limitedDurchsatzgrenze erreicht, siehe Retry-After.
451blocked_by_policyVersandmuster 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].