API
Verbinde deinen Shop oder dein Bestellsystem mit microfulfill, um Bestellungen und Wareneingänge automatisch anzulegen und Bestände abzufragen.
Die vollständige Referenz mit allen Feldern und Antworten ist die API-Referenz (Englisch), die direkt aus dem Code erzeugt wird. In der App findest du sie auch unter /docs/api.
Authentifizierung
Erstelle unter Einstellungen → API-Tokens einen Token und sende ihn bei jeder Anfrage mit:
Authorization: Bearer <dein Token>
Accept: application/jsonHalte Tokens geheim. Wer einen Token hat, kann für deine Organisation handeln. Du kannst einen Token jederzeit löschen. Die API erlaubt 120 Anfragen pro Minute.
Organisation auswählen
Wenn du mehreren Organisationen angehörst, sende die ID der Organisation im Header X-Team-Id. Ohne den Header wird die Organisation verwendet, die du zuletzt in der Weboberfläche genutzt hast.
API v1 (empfohlen)
Basis-URL: https://<deine Domain>/api/v1
Lager
GET /warehouses listet die Lager, an die du Ware und Bestellungen schicken kannst.
Inventar
| Anfrage | Beschreibung |
|---|---|
GET /inventory?search=TEE | Produkte auflisten (seitenweise, per_page bis 100) |
POST /inventory | Produkt anlegen |
GET /inventory/{sku} | Produkt mit Bestand pro Lager |
PATCH /inventory/{sku} | Produkt ändern |
{
"sku": "TEE-L",
"name": "T-Shirt L",
"category": "Apparel",
"weight": 210, "weight_unit": "g",
"length": 30, "width": 20, "height": 2, "dimensions": "cm",
"customs_value": 12.00, "currency": "EUR",
"hs_code": "610910",
"low_stock_threshold": 10
}hs_code braucht 6 bis 10 Ziffern, deren erste sechs eine gültige HS-Unterposition sind (Punkte werden entfernt). category ist optional und frei wählbar.
Bestellungen
| Anfrage | Beschreibung |
|---|---|
GET /orders?status=open | Bestellungen auflisten. Status: open, ready, picking, packed, shipped, cancelled |
POST /orders | Bestellung anlegen (Status open) |
GET /orders/{id} | Bestellung mit Positionen, Label und Sendungsverfolgung |
PATCH /orders/{id} | Offene Bestellung ändern; weggelassene Felder bleiben unverändert |
GET /orders/{id}/rates | Versandtarife für die Bestellung, mit taxes_due_on_delivery (zahlt der Empfänger) und taxes_included |
POST /orders/{id}/label | Label mit rate_id kaufen; die Bestellung wird ready |
GET /orders/{id}/label | Label herunterladen (PDF) |
DELETE /orders/{id}/label | Label stornieren (wird erstattet), die Bestellung geht zurück auf open |
POST /orders/{id}/cancel | Noch nicht versendete Bestellung stornieren (storniert ihr Label) |
GET /orders/{id}/events | Verlauf der Bestellung |
POST /orders/{id}/attachment | PDF fürs Paket anhängen (multipart file oder JSON content_base64), ersetzt ein vorhandenes |
GET /orders/{id}/attachment, DELETE /orders/{id}/attachment | Dokument herunterladen oder entfernen |
So korrigierst du eine Bestellung nach dem Labelkauf (zum Beispiel eine falsche Adresse): Label stornieren, Bestellung mit PATCH ändern, dann ein neues Label kaufen. Optionale Felder beim Stornieren: reason (wird dem Lager angezeigt) und without_refund: true, falls der Label-Anbieter die Stornierung ablehnt.
{
"warehouse_id": 12,
"order_no": "1001",
"shipping_address": {
"name": "Jane Doe",
"line1": "1 Main Street",
"postal_code": "78701",
"city": "Austin",
"state": "TX",
"country": "US",
"email": "jane@example.com"
},
"items": [{ "sku": "TEE-L", "quantity": 2 }]
}Retouren
| Anfrage | Beschreibung |
|---|---|
GET /returns?status=announced | Retouren auflisten. Status: announced, received |
POST /returns | Retoure anmelden (warehouse_id, optional order_id, reason, tracking, items) |
GET /returns/{id} | Retoure mit erwarteten, eingegangenen und eingelagerten Mengen |
Wareneingänge
| Anfrage | Beschreibung |
|---|---|
GET /inbound-shipments | Wareneingänge auflisten |
POST /inbound-shipments | Wareneingang anmelden |
GET /inbound-shipments/{id} | Wareneingang mit gesendeten und eingegangenen Mengen |
{
"warehouse_id": 12,
"reference": "PO-2026-118",
"tracking": { "carrier": "UPS", "number": "1Z999AA10123456784" },
"shipped_at": "2026-11-10",
"items": [{ "sku": "TEE-L", "quantity": 120 }]
}Webhooks
Statt die API regelmäßig abzufragen, lässt du dich von microfulfill benachrichtigen. Hinterlege die URL unter Einstellungen → Webhooks und wähle die Ereignisse (oder alle). microfulfill sendet für jedes Ereignis eine POST-Anfrage mit JSON-Inhalt.
| Ereignis | Geht an | Wann |
|---|---|---|
order.created | Händler, Dienstleister | Eine Bestellung wurde angelegt |
order.label_purchased | Händler, Dienstleister | Das Label wurde gekauft, die Bestellung ist ready |
order.label_voided | Händler, Dienstleister | Das Label wurde storniert, die Bestellung ist wieder open |
order.packed | Händler, Dienstleister | Das Lager hat die Bestellung verpackt |
order.on_hold | Händler, Dienstleister | Das Lager kann die Bestellung nicht versenden; reason nennt den Grund |
order.resumed | Händler, Dienstleister | Das Lager setzt eine angehaltene Bestellung fort |
order.shipped | Händler, Dienstleister | Die Bestellung wurde übergeben |
order.cancelled | Händler, Dienstleister | Die Bestellung wurde storniert |
inbound.received | Händler | Ein Wareneingang wurde eingebucht |
return.announced | Dienstleister | Eine Retoure wurde angemeldet |
return.received | Händler | Eine Retoure wurde eingebucht und geprüft |
{
"id": "5d0c6f4e-0d64-4a3c-9a6b-2b6b2f3a1c11",
"event": "order.shipped",
"created_at": "2026-11-13T10:15:00+00:00",
"team_id": 3,
"data": { "order": { "id": 55, "order_no": "1001", "status": "shipped", "...": "..." } }
}data enthält dieselben Objekte wie die Antworten der API v1 (order, inbound_shipment, return).
Header und Signatur
| Header | Inhalt |
|---|---|
X-Microfulfill-Event | Name des Ereignisses |
X-Microfulfill-Delivery | Eindeutige Zustell-ID, bei Wiederholungen gleich – damit erkennst du Duplikate |
X-Microfulfill-Signature | t=<Unix-Zeit>,v1=<HMAC-SHA256 von "<t>.<Rohinhalt>" mit deinem Signatur-Secret> |
Prüfe jede Anfrage, bevor du ihr vertraust (PHP-Beispiel):
[$t, $v1] = array_map(fn ($part) => explode('=', $part, 2)[1], explode(',', $request->header('X-Microfulfill-Signature')));
$expected = hash_hmac('sha256', $t.'.'.$request->getContent(), $secret);
if (! hash_equals($expected, $v1) || abs(time() - (int) $t) > 300) {
abort(401);
}Antworte innerhalb von 10 Sekunden mit einem 2xx-Status. Andere Antworten werden nach etwa 1 Minute, 5 Minuten, 30 Minuten, 2 Stunden und 12 Stunden wiederholt. Nach 50 fehlgeschlagenen Zustellungen in Folge wird der Webhook pausiert. Die Liste Zustellungen in den Einstellungen zeigt jede Zustellung und erlaubt das erneute Senden.
Fehler
| Status | Bedeutung |
|---|---|
401 | Token fehlt oder ist ungültig |
403 | Kein Zugriff auf diese Organisation oder Ressource |
404 | Nicht gefunden |
422 | Validierung fehlgeschlagen – siehe errors |
429 | Zu viele Anfragen |
Bisherige API
Die Endpunkte des bisherigen Systems (POST /api/orders, GET /api/orders/{order_no}, POST /api/inventory, GET /api/inventory/{sku}, POST /api/inbound, GET /api/inbound/{id}) funktionieren weiterhin mit denselben Feldern und Antworten. Für neue Anbindungen empfehlen wir API v1.