VocalDocscontracts 1.65.0

Replay the events of a time window to a Webhook subscription

POST /v1/webhooks/{webhook_id}/replay

PropertyValue
Operationreplay_webhook
GroupWebhooks
Scopewebhooks:write
Route classcontrol
IdempotencyIdempotency-Key required: a retry with the same key replays the first answer
AuditAudited webhooks.replay (mutation)
Released in1.52.0
Phase 0 hostServed (the hosted api pins 1.65.0)

Creates a webhook.replay job (1.52.0, ADR 0051 rule 6) that re-sends, in sequence order, every event of the 30-day log created in [from, to) that the subscription matches now, narrowed by types; each delivery keeps its event id and carries Vocal-Replay: true, and no effect inside Vocal runs again. Answers 202 with the job and its Location. The window is checked first (ReplayWindowIssueCode): replay_window_inverted, replay_window_out_of_range and, past 10,000 matching events (a target), replay_window_too_large. A second replay while one is queued or running is 409 replay_in_progress. The Audit event webhooks.replay records the subscription, the window and the types. The subscription is a resource of slice 2.5: until it exists every webhook_id is not_found, and slice 2.5 adds the event_id form of the body. From 1.63.0 the subscriptions exist (create_webhook), the body may instead name one event_id, a job of that one event that re-sends it under its own id, at most ten times per event and subscription (WebhookReplayEventIssueCode), and a subscription that is not active is refused with 409 webhook_not_active.

Request

Set VOCAL_API to the base URL of your API and VOCAL_API_KEY to an API key with the webhooks:write scope (Authentication and keys). Replace each placeholder, such as agt_... or <name>, with your own value.

curl -X POST "$VOCAL_API/v1/webhooks/whk_.../replay" \
  -H "Authorization: Bearer $VOCAL_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "from": "2026-10-07T14:02:11.408Z", "to": "2026-10-07T14:02:11.408Z" }'

Parameters

NameInTypeRequiredDescription
webhook_idpathWebhookIdyesThe id of a Webhook subscription: whk_ and the row's UUIDv7 in 26 Crockford base32 characters. Opaque and safe to log.
idempotency-keyheaderstringyesA client-chosen key, kept 24 hours per Organization, environment and route. A replay returns the stored response.

Request body

Content type application/json, required: WebhookReplayRequest.

Responses

StatusContent typeShapeError codes
202application/jsonJob
400application/jsonErrorEnvelopeinvalid_request
401application/jsonErrorEnvelopeunauthenticated
403application/jsonErrorEnvelopeforbidden, org_suspended
404application/jsonErrorEnvelopenot_found
409application/jsonErrorEnvelopereplay_in_progress, webhook_not_active, idempotency_in_progress, idempotency_key_reused
422application/jsonErrorEnvelopevalidation_failed
429application/jsonErrorEnveloperate_limited
500application/jsonErrorEnvelopeinternal_error

Fields of the 202 answer

The shape is Job.

FieldTypeRequiredDescription
created_atTimestampyes
created_byActorRefyes
errorJobError or nullyesWhy the job failed, a code and a message; null otherwise.
finished_atTimestamp or nullyes
has_result_filebooleanyesTrue when the result is a file, fetched through POST /v1/jobs/{job_id}/result-url.
idJobIdyes
object"job"yes
progressJobProgressyes
resourceJobResource or nullyes
resultJobResult or nullyesA small result inline once succeeded, typed by the job type (WebhookReplayJobResult for webhook.replay, from 1.53.0 KnowledgeEvaluationJobResult for knowledge.evaluation, from 1.55.0 PromptEvalRunJobResult for prompt.evaluation and agent.conversation_test, from 1.56.0 AnalysisJobResult for call.analyze); null before.
started_atTimestamp or nullyes
statusJobStatusyes
typeJobTypeyes