POST /v1/bulk-deliveries/{ref}/recipients/{child_ref}/resend
POST /v1/bulk-deliveries/{ref}/recipients/{child_ref}/resend
| Scope | Idempotency-Key | Operation ID |
|---|---|---|
delivery.create | Required | resendBulkRecipientLink |
Resend one recipient's link before the sender confirms.
Before the sender confirms, sends one recipient who has not yet confirmed their location a
new link: the old link is revoked (only a hash of any token is kept, so it cannot be sent
again) and one SMS is owed for that child alone. Within the tenant's resend_limit (the
first link is not a resend) and outside resend_cooldown_s since the newest link, else
RATE_LIMIT_EXCEEDED with detail.reason resend_limit or resend_cooldown (the latter
with retry_after_seconds and a Retry-After header). A child that is not this Bulk's is
TENANT_ACCESS_DENIED; a recipient who confirmed, or a removed child, or a Bulk the sender
confirmed, BULK_STATE_CHANGED. Idempotency-Key required. Audited
(bulk.recipient.resend).
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. |
ref | path | Yes | Pattern ^BK-[0-9A-HJKMNP-TV-Z]{8}$. |
child_ref | path | Yes | Public reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$. |
Responses
200
Resent; one link SMS is owed for this child.
| Field | Type | Required | Description |
|---|---|---|---|
bulk_reference | string | Yes | Pattern ^BK-[0-9A-HJKMNP-TV-Z]{8}$. |
status | string | Yes | One 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_count | integer | Yes | 2–5. |
active_recipient_count | integer | Yes | 0–5. |
confirmed_count | integer | Yes | 0–5. |
quote_revision | integer | Yes | |
total | string or null | Yes | The sum of the children's quotes, null until every active child is quoted. |
currency | string | Yes | One of: GHS. |
children | array of object | Yes | |
children[].position | integer | Yes | 1–5. |
children[].delivery_reference | string | Yes | Public reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$. |
children[].status | string | Yes | The child request's status (request-level states; REMOVED once removed) |
children[].location_confirmed | boolean | Yes | The recipient confirmed the drop-off |
children[].recipient | object | Yes | |
children[].recipient.first_name | string | Yes | |
children[].recipient.last_name | string | Yes | |
children[].recipient.phone | string | Yes | Masked: the last three digits only |
children[].link_expires_at | string or null, date-time | Yes | When the child's live link stops working; null once revoked |
children[].resends_remaining | integer or null | Yes | Resends left while the recipient is awaited, else null |
children[].resend_available_at | string or null, date-time | Yes | When the resend cooldown ends while the recipient is awaited, else null |
children[].quote | object or null | Yes | The 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.reference | string | Yes | Pattern ^QT-[0-9A-HJKMNP-TV-Z]{8}$. |
children[].quote.total | string | Yes | Exact decimal with two places; never a JSON number. Pattern ^-?[0-9]+\.[0-9]{2}$. |
children[].quote.currency | string | Yes | One of: GHS. |
children[].quote.expires_at | string, date-time | Yes | |
children[].quote.expired | boolean | Yes | |
children[].customer_status | string or null | Yes | The child's delivery status as tracking shows it, once dispatched |
children[].tracking_links | object | No | The child's tracking links, shown once on the tenant's confirming response: the sender's link confirms the handover |
children[].tracking_links.sender_url | string | Yes | |
children[].tracking_links.recipient_url | string | Yes | |
children[].tracking_links.expires_at | string, date-time | Yes | |
cancellations | array of object | No | After dispatch, each child's answer to the cancellation; present only on that answer. |
cancellations[].delivery_reference | string | Yes | Public reference of a delivery job or Bulk child. Pattern ^DX-[0-9A-HJKMNP-TV-Z]{8}$. |
cancellations[].cancelled | boolean | Yes | |
cancellations[].reason | string or null | Yes | Why the stage policy left it, e.g. after_pickup |
created_at | string, date-time | 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.