This guide takes you from an API key to a delivered sandbox order. It takes about ten minutes. You need curl, jq and a Bash or Zsh shell (on Windows, use WSL).
export DELIVR_API=https://driver-staging-api.delivr.noexport DELIVR_API_KEY=dmk_your_sandbox_key
# Every write needs a new UUID as its Idempotency-Key.uuid() { uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid; }-
Check your key
Section titled “Check your key”List your store locations. An empty list is fine; it means your key works.
Request curl -s $DELIVR_API/v1/merchant/locations \-H "Authorization: Bearer $DELIVR_API_KEY"Response · 200 { "items": [] }A
401 unauthenticatedmeans the key is wrong or revoked. See Authentication. -
Add a store
Section titled “Add a store”Register the store your goods are picked up from. Delivr finds it on the map from its address.
Request curl -s $DELIVR_API/v1/merchant/locations \-H "Authorization: Bearer $DELIVR_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuid)" \-d '{"externalStoreId": "oslo-sentrum","name": "Oslo Sentrum","street": "Akersgata 45","postalCode": "0158","city": "Oslo","contactName": "Store staff","contactPhone": "+4722000000","prepMinutes": 10}' | jq .Response · 201 {"id": "9b2c4f60-1d7e-4c3a-8f15-6a0e2d9b7c41","externalStoreId": "oslo-sentrum","name": "Oslo Sentrum","street": "Akersgata 45","postalCode": "0158","city": "Oslo","country": "NO","latitude": 59.914,"longitude": 10.7423,"contactName": "Store staff","contactPhone": "+4722000000","prepMinutes": 10,"readyDeadlineMinutes": 60,"readySignal": "assumed","pickupInstructions": ""}From now on you can name this store by your own
externalStoreId. Running this step again answers409 conflict: you already have a store with thatexternalStoreId, so carry on.Robo drivers park at a new store within a minute. Wait a minute before the next step.
-
Quote a delivery
Section titled “Quote a delivery”Ask what Delivr can offer from the store to an address, for one 4.5 kg parcel. The answer is saved to
quote.jsonand its id to$QUOTE.Request curl -s $DELIVR_API/v1/merchant/quotes \-H "Authorization: Bearer $DELIVR_API_KEY" \-H "Content-Type: application/json" \-d '{"pickupExternalStoreId": "oslo-sentrum","delivery": {"address": { "street": "Karl Johans gate 22", "postalCode": "0026", "city": "Oslo" }},"parcels": [{ "count": 1, "weightKg": 4.5, "lengthCm": 40, "widthCm": 30, "heightCm": 20 }]}' | tee quote.json | jq .export QUOTE=$(jq -r .quoteId quote.json)Response · 200 {"quoteId": "3f0e9a52-8a7e-4f8e-9a51-2c0f3c9d1b7a","expiresAt": "2026-11-03T13:05:00Z","timeZone": "Europe/Oslo","options": [{"type": "on_demand","key": "on_demand","eta": { "from": "2026-11-03T13:25:00Z", "to": "2026-11-03T13:55:00Z" },"price": { "amountMinor": 14900, "vatMinor": 2980, "exVatMinor": 11920, "currency": "NOK" },"supply": {"nearbyDrivers": 2,"pickupEta": { "from": "2026-11-03T13:02:00Z", "to": "2026-11-03T13:06:00Z" }}},{"type": "window","key": "window:2026-11-03T17:00:00+01:00/2026-11-03T19:00:00+01:00","window": { "start": "2026-11-03T16:00:00Z", "end": "2026-11-03T18:00:00Z" },"cutoffAt": "2026-11-03T14:00:00Z","price": { "amountMinor": 9900, "vatMinor": 1980, "exVatMinor": 7920, "currency": "NOK" }}]}Show these options to the shopper (see Showing options at checkout). Prices are what Delivr bills you, VAT included; what you charge the shopper is up to you.
-
Place the order
Section titled “Place the order”When the shopper pays, book the option they chose. Use your own order id as
externalRef(here made unique with the time, so you can run the step again), and give the recipient’s name and phone so Delivr can text them a tracking link. The order’s id is saved to$ORDER.Request curl -s $DELIVR_API/v1/merchant/orders \-H "Authorization: Bearer $DELIVR_API_KEY" \-H "Content-Type: application/json" \-H "Idempotency-Key: $(uuid)" \-d @- <<EOF | tee order.json | jq .{"quoteId": "$QUOTE","option": "on_demand","externalRef": "order-$(date +%s)","delivery": {"address": { "street": "Karl Johans gate 22", "postalCode": "0026", "city": "Oslo" },"contact": { "name": "Kari Nordmann", "phone": "+4791234567" },"dropoff": { "floor": 3, "doorCode": "1234" }}}EOFexport ORDER=$(jq -r .id order.json)Response · 201 {"id": "3f0e9a52-8a7e-4f8e-9a51-2c0f3c9d1b7a","reference": "DD-482913","externalRef": "order-1793710812","type": "on_demand","status": "awaiting_goods","readyBy": "2026-11-03T14:00:12Z","readyAt": "2026-11-03T13:10:12Z","trackingUrl": "https://tracking-stage.delivr.no/t/…","eta": { "from": "2026-11-03T13:25:00Z", "to": "2026-11-03T13:55:00Z" },"timeZone": "Europe/Oslo","version": 3,"createdAt": "2026-11-03T13:00:12Z","placedAt": "2026-11-03T13:00:12Z","updatedAt": "2026-11-03T13:00:13Z"}The order’s
idis thequoteId, andreference(DD-…) is what you quote to Delivr support. -
Say the goods are ready
Section titled “Say the goods are ready”The store has packed the parcel. Tell Delivr, and the driver search starts at once. Order paths take Delivr’s
idor theDD-reference.Request curl -s -X POST $DELIVR_API/v1/merchant/orders/$ORDER/ready \-H "Authorization: Bearer $DELIVR_API_KEY" \-H "Idempotency-Key: $(uuid)" | jq .statusThe order moves to
searching. With the store’s default (readySignal: assumed) this step is optional: the goods count as ready afterprepMinutes(10 minutes here), and the search starts then. See Goods ready signals. -
Watch a robo driver deliver it
Section titled “Watch a robo driver deliver it”The sandbox has robo drivers parked at your store. One accepts within seconds, drives to the store, picks up and delivers. A delivery takes about two minutes. Poll the order to watch it move:
Request while :; doSTATUS=$(curl -s $DELIVR_API/v1/merchant/orders/$ORDER -H "Authorization: Bearer $DELIVR_API_KEY" | jq -r .status)echo "$(date +%T) $STATUS"case $STATUS in delivered | cancelled | failed) break ;; esacsleep 5doneOutput 13:00:20 searching13:00:25 driver_assigned13:01:20 picked_up13:02:10 deliveredRead the order once more and it has a
proofOfDelivery. To test failures instead, put a directive such assandbox:no_driverinpickup.note. See Sandbox and testing. -
Receive the webhooks
Section titled “Receive the webhooks”If your webhook endpoint is set up, it received
order.placed,order.searching,order.driver_assigned,order.picked_upandorder.delivered, among others. Check the delivery log:Request curl -s "$DELIVR_API/v1/merchant/webhooks/deliveries?orderId=$ORDER" \-H "Authorization: Bearer $DELIVR_API_KEY" | jq '.items[] | {event, statusCode, succeeded}'Then verify the signatures in your handler. No endpoint yet? See Testing webhooks.
What to read next
Section titled “What to read next”- Showing options at checkout: how to present the quote to shoppers.
- Quotes and orders: expired quotes, price changes and booking without a quote.
- Order lifecycle: every status and reason to handle.
- Receiving webhooks: ordering, retries and deduplication.
- Go-live checklist: what to check before you switch to production.