Skip to content
Linq Copy agent prompt

Retry a pending webhook delivery now

POST/v1/webhook_deliveries/{delivery}/retry

Pulls a pending delivery’s next attempt forward to now, so a receiver that was down — or not yet deployed — gets its retry immediately instead of at the end of the backoff. The delivery is otherwise untouched: the same event, the same payload, the same position in its endpoint-and-chat order. Later deliveries to the same endpoint and chat wait behind it, so pulling the delivery at the head of the line forward and having it succeed releases the rest. A message that is waiting for its attachments has no delivery yet, so there is nothing to pull forward until it is recorded.

The attempt this triggers is an ordinary one, and it is not free. Every delivery gets at most nine attempts; the one you pull forward spends one of them, and a failure schedules the next attempt on the same backoff as before, from the same attempt number. Pulling forward against a receiver that is still down therefore only spends the bounded attempts faster. Once the last attempt fails the delivery leaves live delivery as retry_exhausted, later deliveries in its line proceed, and only a replay (POST /v1/webhook_endpoints/{endpoint}/replays) can send its event.

Answers 200 with the delivery as GET /v1/webhook_deliveries renders it. A pending delivery whose next_attempt_at is already at or before now is answered 200 unchanged — pulling forward what is already due is a no-op, not an error — so read next_attempt_at to tell the two apart. A delivering delivery answers 409 webhook_delivery_in_progress: an attempt is on the wire and its result decides the next timer. A delivered, permanent_refusal or retry_exhausted delivery answers 409 webhook_delivery_terminal with the state in the message. An unknown delivery, or one belonging to another account or partition, answers 404 webhook_delivery_not_found.

Path ParametersExpand Collapse
delivery: string
ReturnsExpand Collapse
Delivery object { id, attempt_history_complete, attempts, 11 more }

One webhook delivery and every retained applied attempt belonging to it.

id: string
attempt_history_complete: boolean

True only when every spent attempt has a retained applied verdict and collection covered this delivery from creation.

attempts: array of DeliveryAttempt { attempt, attempt_completed_at, attempt_started_at, 9 more }
attempt: number

The spent attempt number. Gaps mean a lease expired without an applied verdict.

formatint32
attempt_completed_at: string
formatdate-time
attempt_started_at: string
formatdate-time
destination: string

Scheme, host and effective port only. Path, query, fragment and credentials are never returned.

http_status: number

Response status, or null when no response was received.

formatint32
phase: string

pre_dial when no request began, or wire after the HTTP round trip began.

reason_code: string

A bounded machine reason. Treat unknown values as unknown.

verdict: string

delivered, retryable, or permanent. Treat unknown values as an unavailable verdict.

wire_completed_at: string
formatdate-time
wire_duration_ms: number
formatint64
wire_started_at: string
formatdate-time
trace_id: optional string

W3C trace id when one was recorded. Correlation only; never authorization.

created_at: string
formatdate-time
endpoint_id: string
event_id: string
event_kind: string
observed_attempt_count: number

Applied attempt verdicts retained below.

formatint32
seq_from: number
formatint64
seq_to: number
formatint64
spent_attempt_count: number

Attempts spent by the delivery machine, including leases that expired without an applied verdict.

formatint32
state: string

pending, delivering, delivered, permanent_refusal, or retry_exhausted.

chat_id: optional string
next_attempt_at: optional string

Present only while state is pending: the instant the next attempt becomes due. A value in the future is a delivery backing off after a failed attempt; a value at or before now is a delivery that is due and waiting — usually behind an earlier delivery to the same endpoint and chat. Deliveries to one endpoint and chat are sent in the order their events were recorded. A message.received for a message carrying attachments can be recorded once every attachment has been captured or has failed, or ten minutes after the message arrived. It can therefore follow deliveries for later messages of the same chat, and carry a lower data.seq_from than an event you already received: seq_from can decrease relative to arrival. Never discard such an event as stale: deduplicate by the event id, order a conversation by data.seq_from, and for live processing buffer briefly or reconcile with GET /v1/chats/{chat}/events. POST /v1/webhook_deliveries/{delivery}/retry moves a future value to now.

formatdate-time

Retry a pending webhook delivery now

curl https://whatsapp.messages.api.linqapp.com/v1/webhook_deliveries/$DELIVERY/retry \
    -X POST \
    -H "Authorization: Bearer $LINQ_WHATSAPP_API_KEY"
{
  "id": "id",
  "attempt_history_complete": true,
  "attempts": [
    {
      "attempt": 0,
      "attempt_completed_at": "2019-12-27T18:11:19.117Z",
      "attempt_started_at": "2019-12-27T18:11:19.117Z",
      "destination": "destination",
      "http_status": 0,
      "phase": "phase",
      "reason_code": "reason_code",
      "verdict": "verdict",
      "wire_completed_at": "2019-12-27T18:11:19.117Z",
      "wire_duration_ms": 0,
      "wire_started_at": "2019-12-27T18:11:19.117Z",
      "trace_id": "trace_id"
    }
  ],
  "created_at": "2019-12-27T18:11:19.117Z",
  "endpoint_id": "endpoint_id",
  "event_id": "event_id",
  "event_kind": "event_kind",
  "observed_attempt_count": 0,
  "seq_from": 0,
  "seq_to": 0,
  "spent_attempt_count": 0,
  "state": "state",
  "chat_id": "chat_id",
  "next_attempt_at": "2019-12-27T18:11:19.117Z"
}
Returns Examples
{
  "id": "id",
  "attempt_history_complete": true,
  "attempts": [
    {
      "attempt": 0,
      "attempt_completed_at": "2019-12-27T18:11:19.117Z",
      "attempt_started_at": "2019-12-27T18:11:19.117Z",
      "destination": "destination",
      "http_status": 0,
      "phase": "phase",
      "reason_code": "reason_code",
      "verdict": "verdict",
      "wire_completed_at": "2019-12-27T18:11:19.117Z",
      "wire_duration_ms": 0,
      "wire_started_at": "2019-12-27T18:11:19.117Z",
      "trace_id": "trace_id"
    }
  ],
  "created_at": "2019-12-27T18:11:19.117Z",
  "endpoint_id": "endpoint_id",
  "event_id": "event_id",
  "event_kind": "event_kind",
  "observed_attempt_count": 0,
  "seq_from": 0,
  "seq_to": 0,
  "spent_attempt_count": 0,
  "state": "state",
  "chat_id": "chat_id",
  "next_attempt_at": "2019-12-27T18:11:19.117Z"
}