Hoppa till innehållet
Afi Planner

Utvecklare

Guide för API-integration

Skicka order från din butik, ditt affärssystem eller lagersystem, planera och skicka rutterna och få tillbaka varje status via webhook. Varje steg har ett curl-kommando som du kan köra som det är.

API-adress

https://app.afi.io/api/v1

Varje anrop

Authorization: Bearer afi_…

Fullständig referens: openapi.json (OpenAPI 3.1, version 1.10.0), som de flesta verktyg kan importera för att generera en klient. JSON in och ut, tider i UTC (ISO 8601), metriska enheter.

1Innan du börjar: en API-nyckel

Öppna Inställningar → Utvecklare i Afi Planner, ge nyckeln ett namn (systemet som använder den) och klicka på Skapa nyckel. Kopiera den direkt: den visas bara en gång. Ägaren skapar nycklar, eller en teammedlem vars roll har behörigheten Utvecklare.

  • En nyckel agerar för ditt företag med behörigheterna hos personen som skapade den, aldrig mer än en transportledares: den kan lägga till order, planera och skicka rutter, men aldrig ändra ditt team, fakturering eller inställningar.
  • Välj Endast läsning för ett system som bara läser (alla andra metoder svarar 403 key_read_only), och ett utgångsdatum om du vill.
  • Byt nyckel skapar en ny nyckel med samma namn och låter den gamla fungera i 1 eller 24 timmar, så att du kan byta utan avbrott.

Förvara nyckeln på din server, aldrig i en webbläsare eller en mobilapp. Exemplen nedan läser den, API-adressen och en leveransdag från ditt skal:

Skal
export AFI_API_KEY="afi_…"          # your key, from Settings → Developers
export AFI="https://app.afi.io/api/v1"
export DAY="2026-11-03"              # a delivery day, YYYY-MM-DD: today or later

Kontrollera nyckeln. /me svarar med ditt företag, nyckeln och ditt pakets gränser:

Anrop
curl "$AFI/me" -H "Authorization: Bearer $AFI_API_KEY"
Svar 200
{
  "company": { "id": 1, "name": "Bayside Fresh Co." },
  "key": { "id": 1, "name": "Shop backend", "prefix": "afi_wzPUFcTM", "scope": "full", "expiresAt": null },
  "subscription": { "state": "trial", "limits": { "maxStopsPerPlan": 500, "optimizationsPerMonth": 2000, … } }
}

Ingen kod än? Inställningar → Utvecklare → Testa nyckeln skickar färdiga anrop med din nyckel och visar svaret och curl-kommandot. Ladda ner Postman-samling ger dig varje anrop i den här guiden, uppsatt för ditt företag (nyckeln är en variabel du fyller i), och API-anrop listar varje anrop de senaste 3 dagarna.

2Skicka order för en dag

ref är ditt eget order-ID och day leveransdagen. Skicka en address, eller lat och lng, eller båda: med koordinater slås adressen inte upp igen. Tidsfönster är lokal tid på adressen (HH:MM).

Anrop
curl -X POST "$AFI/orders" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: SHOP-1042-$DAY" \
  -d @- <<EOF
{
  "ref": "SHOP-1042",
  "day": "$DAY",
  "name": "Olivia Shah",
  "phone": "+14155550142",
  "email": "[email protected]",
  "address": "1355 Market St, San Francisco, CA 94103",
  "lat": 37.7768,
  "lng": -122.4166,
  "timeWindows": [{ "start": "09:00", "end": "12:00" }],
  "packages": 2,
  "weightKg": 4.5,
  "customerNote": "Leave with the front desk"
}
EOF
Svar 201
{
  "id": 1,
  "ref": "SHOP-1042",
  "day": "2026-11-03",
  "status": "new",
  "test": false,
  "phoneIssue": null,
  "addressIssue": null,
  "timeZone": "America/Los_Angeles",
  "timeWindows": [{ "start": "09:00", "end": "12:00", "startAt": "2026-11-03T09:00:00-08:00", "endAt": "2026-11-03T12:00:00-08:00" }],
  "route": null,
  "draftRoute": null,
  "trackingUrl": "https://app.afi.io/t/1.bfc92ec4c7c1da1b30b0ccce",
  …
}

