> ## 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.

# Eigen kanalen

> Koppel je eigen webshop of ERP-systeem aan Zippendo met ondertekende bestelpushes en de REST API.

Met een eigen kanaal kan je eigen webshop, ERP of een andere bron van bestellingen die je beheert, bestellingen naar Zippendo sturen, wanneer er geen kant-en-klare koppeling voor is. Het werkt in twee richtingen:

* **Bestellingen binnenstuwen**: je systeem stuurt ondertekende webhook-gebeurtenissen naar de eigen **Ingest-URL** van het kanaal, of roept de [REST API](/docs/api-reference/overview) aan (officiële SDK's beschikbaar).
* **Terughoren**: abonneer je op de [uitgaande webhooks](/docs/nl/quickstarts/webhooks) van Zippendo (`shipment.dispatched`, `tracking.updated` en meer) om trackingnummers en statuswijzigingen te ontvangen.

## 1. Het kanaal aanmaken

Klik in [app.zippendo.com](https://app.zippendo.com) op **Verkoopkanalen**, open het tabblad **Catalogus** en klik op **Kanaal aanmaken** op de kaart **Eigen kanaal**. Of maak het aan via de 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. Het ondertekeningsgeheim genereren

Klik op de instellingenpagina van het kanaal op **Geheim genereren**, of roep `POST /orgs/{orgId}/order-channels/{channelId}/webhook-secret` aan. Het antwoord bevat de **Ingest-URL** en het **geheim**:

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

<Warning>
  Het geheim wordt **maar één keer** getoond. Bewaar het in de configuratie van je systeem. Als je het geheim vervangt, wordt er een nieuw geheim aangemaakt en werkt het oude meteen niet meer. Als je het intrekt, weigert de Ingest-URL elke push tot er weer een nieuw geheim is.
</Warning>

## 3. Bestellingen pushen

Stuur een `POST` naar de Ingest-URL met twee headers:

| Header | Waarde |
| - | - |
| `X-Zippendo-Topic` | `order.created`, `order.updated`, `order.cancelled`, of `ping` |
| `X-Zippendo-Signature` | HMAC-SHA256 van de **onbewerkte request-body**, hex-gecodeerd, met je ondertekeningsgeheim als sleutel |

```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
})
```

### Bestelpayload (`order.created` / `order.updated`)

Beide topics gedragen zich identiek: de bestelling wordt **ge-upsert** op `externalId`, dus opnieuw bezorgde berichten en updates in de verkeerde volgorde zijn veilig. Push wat je systeem het makkelijkst vindt.

```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"
}
```

| Veld | Verplicht | Opmerkingen |
| - | - | - |
| `externalId` | ✔ | Het bestel-ID van je systeem, gebruikt als idempotentiesleutel |
| `orderNumber` | ✔ | Leesbaar bestelnummer |
| `orderLines` | ✔ | Minstens één regel (`name`, `quantity`; optioneel `sku`, `unitPrice`, `weight`, …) |
| `shippingAddress` | | Nodig om een zending aan te maken |
| `shippingMethodTitle` | | Wordt vergeleken met de toewijzingen van verzendmethoden van het kanaal om een verzendregel te kiezen |
| `serviceCode` | | Expliciete code `{carrier}:{product}:{ruleId}[\|{servicePointId}]`; heeft voorrang op de toewijzing |
| `customerName`, `customerEmail`, `subtotalAmount`, `totalAmount`, `currency`, `notes` | | Optionele metagegevens |

### Annuleringspayload (`order.cancelled`)

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

### Verbindingstest (`ping`)

Elke ondertekende body met `X-Zippendo-Topic: ping` geeft `200 { "received": true }` terug zonder gegevens te wijzigen. Gebruik het om je handtekeningcode te controleren.

### Antwoorden

| Status | Betekenis |
| - | - |
| `200` | Bezorging geaccepteerd en verwerkt |
| `400` | Ontbrekende of onbekende topic-header, een payload die de validatie niet doorstond, of een kanaal dat is uitgeschakeld (**Kanaal ingeschakeld** staat uit) |
| `401` | Controle van de handtekening mislukt (verkeerd geheim, ontbrekende header, of er is nog geen geheim aangemaakt) |
| `404` | Onbekend kanaal-ID |
| `429` | [Ingest-limiet](/docs/api-reference/rate-limits) bereikt. Probeer opnieuw na de vertraging in `Retry-After` |
| `5xx` | Verwerking mislukt. Probeer de bezorging opnieuw: dankzij de upsert is opnieuw bezorgen veilig |

## Wat er met een gepushte bestelling gebeurt

1. De bestelling wordt ge-upsert in het kanaal (met het [merk](/docs/nl/settings/brands) van het kanaal, als dat er is).
2. Er wordt een verzendregel bepaald: de expliciete `serviceCode`, anders de **toewijzingen van verzendmethoden** van het kanaal, vergeleken met `shippingMethodTitle`.
3. Er wordt een zending aangemaakt. Zendingen met een gevonden regel zijn klaar om te verzenden. Is er alleen een **Standaard afzenderadres** ingesteld, dan wordt in plaats daarvan een concept aangemaakt.
4. Staat **Zendingen automatisch verzenden** aan voor het kanaal, dan wordt een zending met een gevonden regel direct naar de vervoerder gestuurd en komt het verzendlabel in Zippendo terecht (automatisch printen op de regel is van toepassing).

## REST-alternatief

Heb je liever verzoek en antwoord dan webhooks, maak dan bestellingen aan via de API met een [API-token](/docs/nl/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"
  }'
```

* Een dubbele `externalId` op hetzelfde kanaal geeft **`409 ORDER_EXISTS`** terug. Behandel het als "al ontvangen".
* Als je `shippingRuleId` of `shippingMethodTitle` meegeeft (of **Zendingen automatisch verzenden** aanzet voor het kanaal), wordt de zending in dezelfde aanroep aangemaakt, precies zoals bij een push.
* Verkoopkanalen maken deel uit van de publieke API, dus de [SDK's](/docs/nl/sdks/overview) dekken elke stap: het kanaal aanmaken, het geheim genereren, bestellingen pushen en zendingen opvragen.

## Track & trace terugkrijgen

Zippendo laat je systeem het weten via [uitgaande webhooks](/docs/nl/quickstarts/webhooks): abonneer je op `shipment.dispatched` en `tracking.updated` bij **Instellingen → Webhooks**. Zendingen hebben je bestelnummer als `reference` en de payload bevat de `orderId` om op te zoeken.

## Volgende stappen

<CardGroup cols={2}>
  <Card title="Uitgaande webhooks" icon="webhook" href="/docs/nl/quickstarts/webhooks">
    Ontvang track & trace- en statusgebeurtenissen en controleer onze handtekeningen.
  </Card>

  <Card title="API-referentie" icon="terminal" href="/docs/api-reference/overview">
    Elk endpoint voor verkoopkanalen en bestellingen, met voorbeelden.
  </Card>
</CardGroup>


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