Skip to main content

POST /v1/bulk-deliveries/{ref}/cancel

POST /v1/bulk-deliveries/{ref}/cancel

ScopeIdempotency-KeyOperation ID
delivery.cancelRequiredcancelBulkDelivery

Cancel the whole Bulk before dispatch; per child after.

Before the sender confirms: every active child is cancelled and its link stops working, and the Bulk becomes BULK_CANCELLED with the reason; the tenant is sent bulk.cancelled. After confirmation the Bulk is never cancelled as a whole: each child's delivery gets its own cancellation, judged by its own stage policy (as POST /v1/delivery/jobs/{ref}/cancel), so a child past pickup is not cancelled; cancellations answers child by child, and the parent's status is derived from its children. A cancelled Bulk answers as it is. Requires scope delivery.cancel. Idempotency-Key required. Audited (bulk.cancel).

Request​

Signed with your API credential: see Authentication.

ParameterInRequiredDescription
Idempotency-KeyheaderYesOne key per user intent, reused for every retry of that intent. See Idempotency.
refpathYesPattern ^BK-[0-9A-HJKMNP-TV-Z]{8}$.

Body​

FieldTypeRequiredDescription
reason_codestringYesPattern ^[A-Z][A-Z0-9_]{1,40}$.

Responses​

200​

Cancelled, or each child answered.

FieldTypeRequiredDescription
bulk_referencestringYesPattern ^BK-[0-9A-HJKMNP-TV-Z]{8}$.
statusstringYesOne of: BULK_DRAFT, BULK_AWAITING_RECIPIENTS, BULK_PARTIALLY_CONFIRMED, BULK_READY_FOR_QUOTE, BULK_AWAITING_SENDER_CONFIRMATION, BULK_DISPATCHING, BULK_IN_PROGRESS, BULK_PARTIALLY_COMPLETED, BULK_COMPLETED, BULK_CANCELLED, BULK_EXCEPTION.
recipient_countintegerYes2–5.
active_recipient_countintegerYes0–5.
confirmed_countintegerYes0–5.
quote_revisionintegerYes
totalstring or nullYesThe sum of the children's quotes, null until every active child is quoted.
currencystringYesOne of: GHS.
childrenarray of objectYes
children[].positionintegerYes1–5.
children[].delivery_referencestringYesPublic reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$.
children[].statusstringYesThe child request's status (request-level states; REMOVED once removed)
children[].location_confirmedbooleanYesThe recipient confirmed the drop-off
children[].recipientobjectYes
children[].recipient.first_namestringYes
children[].recipient.last_namestringYes
children[].recipient.phonestringYesMasked: the last three digits only
children[].link_expires_atstring or null, date-timeYesWhen the child's live link stops working; null once revoked
children[].resends_remaininginteger or nullYesResends left while the recipient is awaited, else null
children[].resend_available_atstring or null, date-timeYesWhen the resend cooldown ends while the recipient is awaited, else null
children[].quoteobject or nullYesThe child's own quote: the server's total only, never its arithmetic. expired is judged by the server clock. Null before the child is quoted.
children[].quote.referencestringYesPattern ^QT-[0-9A-HJKMNP-TV-Z]{8}$.
children[].quote.totalstringYesExact decimal with two places; never a JSON number. Pattern ^-?[0-9]+\.[0-9]{2}$.
children[].quote.currencystringYesOne of: GHS.
children[].quote.expires_atstring, date-timeYes
children[].quote.expiredbooleanYes
children[].customer_statusstring or nullYesThe child's delivery status as tracking shows it, once dispatched
children[].tracking_linksobjectNoThe child's tracking links, shown once on the tenant's confirming response: the sender's link confirms the handover
children[].tracking_links.sender_urlstringYes
children[].tracking_links.recipient_urlstringYes
children[].tracking_links.expires_atstring, date-timeYes
cancellationsarray of objectNoAfter dispatch, each child's answer to the cancellation; present only on that answer.
cancellations[].delivery_referencestringYesPublic reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$.
cancellations[].cancelledbooleanYes
cancellations[].reasonstring or nullYesWhy the stage policy left it, e.g. after_pickup
created_atstring, date-timeYes

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.