> ## Documentation Index
> Fetch the complete documentation index at: https://www.zippendo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Eigene Kanäle

> Verbinde deinen eigenen Onlineshop oder dein ERP-System mit Zippendo über signierte Bestellübermittlungen und die REST API.

Mit einem eigenen Kanal kann dein eigener Onlineshop, dein ERP-System oder jede andere Bestellquelle, die du kontrollierst, Bestellungen an Zippendo senden, wenn es dafür keine fertige Verbindung gibt. Er funktioniert in zwei Richtungen:

* **Bestellungen senden**: Dein System sendet signierte Webhook-Ereignisse an die eigene **Eingangs-URL** des Kanals oder ruft die [REST API](/docs/api-reference/overview) auf (offizielle SDKs verfügbar).
* **Rückmeldungen erhalten**: Abonniere die [ausgehenden Webhooks](/docs/de/quickstarts/webhooks) von Zippendo (`shipment.dispatched`, `tracking.updated` und mehr), um Sendungsnummern und Statusänderungen zu erhalten.

## 1. Den Kanal erstellen

Klicke in [app.zippendo.com](https://app.zippendo.com) auf **Verkaufskanäle**, öffne den Tab **Katalog** und klicke bei der Karte **Eigener Kanal** auf **Kanal erstellen**. Oder erstelle ihn über die API:

```bash theme={null}
curl -X POST https://api.zippendo.com/orgs/{orgId}/order-channels \
  -H "Authorization: Bearer zipp_..." \
  -H "Content-Type: application/json" \
  -d '{ "name": "My webshop", "type": "custom" }'
```

## 2. Das Signaturgeheimnis generieren

Klicke auf der Einstellungsseite des Kanals auf **Schlüssel generieren** oder rufe `POST /orgs/{orgId}/order-channels/{channelId}/webhook-secret` auf. Die Antwort enthält die **Eingangs-URL** und das **Geheimnis**:

```json theme={null}
{
  "secret": "zwhs_...",
  "webhookUrl": "https://api.zippendo.com/webhooks/order-channels/{channelId}",
  "createdAt": "2026-09-02T12:00:00.000Z"
}
```

<Warning>
  Das Geheimnis wird **nur einmal** angezeigt. Speichere es in der Konfiguration deines Systems. Wenn du das Geheimnis ersetzt, entsteht ein neues, und das alte funktioniert sofort nicht mehr. Wenn du es widerrufst, lehnt die Eingangs-URL jede Übermittlung ab, bis es ein neues Geheimnis gibt.
</Warning>

## 3. Bestellungen senden

Sende einen `POST` an die Eingangs-URL mit zwei Headern:

| Header | Wert |
| - | - |
| `X-Zippendo-Topic` | `order.created`, `order.updated`, `order.cancelled` oder `ping` |
| `X-Zippendo-Signature` | HMAC-SHA256 des **rohen Request-Body**, hexadezimal kodiert, mit deinem Signaturgeheimnis als Schlüssel |

```javascript theme={null}
import crypto from "node:crypto"

const body = JSON.stringify(order)
const signature = crypto.createHmac("sha256", process.env.ZIPPENDO_WEBHOOK_SECRET)
  .update(body)
  .digest("hex")

await fetch(webhookUrl, {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "X-Zippendo-Topic": "order.created",
    "X-Zippendo-Signature": signature
  },
  body
})
```

### Bestell-Payload (`order.created` / `order.updated`)

Beide Topics verhalten sich gleich: Die Bestellung wird anhand von `externalId` **angelegt oder aktualisiert**, deshalb sind erneute Zustellungen und Aktualisierungen in falscher Reihenfolge unproblematisch. Sende, was für dein System einfacher ist.

```json theme={null}
{
  "externalId": "SO-10422",
  "orderNumber": "#1042",
  "customerName": "Anna Jensen",
  "customerEmail": "anna@example.dk",
  "shippingAddress": {
    "name": "Anna Jensen",
    "address1": "Nørregade 12",
    "city": "København",
    "postalCode": "1165",
    "countryCode": "DK",
    "phone": "+45 12 34 56 78"
  },
  "orderLines": [
    { "name": "Wool Sweater", "sku": "SKU-1042-BLK", "quantity": 2, "unitPrice": 499.0, "weight": 0.5, "weightUnit": "kg" }
  ],
  "totalAmount": 998.0,
  "currency": "DKK",
  "shippingMethodTitle": "GLS Hjemmelevering"
}
```

| Feld | Erforderlich | Hinweise |
| - | - | - |
| `externalId` | ✔ | Die Bestell-ID deines Systems, wird als Idempotenzschlüssel verwendet |
| `orderNumber` | ✔ | Lesbare Bestellnummer |
| `orderLines` | ✔ | Mindestens eine Position (`name`, `quantity`; optional `sku`, `unitPrice`, `weight`, …) |
| `shippingAddress` | | Wird gebraucht, damit eine Sendung erstellt werden kann |
| `shippingMethodTitle` | | Wird mit den Versandart-Zuordnungen des Kanals abgeglichen, um eine Versandregel auszuwählen |
| `serviceCode` | | Expliziter Code `{carrier}:{product}:{ruleId}[\|{servicePointId}]`; hat Vorrang vor der Zuordnung |
| `customerName`, `customerEmail`, `subtotalAmount`, `totalAmount`, `currency`, `notes` | | Optionale Metadaten |

### Stornierungs-Payload (`order.cancelled`)

```json theme={null}
{ "externalId": "SO-10422" }
```

### Verbindungstest (`ping`)

Jeder signierte Body mit `X-Zippendo-Topic: ping` liefert `200 { "received": true }`, ohne Daten zu verändern. Nutze das, um deinen Signaturcode zu prüfen.

### Antworten

| Status | Bedeutung |
| - | - |
| `200` | Zustellung angenommen und verarbeitet |
| `400` | Fehlender oder unbekannter Topic-Header, ein Payload, der die Validierung nicht bestanden hat, oder ein Kanal, der ausgeschaltet ist (**Kanal aktiviert** ist aus) |
| `401` | Signaturprüfung fehlgeschlagen (falsches Geheimnis, fehlender Header oder noch kein Geheimnis erzeugt) |
| `404` | Unbekannte Kanal-ID |
| `429` | [Ratenlimit für den Eingang](/docs/api-reference/rate-limits) erreicht. Versuche es nach der Wartezeit aus `Retry-After` erneut |
| `5xx` | Verarbeitung fehlgeschlagen. Stelle die Lieferung erneut zu: Dank des Anlegens oder Aktualisierens ist eine erneute Zustellung unproblematisch |

## Was mit einer gesendeten Bestellung passiert

1. Die Bestellung wird im Kanal angelegt oder aktualisiert (und übernimmt die [Marke](/docs/de/settings/brands) des Kanals, falls vorhanden).
2. Eine Versandregel wird ermittelt: der explizite `serviceCode`, sonst die **Versandart-Zuordnungen** des Kanals, abgeglichen mit `shippingMethodTitle`.
3. Eine Sendung wird erstellt. Sendungen mit einer passenden Regel sind bereit zum Versenden. Wenn nur eine **Standard-Absenderadresse** festgelegt ist, wird stattdessen ein Entwurf erstellt.
4. Wenn **Sendungen automatisch versenden** für den Kanal eingeschaltet ist, wird eine Sendung mit passender Regel sofort an den Versanddienstleister gesendet, und das Versandetikett landet in Zippendo (der automatische Druck der Regel gilt).

## REST-Alternative

Wenn du Request/Response gegenüber Webhooks bevorzugst, erstelle Bestellungen über die API mit einem [API-Token](/docs/de/settings/api-settings):

```bash theme={null}
curl -X POST https://api.zippendo.com/orgs/{orgId}/orders \
  -H "Authorization: Bearer zipp_..." \
  -H "Content-Type: application/json" \
  -d '{
    "orderChannelId": "{channelId}",
    "orderNumber": "#1042",
    "externalId": "SO-10422",
    "orderLines": [{ "name": "Wool Sweater", "quantity": 2 }],
    "shippingAddress": { "name": "Anna Jensen", "address1": "Nørregade 12", "city": "København", "postalCode": "1165", "countryCode": "DK" },
    "shippingMethodTitle": "GLS Hjemmelevering"
  }'
```

* Eine doppelte `externalId` im selben Kanal liefert **`409 ORDER_EXISTS`**. Behandle das als „bereits empfangen“.
* Wenn du `shippingRuleId` oder `shippingMethodTitle` übergibst (oder **Sendungen automatisch versenden** für den Kanal einschaltest), wird die Sendung im selben Aufruf erstellt, genau wie bei einer Übermittlung.
* Verkaufskanäle sind Teil der öffentlichen API, deshalb decken die [SDKs](/docs/de/sdks/overview) jeden Schritt ab: Kanal erstellen, Geheimnis generieren, Bestellungen senden und Sendungen auflisten.

## Sendungsverfolgung zurückbekommen

Zippendo benachrichtigt dein System über [ausgehende Webhooks](/docs/de/quickstarts/webhooks): Abonniere `shipment.dispatched` und `tracking.updated` unter **Einstellungen → Webhooks**. Sendungen tragen deine Bestellnummer als `reference`, und der Payload enthält die `orderId` zum Nachschlagen.

## Nächste Schritte

<CardGroup cols={2}>
  <Card title="Ausgehende Webhooks" icon="webhook" href="/docs/de/quickstarts/webhooks">
    Empfange Ereignisse zu Sendungsverfolgung und Status und prüfe unsere Signaturen.
  </Card>

  <Card title="API-Referenz" icon="terminal" href="/docs/api-reference/overview">
    Jeder Endpunkt für Verkaufskanäle und Bestellungen, mit Beispielen.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.