Spara id: det är ordern i alla senare anrop. En ref pekar ut en öppen order över alla dagar, inte en per dag: skickar du en ref som har en öppen order någon dag uppdateras den ordern (200) och behåller sin dag, även om den har flyttats sedan dess (ändra dagen med PATCH /orders/{id}). En order är öppen tills den är levererad, misslyckad eller överhoppad; en som inte besöktes på en dag som är över är inte öppen. När en förare har arbetat med ordern blir svaret 409 order_worked och PATCH /orders/{id} ändrar dess fält.

Utan öppen order blir en ref vars order misslyckades under de 14 dagarna före den nya day nästa försök för den ordern, med samma spårningslänk; annars (ett äldre misslyckande eller en levererad order) blir det en ny order (201). Vill du alltid skapa en ny order skickar du "acceptDuplicateRef": true: då pekar ref inte längre ut en enda order, så spara id.

FältVad det är
refDitt order-ID, unikt bland öppna order alla dagar (versaler och omgivande mellanslag ignoreras)
dayLeveransdag, YYYY-MM-DD, i dag eller senare
name, phone, emailKunden. Telefonnummer sparas i E.164; ett nummer som inte kan ta emot sms sparas med phoneIssue
address, unit, lat, lngVar leveransen ska ske: address krävs om du inte skickar lat och lng
timeWindows1 eller 2 fönster { "start": "09:00", "end": "12:00" }; ett slut före starten slutar nästa dag
serviceMinutesTid vid dörren, när den skiljer sig från företagets standard
packages, weightKg, volumeM3Lasten, i metriska enheter oavsett vad appen visar
skills, priorityKompetenser en förare behöver; normal eller high
pickupAt, pickupVar paketet hämtas först: namnet eller id för en sparad hämtplats, "depot", en adress eller "none"
customerNote, leaveAtDoorKundens instruktioner till föraren, t.ex. från din kassa
notifyCustomerfalse: inga sms, WhatsApp eller e-post till den här kunden
notes, barcodes, customFields, access, languageAnteckningar till föraren, paketens streckkoder, dina egna fält, portkod och ingång, kundens språk (en, sv, vi, es)

Skickar du en ref igen ändras de fält du skickar; de andra blir som de var. Ett fält som API:t inte känner till avvisas (400 invalid_request): lägg dina egna uppgifter i customFields, som kommer tillbaka på ordern och i varje webhook.

Många order på en gång: POST /orders/batch tar upp till 1 000, var och en med sin egen day. Varje rad får sitt eget resultat, så en felaktig rad stoppar inte de andra:

Anrop
curl -X POST "$AFI/orders/batch" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @- <<EOF
{
  "orders": [
    { "ref": "SHOP-1043", "day": "$DAY", "name": "Marcus Lee", "address": "600 Guerrero St, San Francisco, CA 94110", "lat": 37.7612, "lng": -122.4241 },
    { "ref": "SHOP-1044", "day": "$DAY", "name": "Ana Torres", "address": "2101 Irving St, San Francisco, CA 94122", "lat": 37.7637, "lng": -122.4825,
      "timeWindows": [{ "start": "13:00", "end": "17:00" }] },
    { "ref": "SHOP-1045", "day": "$DAY", "name": "Jordan Price", "lat": 120, "lng": -122.4752 }
  ]
}
EOF
Svar 200
{
  "results": [
    { "row": 1, "ref": "SHOP-1043", "id": 2, "result": "created", "addressIssue": null },
    { "row": 2, "ref": "SHOP-1044", "id": 3, "result": "created", "addressIssue": null },
    { "row": 3, "ref": "SHOP-1045", "result": "error", "error": "Latitude can't be more than 90", "code": "invalid_order", "field": "lat" }
  ],
  "created": 2, "updated": 0, "failed": 1
}

En ref som förekommer två gånger i samma batch räknas en gång, oavsett radernas dagar: de senare raderna får ref_repeated. Med acceptDuplicateRef (bredvid orders) gäller det bara samma dag.

Testar du mot ditt riktiga företag? Låt ref börja med API-TEST- (till exempel API-TEST-0001): en sådan order planeras aldrig, skickar aldrig meddelanden till kunden, räknas ingenstans och raderas efter 3 dagar. Dess webhooks skickas ändå, med "test": true.

3Planera rutterna

Lista dina förare, välj vem som arbetar den dagen och starta sedan planeringen. Planeringen körs i bakgrunden: svaret är ett jobb att följa.

Förare läggs till i appen, på sidan Förare. API:t listar dem och väljer vem som jobbar varje dag; utan vald förare svarar planeringen 400 (“Choose at least one driver for this plan.”).

Anrop
curl "$AFI/drivers" -H "Authorization: Bearer $AFI_API_KEY"

