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

# Egna kanaler

> Anslut din egen webbutik eller ditt ERP-system till Zippendo med signerade orderpushar och REST API:t.

Med en egen kanal kan din egen webbutik, ditt ERP-system eller någon annan orderkälla som du styr skicka ordrar till Zippendo, när det inte finns någon färdig anslutning för den. Den fungerar i två riktningar:

* **Skicka in ordrar**: ditt system skickar signerade webhook-händelser till kanalens egen **ingest-URL**, eller anropar [REST API:t](/docs/api-reference/overview) (officiella SDK:er finns).
* **Få svar tillbaka**: prenumerera på Zippendos [utgående webhooks](/docs/sv/quickstarts/webhooks) (`shipment.dispatched`, `tracking.updated` med flera) för att ta emot spårningsnummer och statusändringar.

## 1. Skapa kanalen

Klicka på **Orderkanaler** i [app.zippendo.com](https://app.zippendo.com), öppna fliken **Katalog** och klicka på **Skapa kanal** på kortet **Egen kanal**. Eller skapa den via API:t:

```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. Skapa signeringsnyckeln

Klicka på **Skapa nyckel** på kanalens inställningssida, eller anropa `POST /orgs/{orgId}/order-channels/{channelId}/webhook-secret`. Svaret innehåller **ingest-URL:en** och **nyckeln**:

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

<Warning>
  Nyckeln visas **bara en gång**. Spara den i ditt systems konfiguration. Om du ersätter nyckeln skapas en ny och den gamla slutar fungera direkt. Om du återkallar den avvisar ingest-URL:en varje push tills en ny nyckel finns.
</Warning>

## 3. Skicka in ordrar

Skicka en `POST` till ingest-URL:en med två headers:

| Header | Värde |
| - | - |
| `X-Zippendo-Topic` | `order.created`, `order.updated`, `order.cancelled` eller `ping` |
| `X-Zippendo-Signature` | HMAC-SHA256 av **den råa förfrågningskroppen**, hex-kodad, med din signeringsnyckel som nyckel |

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

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

Båda ämnena beter sig likadant: ordern **upsertas** på `externalId`, så omleveranser och uppdateringar i fel ordning är säkra. Skicka den som ditt system tycker är enklast.

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

| Fält | Obligatoriskt | Anmärkningar |
| - | - | - |
| `externalId` | ✔ | Ditt systems order-id, används som idempotensnyckel |
| `orderNumber` | ✔ | Läsbart ordernummer |
| `orderLines` | ✔ | Minst en rad (`name`, `quantity`; valfritt `sku`, `unitPrice`, `weight`, …) |
| `shippingAddress` | | Krävs för att en försändelse ska kunna skapas |
| `shippingMethodTitle` | | Matchas mot kanalens kopplingar för leveranssätt för att välja en fraktregel |
| `serviceCode` | | Uttrycklig kod `{carrier}:{product}:{ruleId}[\|{servicePointId}]`; har företräde framför kopplingen |
| `customerName`, `customerEmail`, `subtotalAmount`, `totalAmount`, `currency`, `notes` | | Valfri metadata |

### Annulleringsdata (`order.cancelled`)

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

### Anslutningstest (`ping`)

Alla signerade kroppar med `X-Zippendo-Topic: ping` returnerar `200 { "received": true }` utan att ändra några data. Använd det för att kontrollera din signeringskod.

### Svar

| Status | Betydelse |
| - | - |
| `200` | Leveransen godkändes och bearbetades |
| `400` | Saknad eller okänd topic-header, data som inte klarade valideringen, eller en kanal som är avstängd (**Kanalen är aktiverad** är av) |
| `401` | Signaturverifieringen misslyckades (fel nyckel, saknad header, eller ingen nyckel skapad än) |
| `404` | Okänt kanal-id |
| `429` | [Gränsen för ingest-frekvens](/docs/api-reference/rate-limits) är nådd. Försök igen efter fördröjningen i `Retry-After` |
| `5xx` | Bearbetningen misslyckades. Försök leveransen igen: upsert gör omleverans säker |

## Vad som händer med en inskickad order

1. Ordern upsertas i kanalen (och ärver kanalens [varumärke](/docs/sv/settings/brands), om det finns något).
2. En fraktregel avgörs: den uttryckliga `serviceCode`, annars kanalens **kopplingar för leveranssätt** matchade mot `shippingMethodTitle`.
3. En försändelse skapas. Försändelser med en matchad regel är redo att skickas. När bara en **Standardavsändaradress** är angiven skapas ett utkast i stället.
4. Om **Skicka försändelser automatiskt** är på för kanalen skickas en försändelse med en matchad regel till transportören direkt, och fraktetiketten hamnar i Zippendo (automatisk utskrift på regeln gäller).

## REST som alternativ

Om du hellre vill ha förfrågan/svar än webhooks skapar du ordrar via API:t med en [API-token](/docs/sv/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"
  }'
```

* En dubblett av `externalId` på samma kanal returnerar **`409 ORDER_EXISTS`**. Behandla det som "redan mottagen".
* Om du anger `shippingRuleId` eller `shippingMethodTitle` (eller slår på **Skicka försändelser automatiskt** för kanalen) skapas försändelsen i samma anrop, precis som vid en push.
* Orderkanaler ingår i det publika API:t, så [SDK:erna](/docs/sv/sdks/overview) täcker varje steg: skapa kanalen, skapa nyckeln, skicka in ordrar och lista försändelser.

## Få tillbaka spårning

Zippendo meddelar ditt system via [utgående webhooks](/docs/sv/quickstarts/webhooks): prenumerera på `shipment.dispatched` och `tracking.updated` under **Inställningar → Webhooks**. Försändelser har ditt ordernummer som sin `reference`, och datan innehåller `orderId` för uppslag.

## Nästa steg

<CardGroup cols={2}>
  <Card title="Utgående webhooks" icon="webhook" href="/docs/sv/quickstarts/webhooks">
    Ta emot spårnings- och statushändelser och verifiera våra signaturer.
  </Card>

  <Card title="API-referens" icon="terminal" href="/docs/api-reference/overview">
    Varje endpoint för orderkanaler och ordrar, med exempel.
  </Card>
</CardGroup>


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