Integration quickstart
The integration API lives under /api/v1/integration/*, is versioned and does not change incompatibly
within v1. The full reference — API интегратора in the sidebar — is built from the same
specification the system itself runs on.
1. Get a key
Section titled “1. Get a key”The company administrator creates a key on Access control → API keys: name, scopes, requests per minute (2000 by default). The key value is shown once.
| Scope | Grants |
|---|---|
orders:write |
create/update orders, cancel, refuse, rebox, payment, mini-statuses, tags |
orders:read |
pull orders with statuses |
trips:read |
pull trips |
vehicles:read |
read vehicles |
couriers:write |
sync drivers |
Send it with every request: Authorization: ApiKey <key>. Check it with GET /api/v1/integration/whoami.
2. Send an order
Section titled “2. Send an order”POST /api/v1/integration/orders/sync is an upsert by externalId: resending the same
externalId updates the order instead of creating a second one — retries are safe. Bulk:
POST /api/v1/integration/orders/sync/bulk (per-item results and errors).
Validated at the door (400 with a field and a code otherwise): every line has requestedQty > 0
(orders.line.requestedQty.invalid), non-negative weight/volume (orders.line.measure.invalid),
a productId and warehouseId that exist in your company and are not archived
(orders.line.product.notFound, orders.line.warehouse.notFound, field lines[i].productId /
lines[i].warehouseId), and at least one address with coordinates (orders.coordinates.required).
For an order to be plannable it needs address coordinates, a delivery window, and weight/volume on its lines. A line without dimensions is not treated as zero — the planner refuses with a reason code.
Re-sending and lines. While the order is not on a trip (New, InPlanning) and none of its lines
has an outcome, a re-sync updates the lines: a line keeping its code keeps its id and takes the
new quantity/weight/volume, a new code is added, a missing one is removed. Once the order is planned
or has an outcome, a changed line answers 409 orders.lines.immutable — the correction is refused, not
silently dropped. Re-sending a cancelled order brings it back: 200, outcome: "Restored",
status New.
3. Pull statuses
Section titled “3. Pull statuses”GET /api/v1/integration/orders?since=2026-09-03T00:00:00Z&limit=200→ { "items": [ … ], "nextCursor": "eyJ…" }GET /api/v1/integration/orders?cursor=eyJ…The cursor is opaque; keep the last nextCursor and continue from it. null means you are caught up.
Same for trips: GET /api/v1/integration/trips.
Order statuses: New → InPlanning → Planned → InProgress → FullyDelivered | PartiallyDelivered | Returned | Collected | PartiallyCollected | NotCollected | Refused | Cancelled → Closed. A Pickup or
Return order ends Collected (everything collected), PartiallyCollected or NotCollected where a
delivery ends FullyDelivered, PartiallyDelivered or Returned; a Rebox order uses the delivery
statuses and is FullyDelivered only when the new item was handed over and the old one collected. The list
can grow: treat a status you do not know as not final rather than as an error.
4. Errors and limits
Section titled “4. Errors and limits”Every error is a Problem Details body whose type is a code from the error catalog; validation errors
carry errors per field. Rate limit is per key per minute: 429, type: orders.rate_limited,
Retry-After.