Ticket-API: Support in Ihre App einbauen
Ihre App legt Tickets per REST-API an, zeigt dem Kunden seine Tickets mit Verlauf und überträgt seine Antworten und Anhänge. Die Schnittstelle ist einfaches JSON über HTTPS, jede App hat einen eigenen Schlüssel. Ein Formular mit Verlauf ist meist in ein bis drei Stunden eingebaut, das fertige Widget in wenigen Minuten. Webhooks melden Ihrer App jede Antwort sofort.
Konto für den API-Schlüssel anlegen
Grundregeln
- Basis-Adresse:
https://idoticket.de/api/v1 - Jeder Aufruf mit
Authorization: Bearer it_…. Den Schlüssel bekommen Sie im Helpdesk unter Einstellungen › Apps. - Die API wird von Ihrem Server aufgerufen, nie aus dem Browser. Der Schlüssel darf Ihren Server nicht verlassen.
- Sie nennen immer Ihre eigene Kundennummer. Ein Kunde sieht nur seine Tickets in dieser App, interne Notizen nie.
- Fehler kommen immer als
{"fehler": "Text für Menschen"}mit passendem HTTP-Code.
Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
| GET | /ping | Schlüssel prüfen, nennt die App |
| POST | /tickets | Ticket anlegen |
| GET | /tickets?kunde=K-1 | Tickets des Kunden, neueste Aktivität zuerst |
| GET | /tickets/{nummer}?kunde=K-1 | Ticket mit Verlauf |
| POST | /tickets/{nummer}/nachrichten | Kunde antwortet |
| GET | /tickets/{nummer}/anhaenge/{id}?kunde=K-1 | Anhang abrufen, mit Range für Videos |
Ticket anlegen
POST /api/v1/tickets
{
"kunde": { "id": "K-1", "name": "Klara Kunde", "email": "klara@beispiel.de", "firma": "Beispiel GmbH" },
"betreff": "Export bleibt bei 90 % stehen",
"text": "Seit gestern bleibt der Export stehen.",
"prioritaet": "normal",
"kategorie": "Export",
"kontext": { "seite": "/konto/export", "browser": "Firefox 133", "tarif": "Team", "version": "1.4" }
}
Pflicht sind kunde.id, betreff (bis 200 Zeichen) und text (bis 20.000 Zeichen). kontext ist frei (bis 8 KB) und steht im Helpdesk neben dem Ticket. Hat der Kunde eine E-Mail-Adresse, bekommt er die Eingangsbestätigung und jede Antwort per Mail.
Die Antwort (201) enthält das Ticket mit Nummer, Status und Verlauf. antwort_offen: true heißt: Das Team hat zuletzt geschrieben, zeigen Sie dem Kunden zum Beispiel „1 neue Antwort“.
Beispiel in PHP
$antwort = (new GuzzleHttp\Client())->post('https://idoticket.de/api/v1/tickets', [
'headers' => ['Authorization' => 'Bearer ' . $_ENV['IDOTICKET_SCHLUESSEL']],
'json' => [
'kunde' => ['id' => (string) $konto['id'], 'name' => $konto['name'], 'email' => $konto['email']],
'betreff' => $betreff,
'text' => $text,
'kontext' => ['seite' => $_SERVER['HTTP_REFERER'] ?? null, 'tarif' => $konto['plan']],
],
]);
$ticket = json_decode((string) $antwort->getBody(), true)['ticket'];
Anhänge: Screenshots und Videos
Beim Anlegen und beim Antworten sind bis zu zehn Anhänge je Nachricht möglich: Bilder (JPEG, PNG, GIF, WebP, HEIC), Videos (MP4, WebM, MOV) bis 250 MB, sonst PDF, Text, CSV, JSON, XML, ZIP und Office-Dateien bis 25 MB. Den Typ erkennen wir am Inhalt. Kleine Dateien gehen als Base64 im JSON ("anhaenge": [{"name": "Screenshot.png", "inhalt": "iVBOR…"}]), Videos besser als multipart/form-data:
curl -H "Authorization: Bearer it_…" \
-F 'daten={"kunde":"K-1","text":"Hier die Aufnahme"}' \
-F 'anhaenge[]=@aufnahme.mp4' \
https://idoticket.de/api/v1/tickets/1001/nachrichten
Im Verlauf hat jede Nachricht anhaenge mit id, name, typ, art (bild, video, dokument), groesse und pfad. Ihr Server ruft pfad mit demselben Schlüssel ab und reicht die Datei an den Kunden durch. Range-Anfragen funktionieren, Videos lassen sich spulen.
Status
neu → offen → wartet (auf Kunde) → geloest → geschlossen. Antwortet der Kunde auf ein gelöstes oder wartendes Ticket, wird es wieder offen. Ein geschlossenes Ticket nimmt keine Antwort mehr an (409), dann legen Sie ein neues an.
Fehlercodes
| Code | Bedeutung |
|---|---|
| 400 | Body ist kein JSON-Objekt |
| 401 | Schlüssel fehlt, ist falsch oder die App ist deaktiviert |
| 402 | Das Konto hat kein laufendes Abo (Testphase abgelaufen oder gekündigt) |
| 404 | Ticket gibt es für diesen Kunden in dieser App nicht |
| 409 | Ticket ist geschlossen |
| 413 | Datei oder Anfrage zu groß |
| 415 | Dateityp nicht erlaubt |
| 422 | Eingabe ungültig, der Text sagt, was fehlt |
| 429 | zu viele Fehlversuche mit falschem Schlüssel |
Widget: Support mit einer Zeile
Statt eines eigenen Formulars binden Sie das fertige Widget ein. Es zeigt einen Hilfe-Knopf in der Farbe Ihrer App und öffnet ein Fenster, in dem Ihre Kunden schreiben, Screenshots oder Videos anhängen und ihre bisherigen Anfragen mit allen Antworten sehen. Sie schalten es im Helpdesk unter Einstellungen › Apps › Widget & Webhooks ein, dort steht auch der fertige Einbau-Code.
<script src="https://idoticket.de/widget/skript" data-app="iw_…" async></script>
Ohne weitere Angaben schreiben Besucher mit Name und E-Mail und bekommen die Antwort per Mail (abschaltbar). Ist der Kunde in Ihrer App angemeldet, signiert Ihr Server seine Kundennummer mit dem Signatur-Geheimnis der App. Dann sieht er im Widget alle seine Tickets, auch die aus der API:
<?php
$zeit = time();
$signatur = hash_hmac('sha256', $konto['id'] . '|' . strtolower($konto['email']) . '|' . $zeit, $_ENV['IDOTICKET_GEHEIMNIS']);
?>
<script src="https://idoticket.de/widget/skript" data-app="iw_…"
data-kunde-id="<?= htmlspecialchars($konto['id']) ?>" data-kunde-name="<?= htmlspecialchars($konto['name']) ?>"
data-kunde-email="<?= htmlspecialchars($konto['email']) ?>" data-zeit="<?= $zeit ?>" data-signatur="<?= $signatur ?>" async></script>
- Das Fenster erscheint nur auf der Domain der App und ihren Subdomains, auf jeder anderen Seite verweigert der Browser es.
- Die Signatur gilt 24 Stunden. Eine falsche oder fremde Kundennummer weisen wir ab.
- Weitere Angaben:
data-farbe,data-text(Beschriftung),data-position="links",data-knopf="aus"für einen eigenen Knopf mitIDOTicketWidget.oeffnen(). - Das Widget setzt keine Cookies und lädt nichts von Dritten.
Webhooks: Ihre App erfährt es sofort
Tragen Sie unter Widget & Webhooks eine https-Adresse ein. Wir schicken dann ein JSON per POST, sobald etwas passiert:
| Ereignis | Wann |
|---|---|
ticket.antwort | Das Team hat dem Kunden geantwortet (nie bei internen Notizen). Mit nachricht und dem neuen Status. |
ticket.status | Status im Helpdesk geändert, mit status_vorher |
ticket.angelegt | Ticket kam über das Widget oder per E-Mail (über die API angelegte kennt Ihre App schon) |
test | Testsendung aus den Einstellungen |
{
"id": "evt_5f2c…",
"ereignis": "ticket.antwort",
"erstellt_am": "2026-10-31T10:15:00+01:00",
"app": { "kennung": "mailarchiv-leicht", "name": "Mailarchiv leicht" },
"kunde": { "id": "K-1", "email": "klara@beispiel.de" },
"ticket": { "nummer": 1001, "betreff": "Export bleibt bei 90 % stehen", "status": "wartet", "antwort_offen": true, … },
"nachricht": { "id": 42, "von": "mitarbeiter", "name": "Martin", "text": "Hallo Klara, …", "anhaenge": [] }
}
Jede Sendung trägt den Kopf IDO-Ticket-Signatur: t=<Unix-Zeit>,v1=<HMAC>. v1 ist HMAC-SHA256 über t + "." + Body mit dem Signatur-Geheimnis. Prüfen Sie die Signatur und dass t höchstens fünf Minuten alt ist. Antworten Sie mit einem 2xx-Status, sonst versuchen wir es nach 1, 5 und 30 Minuten, 2, 6, 12 und 24 Stunden erneut. Dasselbe Ereignis kann dabei zweimal ankommen, die id bleibt gleich.
$body = file_get_contents('php://input');
parse_str(str_replace(',', '&', $_SERVER['HTTP_IDO_TICKET_SIGNATUR'] ?? ''), $s);
$soll = hash_hmac('sha256', ($s['t'] ?? '') . '.' . $body, $_ENV['IDOTICKET_GEHEIMNIS']);
if (!hash_equals($soll, $s['v1'] ?? '') || abs(time() - (int) ($s['t'] ?? 0)) > 300) {
http_response_code(400);
exit;
}
Fragen zur Anbindung beantworten wir gern über das Kontaktformular.