Skip to main content

ERP integration checklist

Work through this in a test project before you go live. Each step says what to check and where it is explained.

Before you start​

  • API key and project id received; separate test project agreed (Getting started)
  • Webhooks switched on for the test project, if you will use them
  • Your webhook URL is https://, publicly reachable, and answers within 5 seconds
  • GET /v1/orders?limit=1 with your token returns 200

1. Create an order​

  • POST /v1/orders with tasks (pickup at the shop, delivery to the recipient), delivery.oneOf with the recipient, time windows and your order number in reference_id (Creating orders)
  • resource.id stored next to your order number
  • related.tasks holds two tasks, and related.locations the shop and the recipient at the right addresses
  • where filters are sent as URL-encoded JSON: filtering on your reference_id returns only that order
  • Retrying after a simulated timeout finds the existing order instead of creating a duplicate
  • With webhooks: order.created received and its signature verified

2. See it in the dashboard​

  • The order is listed in the dashboard with your order number, as RESERVED
  • The pickup and delivery are on the map where you expect them

3. Plan a route​

  • A dispatcher puts the order on a route in the dashboard
  • Your next poll shows status: ROUTED and a route_id (Polling)

4. Drive and complete it​

  • The driver sees the route in the driver app, picks up at the shop and delivers
  • Your poll shows ONGOING / PICKUP_COMPLETED after the pickup, then COMPLETED / DELIVERY_COMPLETED
  • With webhooks: order.delivered received once
  • Proof of delivery: order_action.created received, or GET /v1/order_actions?where=[{"order_id":{"=":"<id>"}}] returns the photo or signature (Proof of delivery)

5. Reasons​

Choosing a reason in the driver app is coming. To test your mapping now, set the outcome through the Routes API on a test order's delivery stop (Report progress on an activity):

PATCH https://routes-api.cloud.zoopit.no/v1/routes/<route id>/activities/<activity id>

{
"modified_at": "<from your latest read of the activity>",
"status": "COMPLETED",
"status_reason": "completed.alternative_recipient",
"status_description": "Neighbour in flat 2B"
}
  • Your poll shows the order COMPLETED with that status_reason and status_description
  • Repeat on another order with "status": "FAILED" and failed.recipient_absent: your system does not close the order
  • Every legacy deviation you used maps to a code (Migrating from the legacy platform)
  • An unknown status_reason falls back to its family instead of failing

6. Change and cancel​

  • PATCH with a stale modified_at is refused with 404; your system re-reads and retries
  • Changing attributes keeps the keys you did not change (you merged before sending)
  • Cancel with canceled.by_customer: your poll shows CANCELED with the reason
  • Cancel with canceled.other and no status_description: refused with 400
  • Cancel an order that is on a route: the stop leaves the route, and cancelling it again returns 409

7. Recipient SMS​

  • Subscriptions for orders.reserved, orders.routed and orders.delivered created with "enabled": false, then enabled (Recipient SMS)
  • A test order with your own phone number as recipient gives one SMS on create and one on delivery
  • The finished message fits the length you planned for

8. Catching up​

  • Stop your webhook receiver, deliver a test order, start it again: your next poll picks the change up
  • GET /v1/webhook_deliveries shows the failed attempt