Dokumentation
Schnellstart. Basis-URL ist https://draht.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 draht_live_ (Produktion) oder
draht_test_ (Testkanal).
Authorization: Bearer draht_live_…
Der Schlüssel wird beim Anlegen einmal im Klartext angezeigt und danach nur noch als Prüfsumme gespeichert. Verloren heisst neu erzeugen.
Schlüssel erzeugst und sperrst du in deinem Konto — dort meldest du dich ohne Passwort an, mit einem Link per E-Mail. Alles, was hier beschrieben ist, geht auch von Hand über diese Seite.
1. Kanal anlegen
curl -X POST https://draht.edv.sg/v1/channels \
-H "Authorization: Bearer draht_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://draht.edv.sg/v1/channels/ch_8fa2c1d40b7e/qr \
-H "Authorization: Bearer draht_live_…" > qr.png
# oder den rohen Verknüpfungs-Link, wenn du selbst zeichnen willst
curl "https://draht.edv.sg/v1/channels/ch_8fa2c1d40b7e/qr?format=raw" \
-H "Authorization: Bearer draht_live_…"
Der Code ist rund 60 Sekunden gültig und wird danach automatisch erneuert — hol
ihn bei Ablauf einfach neu ab. Auch ein Kanal, der lange ungescannt lag und auf
disconnected gefallen ist, kommt damit zurück: der erneute Abruf
startet die Sitzung neu und braucht dann ein paar Sekunden länger. Sobald das
Handy den Code gescannt hat, wechselt der Kanal auf connected.
3. Status abfragen
curl https://draht.edv.sg/v1/channels/ch_8fa2c1d40b7e \
-H "Authorization: Bearer draht_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 | Die Nummer ist mit hoher Wahrscheinlichkeit von WhatsApp gesperrt: die Verknüpfung ist dreimal in Folge gescheitert, bei einer Nummer, die vorher verbunden war. Der Kanal nimmt keine Aufträge mehr an. Wir melden uns in diesem Fall bei dir. (WhatsApp meldet eine Sperre nicht als eigenen Zustand — darum die Bedingung aus Wiederholung und Vorgeschichte statt einer Behauptung.) |
4. Nachricht senden
curl -X POST https://draht.edv.sg/v1/messages \
-H "Authorization: Bearer draht_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.
Bilder, Dokumente, Sprachnachrichten
Neben text kennt Draht image, video,
voice und document. Die Datei kommt als
https-Adresse; wir laden sie beim Versand von dort.
curl -X POST https://draht.edv.sg/v1/messages \
-H "Authorization: Bearer draht_live_…" \
-H "Content-Type: application/json" \
-d '{
"channel_id": "ch_8fa2c1d40b7e",
"to": "41791234567",
"type": "document",
"media_url": "https://deine-seite.ch/rechnung-2026-001.pdf",
"filename": "Rechnung 2026-001.pdf",
"caption": "Ihre Rechnung"
}'
filename und caption sind freiwillig; ohne
filename nehmen wir den letzten Teil der Adresse. Eine
Sprachnachricht braucht Opus in einem Ogg-Behälter
(.ogg) — alles andere kommt beim Empfänger als Datei an, nicht als
Sprachnachricht. Für voice gibt es keine Bildunterschrift.
Wir nehmen keine Dateien entgegen und lagern keine. Es gibt bewusst keinen Upload und kein base64: Draht speichert keine Inhalte, und eine hochgeladene Datei wäre genau das. Die Adresse muss zum Sendezeitpunkt erreichbar sein — ein signierter Link mit kurzer Gültigkeit reicht.
Nutzung abfragen
Wo steht der Kanal heute im Tagesbudget? Das musst du nicht aus einer
429-Antwort erraten:
curl https://draht.edv.sg/v1/channels/ch_8fa2c1d40b7e/usage \
-H "Authorization: Bearer draht_live_…"
{
"today": { "sent": 42, "counted": 18.5, "received": 31,
"new_contacts": 4, "remaining": 281.5 },
"queued": 2,
"limits": { "per_day": 300, "per_minute": 15, "min_gap_seconds": 12,
"warmup_day": 9, "warmup_complete": false },
"history": [ … ]
}
sent ist die Zahl der Nachrichten, counted die
gewichtete Summe — an der hängt die Bremse. Antworten in einem Chat, den
die Gegenseite eröffnet hat, zählen nur zu einem Viertel.
5. Webhooks empfangen
Eingehende Nachrichten und Statuswechsel schickt Draht 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 |
|---|---|---|
| 400 | invalid_request | Ein Pflichtfeld fehlt oder eine Adresse ist keine https-Adresse. |
| 400 | unsupported_type | type ist keiner von text, image, video, voice, document. |
| 401 | no_key | Der Authorization-Kopf fehlt. |
| 401 | invalid_key | Schlüssel unbekannt, falsch oder gesperrt. |
| 402 | subscription_required | Testphase abgelaufen oder Zahlung offen. |
| 403 | account_suspended | Konto gesperrt. |
| 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. |
| 503 | capacity_reached | Auf diesem Server ist kein weiterer Kanal mehr frei. Wir melden uns. |
| 503 | qr_unavailable | Der QR-Code ist noch nicht bereit — in ein paar Sekunden erneut abrufen. |
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].