curl -X PUT "$AFI/days/$DAY/drivers" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "driverIds": [1, 2] }'

curl -X POST "$AFI/days/$DAY/optimize" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Idempotency-Key: plan-$DAY-1"
Svar 202
{ "jobId": "75d50077-6549-449a-bccc-80cc661174c6", "state": "running", "planId": 1, "day": "2026-11-03" }

Fråga efter jobbet med några sekunders mellanrum tills state är done (eller failed, med orsaken i error). En dag med 176 stopp och 8 förare tar ungefär 40 sekunder; mindre dagar går fortare.

Anrop
curl "$AFI/jobs/$JOB_ID" -H "Authorization: Bearer $AFI_API_KEY"
Svar 200
{ "id": "75d50077-…", "state": "done", "kind": "optimize", "planId": 1, "day": "2026-11-03", "error": null, … }

GET /days/{day}/plan ger rutterna. Tills de skickas ligger de i draft: routes är alltid det förarna har, och dina transportledare kan fortfarande ändra utkastet i appen.

Anrop
curl "$AFI/days/$DAY/plan" -H "Authorization: Bearer $AFI_API_KEY"
Svar 200
{
  "day": "2026-11-03", "planId": 1, "plannedAt": null, "dispatchedAt": null,
  "routes": [],
  "notOnRoute": [],
  "draft": {
    "plannedAt": "2026-11-02T22:12:43Z",
    "routes": [
      { "driverId": 1, "driverName": "Daniel Kim", "start": "2026-11-03T16:32:57Z", "end": "2026-11-03T17:12:57Z",
        "distanceMeters": 12623, "travelSeconds": 1233, "breaks": [],
        "visits": [
          { "position": 1, "orderId": 2, "ref": "SHOP-1043", "kind": "delivery", "arrival": "2026-11-03T16:39:51Z", "departure": "2026-11-03T16:44:51Z" },
          { "position": 2, "orderId": 1, "ref": "SHOP-1042", "kind": "delivery", "arrival": "2026-11-03T17:00:00Z", "departure": "2026-11-03T17:05:00Z" }
        ] }
    ],
    "notOnRoute": []
  }
}

4Skicka rutterna till förarna

När du skickar får varje förare sin rutt i förarappen, eller en länk som öppnas på vilken telefon som helst (url). Anropa igen efter en ändring för att skicka uppdateringarna.

Anrop
curl -X POST "$AFI/days/$DAY/dispatch" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Idempotency-Key: send-$DAY-1"
Svar 200
{
  "day": "2026-11-03",
  "dispatchedAt": "2026-11-03T14:02:57Z",
  "drivers": [
    { "driverId": 1, "url": "https://app.afi.io/d/1.3uu3J7…" },
    { "driverId": 2, "url": "https://app.afi.io/d/2.Qm9xk2…" }
  ]
}

En dag med order men utan planerade rutter svarar 400 (”Plan the routes first”), en dag som är över 409 day_over.

5Se var varje order står

En order, med sin rutt som den skickades till föraren, ETA, varje förarrapport med leveransbevis och varje försök:

Anrop
curl "$AFI/orders/$ORDER_ID" -H "Authorization: Bearer $AFI_API_KEY"
Svar 200
{
  "id": 1, "ref": "SHOP-1042", "status": "assigned",
  "route": { "driverId": 1, "driverName": "Daniel Kim", "position": 2, "eta": "2026-11-03T17:00:00Z", "liveEta": null, "pickupEta": null },
  "draftRoute": null,
  "trackingUrl": "https://app.afi.io/t/1.bfc92ec4c7c1da1b30b0ccce",
  "events": [],
  "attempts": [{ "number": 1, "orderId": 1, "day": "2026-11-03", "current": true, "moved": false, "outcome": null }],
  …
}

Alla order för en dag, eller en ref. Med limit (1–1 000) kommer svaret en sida i taget: skicka dess nextCursor som cursor för nästa sida; den är null på den sista.

Anrop
curl "$AFI/orders?day=$DAY&ref=SHOP-1042" -H "Authorization: Bearer $AFI_API_KEY"

curl "$AFI/orders?day=$DAY&status=assigned&limit=100" -H "Authorization: Bearer $AFI_API_KEY"

URL-koda en ref i en fråga: Shopifys #1001 blir %231001 (encodeURIComponent). Okodat tappas allt efter # och svaret blir dagens alla ordrar.

Statusar:

