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/v1Varje 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:
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 laterKontrollera nyckeln. /me svarar med ditt företag, nyckeln och ditt pakets gränser:
curl "$AFI/me" -H "Authorization: Bearer $AFI_API_KEY"{
"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).
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": "olivia@example.com",
"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{
"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ält | Vad det är |
|---|---|
| ref | Ditt order-ID, unikt bland öppna order alla dagar (versaler och omgivande mellanslag ignoreras) |
| day | Leveransdag, YYYY-MM-DD, i dag eller senare |
| name, phone, email | Kunden. Telefonnummer sparas i E.164; ett nummer som inte kan ta emot sms sparas med phoneIssue |
| address, unit, lat, lng | Var leveransen ska ske: address krävs om du inte skickar lat och lng |
| timeWindows | 1 eller 2 fönster { "start": "09:00", "end": "12:00" }; ett slut före starten slutar nästa dag |
| serviceMinutes | Tid vid dörren, när den skiljer sig från företagets standard |
| packages, weightKg, volumeM3 | Lasten, i metriska enheter oavsett vad appen visar |
| skills, priority | Kompetenser en förare behöver; normal eller high |
| pickupAt, pickup | Var paketet hämtas först: namnet eller id för en sparad hämtplats, "depot", en adress eller "none" |
| customerNote, leaveAtDoor | Kundens instruktioner till föraren, t.ex. från din kassa |
| notifyCustomer | false: inga sms, WhatsApp eller e-post till den här kunden |
| notes, barcodes, customFields, access, language | Anteckningar 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:
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{
"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.”).
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"{ "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.
curl "$AFI/jobs/$JOB_ID" -H "Authorization: Bearer $AFI_API_KEY"{ "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.
curl "$AFI/days/$DAY/plan" -H "Authorization: Bearer $AFI_API_KEY"{
"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.
curl -X POST "$AFI/days/$DAY/dispatch" \
-H "Authorization: Bearer $AFI_API_KEY" \
-H "Idempotency-Key: send-$DAY-1"{
"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:
curl "$AFI/orders/$ORDER_ID" -H "Authorization: Bearer $AFI_API_KEY"{
"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.
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:
| status | Betydelse |
|---|---|
| new | Ännu inte på en rutt som förarna har |
| assigned | På en rutt som skickats till en förare |
| unassigned | De skickade rutterna utelämnade den |
| on_hold | Hålls utanför planeringen (POST /orders/{id}/hold, /release) |
| needs_fix, locating | Adressen kunde inte användas (addressIssue säger varför), eller slås upp |
| to_pickup, at_pickup, picked_up, pickup_failed | Förarens rapporter vid hämtningen |
| in_transit, at_delivery | På väg, vid dörren |
| delivered, failed, skipped | Klar: events har orsaken, foton, signatur och mottagare |
| cancelled | Avbokad: 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.
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.
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"
}'{
"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:
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ändelse | När |
|---|---|
| order.created, order.updated, order.deleted | En order lades till, ändrades (changed listar fälten) eller togs bort |
| order.cancelled | Ordern 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_changed | Skickad på en rutt, på väg, levererad, misslyckad…, med orsak och bevis |
| order.eta_changed | ETA flyttades med din tröskel, 5 minuter som standard (live medan föraren är ute) |
| order.loaded | Föraren lastade paketet i bilen |
| order.rescheduled_by_customer, order.instructions_changed, order.rated | Kunden valde en annan dag, ändrade instruktionerna eller betygsatte leveransen på spårningssidan |
| order.not_attempted | Förarens dag slutade med ordern fortfarande öppen |
| order.moved_back | En flytt till en annan dag ångrades: ordern är åter den i movedBackTo |
| plan.optimized, plan.job_failed, route.dispatched | Nya 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:
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 sammaidochsequence. - 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
eventsfår en slutpunkt alla händelsetyper (*). order.deletedochorder.moved_backharid,refochdayidata, ingenorder.- 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.
orders/create, orders/updated → bridge → POST /orders
orders/cancelled → bridge → DELETE /orders/{id}
fulfillment, tracking link ← bridge ← webhooks (signed)| Shopify-order | Order i Afi Planner |
|---|---|
| name | ref: ordernumret som dina kunder och anställda ser (#1001) |
| shipping_address | name, phone, address på en rad, unit från address2, och lat, lng när Shopify har dem |
| email, note | email, customerNote |
| id | customFields: { "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 |
// 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 Planner | I Shopify |
|---|---|
| order.status_changed → assigned | Skapa leveransen (fulfillment) med orderns trackingUrl som spårningslänk: kunden följer föraren live |
| order.status_changed → in_transit | Fulfillment-händelse out_for_delivery |
| order.status_changed → delivered | Fulfillment-händelse delivered; data.event.proof har foton, signatur och mottagare |
| order.status_changed → failed | Fulfillment-händelse attempted_delivery; POST /orders/{id}/redeliver skickar ut den igen |
| order.eta_changed | Ditt 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.
{ "error": "Latitude can't be more than 90", "code": "invalid_request", "field": "lat" }| HTTP | code | Vad du gör |
|---|---|---|
| 400 | invalid_request | Ett fält är fel (field), eller kroppen är inte JSON skickad med Content-Type: application/json |
| 400 | day_in_past | Order gäller i dag eller senare |
| 400 | invalid_cursor | Skicka föregående sidas nextCursor som den kom |
| 401 | unauthorized | Nyckeln saknas, är fel, återkallad eller har gått ut |
| 402 | subscription_ended | Abonnemanget har upphört: läsning fungerar fortfarande |
| 403 | company_paused | Företaget är pausat |
| 403 | key_read_only | En nyckel med endast läsning försökte ändra något |
| 403 | creator_forbidden | Personen som skapade nyckeln får inte göra detta: använd en nyckel från någon som får det |
| 403 | webhook_needs_view | För att lägga till en webhook krävs en nyckel vars skapare kan se order |
| 403 | plan_full | Dagens plan har inte plats för så många nya order i ditt paket (planFull); inget sparades |
| 404 | not_found, no_plan | Ingen sådan order, jobb eller webhook, eller ingen plan för den dagen än |
| 409 | order_worked | En förare har redan arbetat med ordern: PATCH /orders/{id} ändrar dess fält |
| 409 | order_sent | En förare har den här ordern: avboka den med POST /orders/{id}/cancel i stället för att ta bort den |
| 409 | order_cancelled | Den här ref:ens order för den dagen är avbokad: skicka acceptDuplicateRef: true för en ny order |
| 409 | order_moved | Ordern flyttades till en annan dag: movedTo anger ordern den är nu |
| 409 | ref_taken | En annan öppen order har redan denna ref, någon dag |
| 409 | day_over | Den dagen är över: den kan inte planeras eller skickas |
| 409 | idempotency_conflict | Denna Idempotency-Key användes för ett annat anrop |
| 409 | idempotency_in_progress | Det första anropet med denna nyckel pågår fortfarande: fråga igen om en stund |
| 422 | cannot_plan | Dagen kan inte planeras: meningen säger varför |
| 429 | rate_limited | Fö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-RemainingochRateLimit-Reset(sekunder till nästa minut). Över gränsen blir svaret 429 medRetry-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.
/mevisar dem. - Upp till 10 webhook-slutpunkter per företag.
HTTP/1.1 200 OK
RateLimit-Limit: 600
RateLimit-Remaining: 599
RateLimit-Reset: 4Alla 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.