API referenceEvents

Replay events from the ledger to webhooks

Re-reads a slice of the event ledger and re-delivers it to your webhook subscriptions, reconstructing each event body byte-identically — same eventId, type, and data — and signing it with a fresh X-Dairo-Timestamp like any delivery attempt, so it passes the consumer's verification and timestamp window while consumer-side dedupe on the event ID stays exact.

Endpoint
POST https://api.dairo.app/v1/events/replay

Re-reads a slice of the event ledger and re-delivers it to your webhook subscriptions, reconstructing each event body byte-identically — same eventId, type, and data — and signing it with a fresh X-Dairo-Timestamp like any delivery attempt, so it passes the consumer's verification and timestamp window while consumer-side dedupe on the event ID stays exact. Select the slice with exactly one lower bound: since (an opaque cursor from a GET /v1/events pagination.nextCursor), sinceSeq together with inboxId (replay one inbox partition from that seq, inclusive), or sinceTimestamp (RFC3339, events created at or after). Optionally cap the top with until (RFC3339), filter with types (e.g. ["email.bounced"]; each a plain type name of letters, digits, ., _, and -, else 400), and target one subscription with webhookId — otherwise every active matching subscription receives the slice. Delivery is synchronous and ordered by (partitionKey, seq); maxEvents bounds the slice at 1–5000 (default 1000), and a slice larger than the cap is rejected with 400 so you page it with until/maxEvents. The response returns replayed (events sent to at least one matching subscription), skipped (events with no matching active subscription), and the from/to bounds of the slice; each re-delivery lands as a terminal delivery record on your webhook subscriptions. Requires the events:write scope.

Scope: events:write. Send the API key as a bearer token; Scopes lists what each one reaches.

Request

cURL
curl -X POST "https://api.dairo.app/v1/events/replay" \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Body

Required, application/json: EventReplayRequest.

Selects a ledger slice to re-deliver. Provide exactly one lower bound: since (an opaque cursor from GET /v1/events), sinceSeq (+inboxId, replay one partition from a seq), or sinceTimestamp (RFC3339).

FieldTypeRequiredDescription
sincestringnoOpaque keyset cursor (from GET /v1/events) to replay forward from.
sinceSeqinteger (int64)noReplay one partition starting at this seq (inclusive). Requires inboxId.
inboxIdstring (uuid)noScope the replay to one inbox partition (required with sinceSeq; an optional filter otherwise).
sinceTimestampstring (date-time)noReplay events created at or after this RFC3339 timestamp.
untilstring (date-time)noOptional upper bound (events created at or before this RFC3339 timestamp).
typesarray of stringnoOptional event-type filter, e.g. ["email.bounced"].
webhookIdstringnoOptional: replay only to this one webhook subscription; otherwise to every matching active subscription.
maxEventsintegernoHard cap on the slice size. A slice that exceeds the cap is rejected with 400 asking the caller to page with until/maxEvents. (minimum 1, maximum 5000, default 1000)

Response

200 Success. Body: application/json, EventReplayResult.

FieldTypeRequiredDescription
replayedintegeryesNumber of events re-delivered to at least one matching subscription.
skippedintegeryesNumber of events in the slice with no matching active subscription.
fromEventReplayBound or nullno
toEventReplayBound or nullno
200
{
  "replayed": 0,
  "skipped": 0,
  "from": {
    "eventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "seq": 0,
    "partitionKey": "string",
    "createdAt": "2026-10-19T09:30:00Z"
  },
  "to": {
    "eventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "seq": 0,
    "partitionKey": "string",
    "createdAt": "2026-10-19T09:30:00Z"
  }
}

Errors

Every error has the same body, {"error": {"type", "code", "message", "param"}}; branch on code. Errors lists every code.

StatusMeaning
400The request is malformed or a value is invalid (invalid_request, invalid_domain, idempotency_key_mismatch).
401The API key is missing or invalid.
403The key lacks the scope this endpoint needs (scope_missing) or may not do this (not_permitted).
404No such resource in this account (resource_not_found).
422The request is well-formed but a field failed validation (validation_failed).
429Rate limit, plan limit, budget or spend cap reached (rate_limited, plan_limit_reached, budget_exceeded, spend_cap_reached).
500An unexpected error; retry with backoff, then contact support (internal_error).

On this page