statusBetydelse
newÄnnu inte på en rutt som förarna har
assignedPå en rutt som skickats till en förare
unassignedDe skickade rutterna utelämnade den
on_holdHålls utanför planeringen (POST /orders/{id}/hold, /release)
needs_fix, locatingAdressen kunde inte användas (addressIssue säger varför), eller slås upp
to_pickup, at_pickup, picked_up, pickup_failedFörarens rapporter vid hämtningen
in_transit, at_deliveryPå väg, vid dörren
delivered, failed, skippedKlar: events har orsaken, foton, signatur och mottagare
cancelledAvbokad: cancellation har reason, note, vem som avbokade (by), när (cancelledAt) och returnToDepot när paketet var i en bil

Ändra en order med PATCH /orders/{id} (bara fälten du skickar), avboka den med POST /orders/{id}/cancel (en reason och en valfri note: den finns kvar, med status cancelled), ta bort en order som lagts in av misstag med DELETE /orders/{id} (en som redan skickats till en förare svarar 409 order_sent: avboka den i stället), och skicka ut en misslyckad order igen med POST /orders/{id}/redeliver: ett nytt försök nästa arbetsdag (eller den day du skickar), med samma spårningslänk.

Anrop
curl -X PATCH "$AFI/orders/$ORDER_ID" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "timeWindows": [{ "start": "10:00", "end": "13:00" }], "notes": "Gate code at the side door" }'

6Få varje ändring som en webhook

I stället för att fråga om och om igen kan Afi Planner posta varje ändring till din server. Lägg till en slutpunkt i Inställningar → Utvecklare, eller via API. Svaret innehåller signeringsnyckeln secret, som bara visas en gång.

Anrop
curl -X POST "$AFI/webhooks" \
  -H "Authorization: Bearer $AFI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/afi/webhooks",
    "events": ["order.status_changed", "order.eta_changed", "route.dispatched"],
    "description": "Shop backend"
  }'
Svar 201
{
  "id": 1,
  "url": "https://example.com/afi/webhooks",
  "events": ["order.status_changed", "order.eta_changed", "route.dispatched"],
  "enabled": true,
  "secret": "whsec_…",
  …
}

Skicka en testhändelse med POST /webhooks/{id}/test. Varje händelse är en JSON-POST:

Händelse
POST /afi/webhooks
Afi-Event: order.status_changed
Afi-Delivery: 3
Afi-Signature: t=1793078018,v1=5f0c…

{
  "id": "evt_EbCy9y6Dq8yoTQXL",
  "type": "order.status_changed",
  "sequence": 3,
  "occurredAt": "2026-11-03T14:02:58Z",
  "createdAt": "2026-11-03T14:02:58Z",
  "companyId": 1,
  "test": false,
  "data": {
    "order": { "id": 1, "ref": "SHOP-1042", "status": "assigned", "route": { "driverId": 1, "eta": "2026-11-03T17:00:00Z", … }, … },
    "previousStatus": "new",
    "event": null
  }
}
HändelseNär
order.created, order.updated, order.deletedEn order lades till, ändrades (changed listar fälten) eller togs bort
order.cancelledOrdern avbokades, i appen eller med POST /orders/{id}/cancel, med sin cancellation; ingen order.status_changed eller order.deleted kommer för den
order.status_changedSkickad på en rutt, på väg, levererad, misslyckad…, med orsak och bevis
order.eta_changedETA flyttades med din tröskel, 5 minuter som standard (live medan föraren är ute)
order.loadedFöraren lastade paketet i bilen
order.rescheduled_by_customer, order.instructions_changed, order.ratedKunden valde en annan dag, ändrade instruktionerna eller betygsatte leveransen på spårningssidan
order.not_attemptedFörarens dag slutade med ordern fortfarande öppen
order.moved_backEn flytt till en annan dag ångrades: ordern är åter den i movedBackTo
plan.optimized, plan.job_failed, route.dispatchedNya rutter på tavlan, en planering som misslyckades, rutter eller uppdateringar skickade

Kontrollera signaturen innan du litar på en händelse: v1 är HMAC-SHA256 av t.body med din hemlighet, i hex. Avvisa händelser äldre än 5 minuter, svara 2xx inom 10 sekunder och gör arbetet efteråt. I Node:

Node.js
import http from 'node:http'
import crypto from 'node:crypto'

const secret = process.env.AFI_WEBHOOK_SECRET // whsec_…

