POST /v1/delivery/jobs
POST /v1/delivery/jobs
| Scope | Idempotency-Key | Operation ID |
|---|---|---|
delivery.create | Required | createJob |
Confirm a quote into exactly one delivery job.
The quote reference is the contract: the fee is never re-supplied (SERVER_CONTROLLED_FIELD
otherwise). In one transaction the quote is locked and checked against the server clock
(QUOTE_EXPIRED), both pins are re-resolved under the boundary version in force (a pin now in
another area is QUOTE_EXPIRED with detail.reason: geography_changed), the pricing snapshot
is frozen, the job is written and released to dispatch (DELIVERY_REQUESTED), and the
outbox event and dispatch evaluation are enqueued. Before it, the vehicle is re-checked
against the live partner set (VEHICLE_UNAVAILABLE) and a preferred_partner must be
available to the tenant (NO_ELIGIBLE_PARTNER, or PARTNER_BLOCKED when it is blocked for
fees). Outside the tenant's availability windows the request is VALIDATION_FAILED with
detail.reason: outside_availability_window. A quote made for a customer request or
a Bulk Delivery's child is confirmed only through that request or Bulk: here it is
VALIDATION_FAILED with detail.field: quote_reference and detail.reason: quote_of_request. Idempotency-Key required: a
repeated key replays the recorded response; a confirmed quote confirmed again (any key)
returns its job with 200. A key reused after its retention is DUPLICATE_JOB_INTENT; an
external_order_reference already used by another of the tenant's jobs is
EXTERNAL_REFERENCE_IN_USE. Job creation is audited.
The 201 carries tracking_links: the sender's and the recipient's secure tracking links, for the tenant to deliver through its own channel. They are
shown once — on this response and its verbatim Idempotency-Key replay — and never on a
read or on a confirmed quote's 200, since only their hashes are kept.
Request
Signed with your API credential: see Authentication.
| Parameter | In | Required | Description |
|---|---|---|---|
Idempotency-Key | header | Yes | One key per user intent, reused for every retry of that intent. See Idempotency. |
Body
| Field | Type | Required | Description |
|---|---|---|---|
quote_reference | string | Yes | Pattern ^QT-[0-9A-HJKMNP-TV-Z]{8}$. |
external_order_reference | string | No | At most 64 characters. |
preferred_partner | string | No | Pattern ^prt_[a-z0-9][a-z0-9_]{1,62}$. |
sender | object | No | |
sender.name | string | No | At most 200 characters. |
sender.phone | string | No | Pattern ^\+[1-9][0-9]{7,14}$. |
recipient | object | No | |
recipient.name | string | No | At most 200 characters. |
recipient.phone | string | No | Pattern ^\+[1-9][0-9]{7,14}$. |
note | string | No | Context for the rider, e.g. "Call before arrival." At most 500 characters. |
Responses
200
The quote was already confirmed; its job is returned and nothing changed.
| Field | Type | Required | Description |
|---|---|---|---|
delivery_reference | string | Yes | Public reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$. |
status | string | Yes | One of: PENDING_DELIVERY, DELIVERY_REQUESTED, OFFERED, ASSIGNED, ARRIVED_AT_PICKUP, PICKED_UP, ON_THE_WAY, ARRIVED_AT_DESTINATION, RECEIPT_CONFIRMED, DELIVERED, CANCELLED, FAILED, DELIVERY_EXCEPTION, RECOVERY_REQUIRED. |
customer_status | string | Yes | The customer-facing projection |
delivery_fee | string or null | Yes | |
currency | string or null | Yes | |
external_order_reference | string or null | Yes | |
vehicle_type | string | Yes | |
service_type | string | Yes | One of: EXPRESS, PRIORITY, STANDARD, NEXT_DAY. |
pickup | object | Yes | |
pickup.description | string | Yes | " |
dropoff | object | Yes | |
dropoff.description | string | Yes | " |
partner | object or null | Yes | |
partner.name | string | Yes | |
rider | object or null | Yes | |
rider.first_name | string | Yes | |
created_at | string, date-time | Yes | |
updated_at | string, date-time | Yes | |
tracking_links | object | No | Only on the creating 201. Each link works until it expires; open it to track. |
tracking_links.sender_url | string | Yes | |
tracking_links.recipient_url | string | Yes |
201
Created and released to dispatch.
| Field | Type | Required | Description |
|---|---|---|---|
delivery_reference | string | Yes | Public reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$. |
status | string | Yes | One of: PENDING_DELIVERY, DELIVERY_REQUESTED, OFFERED, ASSIGNED, ARRIVED_AT_PICKUP, PICKED_UP, ON_THE_WAY, ARRIVED_AT_DESTINATION, RECEIPT_CONFIRMED, DELIVERED, CANCELLED, FAILED, DELIVERY_EXCEPTION, RECOVERY_REQUIRED. |
customer_status | string | Yes | The customer-facing projection |
delivery_fee | string or null | Yes | |
currency | string or null | Yes | |
external_order_reference | string or null | Yes | |
vehicle_type | string | Yes | |
service_type | string | Yes | One of: EXPRESS, PRIORITY, STANDARD, NEXT_DAY. |
pickup | object | Yes | |
pickup.description | string | Yes | " |
dropoff | object | Yes | |
dropoff.description | string | Yes | " |
partner | object or null | Yes | |
partner.name | string | Yes | |
rider | object or null | Yes | |
rider.first_name | string | Yes | |
created_at | string, date-time | Yes | |
updated_at | string, date-time | Yes | |
tracking_links | object | No | Only on the creating 201. Each link works until it expires; open it to track. |
tracking_links.sender_url | string | Yes | |
tracking_links.recipient_url | string | Yes |
400
Structural validation failed or an Idempotency-Key is missing.
The error envelope: code, message, detail, request_id.
401
Unknown, revoked or wrong-environment credential, bad signature, or expired session.
The error envelope: code, message, detail, request_id.
403
Tenant access denied (existence is not disclosed), insufficient scope, MFA/step-up required, partner blocked or module disabled.
The error envelope: code, message, detail, request_id.
409
State changed, race lost, or idempotency conflict. Refetch before deciding again.
The error envelope: code, message, detail, request_id.
422
Semantically invalid (location, vehicle, server-controlled field, bulk limits).
The error envelope: code, message, detail, request_id.
429
Rate limit reached; honour Retry-After.
The error envelope: code, message, detail, request_id.
500
Unexpected failure. Only code and request_id are returned.
The error envelope: code, message, detail, request_id.
503
Pricing/routing unavailable, request timeout, retryable contention, or an operator must act first (ACCOUNTING_PERIOD_UNAVAILABLE, outcome REQUIRES_ADMIN), or the payment provider cannot start a payment (PAYMENT_PROVIDER_UNAVAILABLE, outcome REQUIRES_PAYMENT; nothing charged).
The error envelope: code, message, detail, request_id.