Webhooks: Bestellupdates automatisch empfangen
11 Min. LesezeitAktualisiert
Mit Webhooks schickt Printen.eu Ihnen eine Nachricht, sobald mit einer Bestellung etwas passiert: wartet auf Guthaben, in Produktion, versandt mit Sendungsverfolgung, zugestellt oder storniert. So müssen Sie die API nicht ständig abfragen. In diesem Artikel fügen Sie einen Endpunkt hinzu, prüfen die Signatur und bauen eine Verarbeitung, die mit Wiederholungen umgehen kann.
In diesem Artikel
Wie funktionieren Webhooks?
Sie geben uns eine https-URL Ihres eigenen Servers. Bei jedem Ereignis senden wir dorthin eine POST-Anfrage mit einer JSON-Nachricht. Ihr Server antwortet mit einem 2xx-Status, und wir wissen, dass die Nachricht angekommen ist.
X-Printen-Event: die Art des Events, zum Beispielorder.shipped.X-Printen-Delivery: eine id dieser Zustellung. Praktisch für Ihre Logs.X-Printen-Timestamp: der Sendezeitpunkt in Sekunden seit 1970 (Unix-Zeit).X-Printen-Signature: die Signatur (v1=gefolgt von einem Hex-Code), mit der Sie prüfen, dass die Nachricht wirklich von uns stammt.
Wie fügen Sie einen Endpunkt hinzu?
Registerkarte öffnen
Öffnen Sie in Ihrem Dashboard Webhooks.
URL eingeben
Geben Sie unter URL (https) die Adresse Ihres eigenen Servers ein, zum Beispiel
https://ihredomain.de/printen-webhook.Events wählen
Haken Sie an, welche Events Sie empfangen möchten. Standardmäßig sind
order.shipped,order.payment_failedundorder.awaiting_fundsangehakt.Webhook hinzufügen
Klicken Sie auf Webhook hinzufügen. Sie sehen nun das Geheimnis mit dem Hinweis Speichern Sie dieses Geheimnis jetzt. Sie sehen es nur einmal.
Geheimnis speichern
Legen Sie das Geheimnis sofort in der Konfiguration Ihres Servers ab, zum Beispiel als Umgebungsvariable. Sie brauchen es, um die Signatur zu prüfen.
Sie können einen Endpunkt auch über die API mit POST /webhooks hinzufügen. Lassen Sie events weg oder senden Sie eine leere Liste, erhalten Sie alle Events. Das Geheimnis steht nur in dieser einen Antwort.
curl -X POST https://www.printen.eu/api/reseller/v1/webhooks \
-H "Authorization: Bearer prk_live_..." -H "Content-Type: application/json" \
-d '{"url":"https://example.com/printen-webhook","events":["order.shipped","order.delivered"]}'{
"data": {
"id": "WEBHOOK_ID",
"url": "https://example.com/printen-webhook",
"events": ["order.shipped", "order.delivered"],
"allEvents": false,
"active": true,
"createdAt": "2026-10-10T09:00:00.000Z",
"updatedAt": "2026-10-10T09:00:00.000Z",
"secret": "WEBHOOK_SECRET"
}
}- Die URL muss https verwenden und öffentlich erreichbar sein. Adressen wie
localhost, interne Netzwerkadressen und Namen, die auf.local,.internaloder.lanenden, werden abgelehnt. - Sie können höchstens 10 Endpunkte pro Konto haben.
- Jeder Endpunkt hat sein eigenes Geheimnis.
Welche Events gibt es?
| Event | Wann | Was Sie meist tun |
|---|---|---|
order.created | Eine Bestellung wurde angelegt, über die API, das Dashboard oder einen verbundenen Shop. | Unsere Bestellnummer bei Ihrer eigenen Bestellung speichern. |
order.submitted | Die Bestellung ist bezahlt und geht in die Produktion. | Die Bestellung in Ihrem System auf "in Bearbeitung" setzen. |
order.awaiting_funds | Ihr Guthaben reicht nicht; die Bestellung wartet. | Sich selbst benachrichtigen und aufladen. |
order.payment_failed | Die Zahlung mit Ihrer hinterlegten Karte ist fehlgeschlagen. | Karte prüfen und die Bestellung im Dashboard erneut versuchen. |
order.in_production | Die Produktion hat begonnen. | Den Status anzeigen. Ab jetzt ist keine Stornierung mehr möglich. |
order.shipped | Das Paket ist versandt; tracking enthält Nummer und Link. | Die Sendungsverfolgung an Ihren Kunden senden oder in Ihren Shop eintragen. |
order.delivered | Das Paket wurde zugestellt. | Die Bestellung abschließen. |
order.cancelled | Die Bestellung wurde storniert. | Die Bestellung in Ihrem System stornieren und eine eventuelle Erstattung verbuchen. |
order.file_problem | Es gibt ein Problem mit der Druckdatei. Wir melden uns bei Ihnen. | Ihre Datei prüfen und auf unsere Nachricht antworten. |
Wie sieht eine Nachricht aus?
Jede Nachricht ist gleich aufgebaut. Unten ein Beispiel für order.shipped.
{
"id": "EVENT_ID",
"type": "order.shipped",
"created": "2026-10-10T14:32:05.000Z",
"data": {
"order": {
"id": "ORDER_ID",
"orderNumber": "RS-3F9A1C7B2E",
"externalOrderId": "1001",
"externalOrderNumber": "1001",
"state": "SUBMITTED",
"status": "SHIPPED",
"tracking": {
"code": "3SABCD1234567",
"url": "https://example.com/track/3SABCD1234567"
},
"items": [
{
"productId": "PRODUCT_ID",
"name": "Poster",
"quantity": 1,
"options": { "size": "A2" }
}
]
}
}
}| Feld | Bedeutung |
|---|---|
id | Eindeutige id des Events. Behandeln Sie sie als Text ohne feste Struktur und erkennen Sie damit doppelte Nachrichten. |
type | Die Art des Events, identisch mit dem Header X-Printen-Event. |
created | Wann das Event entstanden ist (ISO 8601). |
data.order.orderNumber | Unsere Bestellnummer, wie sie im Dashboard steht. |
data.order.externalOrderId | Ihre eigene Bestell-id, wenn Sie sie beim Bestellen mitgesendet haben. |
data.order.state und status | Der Status auf Ihrer Seite (zum Beispiel SUBMITTED) und der Produktionsstatus (zum Beispiel SHIPPED). Siehe Bestellstatus. |
data.order.tracking | Sendungsnummer und Tracking-Link, sobald die Bestellung versandt ist. |
Zusätzliche Felder in data | Bei order.awaiting_funds und order.payment_failed steht der Grund in reason. Bei order.cancelled kann refundedCents enthalten sein. In der Sandbox hat order.submitted das Feld test. |
Wie prüfen Sie die Signatur?
Jeder kann eine Anfrage an Ihre URL senden. Prüfen Sie deshalb bei jeder Nachricht die Signatur, bevor Sie etwas damit tun. Die Signatur ist ein HMAC-SHA256 mit dem Geheimnis Ihres Endpunkts.
Header lesen
Lesen Sie
X-Printen-TimestampundX-Printen-Signatureaus der Anfrage.Zeit prüfen
Lehnen Sie die Nachricht ab, wenn der Zeitstempel mehr als 5 Minuten (300 Sekunden) von der aktuellen Zeit abweicht. So kann niemand eine alte Nachricht erneut abspielen.
Erwartete Signatur berechnen
Berechnen Sie mit Ihrem Geheimnis einen HMAC-SHA256 über den Text
timestamp.rawBody: den Zeitstempel, einen Punkt und dann den rohen Body. Stellen Siev1=voran.Sicher vergleichen
Vergleichen Sie das Ergebnis mit
X-Printen-Signaturemit einem Vergleich in konstanter Zeit. Stimmen sie nicht überein, antworten Sie mit 401 und verarbeiten nichts.
import crypto from 'node:crypto';
export function verifyPrintenWebhook(rawBody, headers, secret) {
const timestamp = headers['x-printen-timestamp'];
const signature = headers['x-printen-signature'] || '';
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
const expected = 'v1=' + crypto.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`).digest('hex');
return signature.length === expected.length
&& crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}<?php
function verify_printen_webhook(string $rawBody, string $timestamp, string $signature, string $secret): bool {
if (abs(time() - (int) $timestamp) > 300) return false;
$expected = 'v1=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
return hash_equals($expected, $signature);
}import hashlib, hmac, time
def verify_printen_webhook(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
if abs(time.time() - int(timestamp)) > 300:
return False
expected = "v1=" + hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)Stolperfalle: auf den rohen Body prüfen
Die Signatur wird über den Body berechnet, genau so, wie wir ihn senden, Byte für Byte. Viele Frameworks lesen den Body automatisch als JSON ein. Wandeln Sie dieses JSON danach wieder in Text um, können Leerzeichen, Reihenfolge oder Zeichen leicht abweichen, und die Signatur stimmt nicht mehr.
import express from 'express';
import { verifyPrintenWebhook } from './verify-printen-webhook.js';
const app = express();
// express.raw (not express.json) keeps the body exactly as it was sent
app.post('/printen-webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const rawBody = req.body.toString('utf8');
if (!verifyPrintenWebhook(rawBody, req.headers, process.env.PRINTEN_WEBHOOK_SECRET)) {
return res.status(401).send('invalid signature');
}
const event = JSON.parse(rawBody);
await saveEventForProcessing(event); // store first, process later
res.status(200).send('ok');
});- PHP: Lesen Sie den Body mit
file_get_contents("php://input"), nicht mit$_POST. - Python (Flask): Verwenden Sie
request.get_data()für die rohen Bytes, nichtrequest.json. - Next.js (App Router): Verwenden Sie
await request.text()und erst danachJSON.parse.
Was, wenn Ihr Endpunkt nicht antwortet?
Eine Zustellung ist erfolgreich, wenn Sie innerhalb von 10 Sekunden mit einem 2xx-Status antworten. Alles andere gilt als fehlgeschlagen: ein Timeout, ein Fehlerstatus, aber auch eine Weiterleitung (3xx). Dann versuchen wir es nach diesem Schema erneut.
| Versuch | Wartezeit nach dem vorigen Versuch | Etwa nach dem ersten Versuch |
|---|---|---|
| 1 | Sofort | Start |
| 2 | 1 Minute | 1 Minute |
| 3 | 5 Minuten | 6 Minuten |
| 4 | 15 Minuten | 21 Minuten |
| 5 | 30 Minuten | 51 Minuten |
| 6 | 1 Stunde | 2 Stunden |
| 7 | 2 Stunden | 4 Stunden |
| 8 | 4 Stunden | 8 Stunden |
| 9 | 8 Stunden | 16 Stunden |
| 10 | 8 Stunden | 24 Stunden |
Nach dem zehnten Versuch geben wir dieses Event auf. Ihr Endpunkt wird nie automatisch deaktiviert: Neue Events senden wir weiterhin.
Doppelte und ungeordnete Events verarbeiten
Durch Wiederholungen kann dasselbe Event mehrmals ankommen, und Events können in einer anderen Reihenfolge eintreffen, als sie entstanden sind. Richten Sie Ihre Verarbeitung darauf aus.
- Auf `id` deduplizieren: Speichern Sie die
idjedes verarbeiteten Events. Kommt dieselbeiderneut, antworten Sie mit 2xx und tun sonst nichts. - Reihenfolge über `created` prüfen: Haben Sie für diese Bestellung schon ein neueres Event verarbeitet, überschreiben Sie keinen neueren Status mit einem älteren.
- Keinen Status zurücksetzen: Kommt
order.shippednachorder.delivered, bleibt die Bestellung zugestellt. - Im Zweifel die Bestellung abrufen: Mit
GET /orders/{id}erhalten Sie immer den aktuellen Stand.
Wie testen Sie Ihren Webhook?
Endpunkt vorbereiten
Sorgen Sie dafür, dass Ihre URL öffentlich über https erreichbar ist. Arbeiten Sie lokal, nutzen Sie einen Tunnel-Dienst, der eine öffentliche https-URL an Ihren eigenen Rechner weiterleitet.
Endpunkt hinzufügen
Fügen Sie ihn unter Webhooks hinzu und haken Sie
order.created,order.submittedundorder.cancelledan (oder lassen Sie die Events über die API weg, um alles zu empfangen).Sandbox-Bestellung aufgeben
Geben Sie mit einem Testschlüssel (
prk_test_) eine Bestellung über die API auf. Innerhalb weniger Minuten erhalten Sieorder.createdundorder.submitted(mittestindata).Testbestellung stornieren
Stornieren Sie die Bestellung mit
POST /orders/{id}/cancel. Sie erhalten dannorder.cancelled.Logs prüfen
Prüfen Sie, ob die Signatur stimmte, ob Sie 2xx zurückgegeben haben und ob eine wiederholte Nachricht mit derselben
idsauber ignoriert wurde.
Probleme lösen
Ich erhalte gar nichts.
Prüfen Sie, ob die URL stimmt, https verwendet und aus dem Internet erreichbar ist (kein localhost und keine interne Adresse). Prüfen Sie, ob Sie die richtigen Events angehakt haben. Beachten Sie, dass ein Event erst nach einigen Minuten ankommen kann.
Die Signatur stimmt nie.
Prüfen Sie, ob Sie das Geheimnis dieses Endpunkts verwenden (jeder Endpunkt hat sein eigenes) und ob Sie auf den rohen Body prüfen, nicht auf neu aufgebautes JSON. Siehe der rohe Body.
Ich erhalte Nachrichten doppelt.
Das ist nach einem Timeout oder Fehlerstatus normal. Deduplizieren Sie auf die id des Events. Siehe doppelte Events.
Mein Server sendet eine Weiterleitung.
Wir folgen keinen Weiterleitungen; ein 301 oder 302 gilt als fehlgeschlagen. Verwenden Sie die endgültige URL und achten Sie dabei auf www, einen Schrägstrich am Ende und http zu https.
Ich habe das Geheimnis nicht gespeichert.
Löschen Sie den Endpunkt und fügen Sie ihn neu hinzu. Sie erhalten ein neues Geheimnis; tragen Sie es in Ihre Serverkonfiguration ein.
Ich kann keinen Endpunkt mehr hinzufügen.
Sie haben das Maximum von 10 Endpunkten erreicht. Löschen Sie zuerst einen, den Sie nicht mehr nutzen.
Verwandte Artikel
- Die API: aus Ihrem eigenen System bestellenErstellen Sie einen API-Schlüssel, fragen Sie Preise ab, bestellen Sie mit Idempotency-Key, verwalten Sie eigene Produkte und testen Sie sicher in der Sandbox.
- Bestellungen verfolgen, ändern und Probleme lösenVerfolgen Sie Ihre Bestellungen, verstehen Sie jeden Status, bestellen Sie manuell, stornieren Sie rechtzeitig und lösen Sie Zahlungs-, Adress- oder Schadensfälle.
Kommen Sie nicht weiter?
Wir helfen Ihnen gern, an Werktagen persönlich und meist noch am selben Tag.