function verify(header, rawBody) { // rawBody: the bytes as they came, before any JSON parsing
  const parts = header.split(',').map((p) => p.split('='))
  const t = Number(parts.find(([k]) => k === 't')?.[1])
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false // older than 5 minutes
  const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest()
  return parts.filter(([k]) => k === 'v1').some(([, sig]) => {
    const got = Buffer.from(sig, 'hex')
    return got.length === expected.length && crypto.timingSafeEqual(got, expected)
  })
}

http.createServer((req, res) => {
  const chunks = []
  req.on('data', (c) => chunks.push(c))
  req.on('end', () => {
    const raw = Buffer.concat(chunks)
    if (!verify(req.headers['afi-signature'] ?? '', raw)) { res.writeHead(401).end(); return }
    res.writeHead(200).end() // answer first, then process
    const event = JSON.parse(raw.toString('utf8'))
    const order = event.data.order ?? event.data // order.deleted, order.moved_back: id, ref, day
    console.log(event.sequence, event.type, order.ref, order.status)
  })
}).listen(3000)
  • Omförsök: ett annat svar än 2xx, eller inget inom 10 sekunder, försöks igen efter 1 min, 5 min, 30 min, 2 h, 6 h och 12 h. En slutpunkt som misslyckas 3 dagar i rad stängs av.
  • Ordning: händelser kan komma i fel ordning. Tillämpa en händelse bara om dess sequence är högre än den senaste du tillämpade för den ordern; ett omförsök har samma id och sequence.
  • Efter en ny signeringsnyckel (POST /webhooks/{id}/rotate-secret) signerar den gamla i 24 timmar till: huvudet har då två v1-värden, godta vilket som helst.
  • Händelser medan en slutpunkt är avstängd sparas inte för den: läs dagen med GET /orders?day= när du har slagit på den igen.
  • Varje leverans, dess innehåll och din servers svar finns kvar i 3 dagar i Inställningar → Utvecklare och i GET /webhooks/{id}/deliveries, med Försök igen och Skicka igen.
  • Utan events får en slutpunkt alla händelsetyper (*).
  • order.deleted och order.moved_back har id, ref och day i data, ingen order.
  • Länkar till leveransbevis (foton, signatur) är signerade och fungerar i 1 timme: ladda ner det du sparar, eller läs ordern igen för nya länkar.

Hemligheten är hela strängen whsec_…. Signera kroppen exakt som den kom: ett ramverk som tolkar JSON först måste ge dig de råa byten (i Express express.raw({ type: "application/json" }) på den här rutten).

7Koppla en butik: Shopify som exempel

Afi Planner tar inte emot butikens webhooks direkt: en liten tjänst hos dig, en brygga, sitter emellan. Den gör varje butiksorder till en order i Afi Planner, och varje händelse från Afi Planner till en uppdatering i butiken. Samma steg fungerar för WooCommerce, ett affärssystem eller ett lagersystem.

Flöde
orders/create, orders/updated  →  bridge  →  POST /orders
orders/cancelled               →  bridge  →  DELETE /orders/{id}
fulfillment, tracking link     ←  bridge  ←  webhooks (signed)
Shopify-orderOrder i Afi Planner
nameref: ordernumret som dina kunder och anställda ser (#1001)
shipping_addressname, phone, address på en rad, unit från address2, och lat, lng när Shopify har dem
email, noteemail, customerNote
idcustomFields: { "shopifyOrderId": "…" }, för att hitta Shopify-ordern från varje händelse
(delivery date)day: datumet som valdes i kassan om du frågar efter ett, annars din nästa leveransdag
Node.js
// Shopify orders/create and orders/updated → Afi Planner (check Shopify's own signature first)
async function sendToAfi(o, day) {
  const a = o.shipping_address
  const res = await fetch(`${process.env.AFI}/orders`, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.AFI_API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': `shopify-${o.id}-${o.updated_at}`, // Shopify may send a webhook twice
    },
    body: JSON.stringify({
      ref: o.name,
      day,
      name: a.name,
      phone: a.phone ?? o.phone,
      email: o.email,
      address: [a.address1, a.city, a.province_code, a.zip].filter(Boolean).join(', '),
      unit: a.address2 || undefined,
      ...(a.latitude != null ? { lat: a.latitude, lng: a.longitude } : {}),
      customerNote: o.note || undefined,
      customFields: { shopifyOrderId: String(o.id) },
    }),
  })
  const body = await res.json()
  if (!res.ok) throw new Error(`Afi Planner ${res.status} ${body.code}: ${body.error}`)
  return body // keep body.id with the Shopify order
}

