Draht von edv.sg

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_…"
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.
bannedDie 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:

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
400invalid_requestEin Pflichtfeld fehlt oder eine Adresse ist keine https-Adresse.
400unsupported_typetype ist keiner von text, image, video, voice, document.
401no_keyDer Authorization-Kopf fehlt.
401invalid_keySchlüssel unbekannt, falsch oder gesperrt.
402subscription_requiredTestphase abgelaufen oder Zahlung offen.
403account_suspendedKonto gesperrt.
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.
503capacity_reachedAuf diesem Server ist kein weiterer Kanal mehr frei. Wir melden uns.
503qr_unavailableDer 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].