Spara id som Afi Planner svarar med bredvid Shopify-ordern: avbokning (POST /orders/{id}/cancel) och senare ändringar behöver det; utan det hittar GET /orders?ref=%231001 ordern på vilken dag som helst. En uppdatering efter att en förare har arbetat med ordern svarar 409 order_worked: ändra den med PATCH /orders/{id}, eller låt den vara.

Händelse i Afi PlannerI Shopify
order.status_changed → assignedSkapa leveransen (fulfillment) med orderns trackingUrl som spårningslänk: kunden följer föraren live
order.status_changed → in_transitFulfillment-händelse out_for_delivery
order.status_changed → deliveredFulfillment-händelse delivered; data.event.proof har foton, signatur och mottagare
order.status_changed → failedFulfillment-händelse attempted_delivery; POST /orders/{id}/redeliver skickar ut den igen
order.eta_changedDitt eget meddelande “kommer kl.”, om du visar ett

Prova ordersidan först med ref som börjar med API-TEST- (till exempel API-TEST-1001): de ordrarna planeras aldrig, skickar inga meddelanden och raderas efter 3 dagar; deras webhooks har "test": true.

8Fel

Alla fel har samma form: en mening du kan visa eller logga, en code som ditt program kan agera på och field när ett fält är fel.

Svar 400
{ "error": "Latitude can't be more than 90", "code": "invalid_request", "field": "lat" }
HTTPcodeVad du gör
400invalid_requestEtt fält är fel (field), eller kroppen är inte JSON skickad med Content-Type: application/json
400day_in_pastOrder gäller i dag eller senare
400invalid_cursorSkicka föregående sidas nextCursor som den kom
401unauthorizedNyckeln saknas, är fel, återkallad eller har gått ut
402subscription_endedAbonnemanget har upphört: läsning fungerar fortfarande
403company_pausedFöretaget är pausat
403key_read_onlyEn nyckel med endast läsning försökte ändra något
403creator_forbiddenPersonen som skapade nyckeln får inte göra detta: använd en nyckel från någon som får det
403webhook_needs_viewFör att lägga till en webhook krävs en nyckel vars skapare kan se order
403plan_fullDagens plan har inte plats för så många nya order i ditt paket (planFull); inget sparades
404not_found, no_planIngen sådan order, jobb eller webhook, eller ingen plan för den dagen än
409order_workedEn förare har redan arbetat med ordern: PATCH /orders/{id} ändrar dess fält
409order_sentEn förare har den här ordern: avboka den med POST /orders/{id}/cancel i stället för att ta bort den
409order_cancelledDen här ref:ens order för den dagen är avbokad: skicka acceptDuplicateRef: true för en ny order
409order_movedOrdern flyttades till en annan dag: movedTo anger ordern den är nu
409ref_takenEn annan öppen order har redan denna ref, någon dag
409day_overDen dagen är över: den kan inte planeras eller skickas
409idempotency_conflictDenna Idempotency-Key användes för ett annat anrop
409idempotency_in_progressDet första anropet med denna nyckel pågår fortfarande: fråga igen om en stund
422cannot_planDagen kan inte planeras: meningen säger varför
429rate_limitedFör många anrop: vänta Retry-After sekunder

Säkra omförsök: skicka ett Idempotency-Key-huvud med varje POST (vilken unik sträng som helst, till exempel ditt order-ID och ett försöksnummer). Samma nyckel och kropp inom 24 timmar ger det första svaret i stället för att göra det två gånger.

9Anropsgränser och paketgränser

  • 600 anrop per minut och nyckel, räknat per kalenderminut. Varje svar säger var du är: RateLimit-Limit, RateLimit-Remaining och RateLimit-Reset (sekunder till nästa minut). Över gränsen blir svaret 429 med Retry-After.
  • Upp till 1 000 order per batchanrop.
  • Ditt pakets gränser gäller som i appen: stopp per plan (500 under den kostnadsfria provperioden), planeringar och adressuppslag per månad. /me visar dem.
  • Upp till 10 webhook-slutpunkter per företag.
Svarshuvuden
HTTP/1.1 200 OK
RateLimit-Limit: 600
RateLimit-Remaining: 599
RateLimit-Reset: 4

Alla exempel på den här sidan kördes mot API:et den 27 okt. 2026 (OpenAPI 1.10.0). Att ställa in det i appen: guiden API och webhooks

Få en API-nyckel på en minut

Starta den kostnadsfria provperioden på 3 månader: API och webhooks ingår i alla abonnemang. Inget kreditkort.