Skip to main content
GET
JavaScript
When a webhook does not arrive, this endpoint tells you whether Cadenya sent it and what your endpoint said back. It settles the question of whose bug it is before you go looking. Set webhookEventsUrl on an agent’s spec and every objective event for that agent is POSTed to it. Each attempt is recorded here.

Read a delivery

Each record carries the event it delivered, where it went, and what came back. webhookId is the useful one when correlating. It is the same value Cadenya sent in the webhook-id header, so a delivery here and a request in your access log can be matched exactly.
Only WEBHOOK_DELIVERY_STATUS_COMPLETED and WEBHOOK_DELIVERY_STATUS_FAILED are ever written. The enum also declares PENDING and DISABLED, which never appear on a record.On a failed delivery, httpStatusCode, latencyMs, and attemptCount are unreliable: attemptCount is set to the maximum rather than the number of tries made, and the response fields are left at zero. Read errorMessage.

Filter to the delivery you want

The list takes objectiveId, eventType, labels, and cursor pagination.
An unrecognized eventType is a 400, so a typo announces itself. There is no status filter: to find failures, list and filter on the client.
Delivery records are kept for 24 hours and then expire. This is a live debugging surface, not an audit log. Persist what you need from your own handler.

How Cadenya delivers

Each event is one POST with Content-Type: application/json and a Standard Webhooks envelope:
Failures retry five times with exponential backoff, starting at one second and doubling to a one-minute ceiling. Each attempt gets 30 seconds to complete. Any non-2xx response is retried. Three failures do not retry, because retrying cannot help:
  • The URL is unparseable, or is not https. Cadenya refuses plain HTTP.
  • Your endpoint answers 410 Gone, which Cadenya reads as “stop sending.”
  • The signing key cannot be loaded.

Verify the signature

Every delivery carries webhook-id, webhook-timestamp, and webhook-signature headers, following Standard Webhooks. The signature is an HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{body}, keyed by your account signing key, not a per-agent secret. The SDK verifies and parses in one call:
Read the key from GET /v1/account (info.webhookEventsHmacSecret) and store it as a secret. Rotate it with POST /v1/account:rotateWebhookSigningKey, which returns the new key and takes effect immediately, with no overlap window. Deploy the new key to your handler before you rotate.
Rotation has no grace period. The old key stops signing the moment the new one is issued, so a handler still holding the old key rejects every delivery until you redeploy.

Streaming or webhooks

Webhooks retry, record their outcome, and survive your process restarting. Streaming does none of that, but it needs no public endpoint and shows up instantly. Use webhooks when a machine reacts. Use streaming when a person watches.

Webhooks

Signature verification, the payload envelope, and a full handler.

Approving a tool

The webhook that pauses an objective until a person decides.

Stream objective events

The same events, live, with no endpoint to host.

Rotate the signing key

One call, immediate effect, no overlap.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

workspaceId
string
required

Workspace ID.

Example:

"workspace_01HXKD2E5NQM3T9AYWCF133E3Q"

agentId
string
required
Example:

"agent_01HXKD2E5NQM3T9AYWCFMGWT9Y"

Query Parameters

cursor
string

Pagination cursor from previous response

limit
integer<int32>

Maximum number of results to return

objectiveId
string

Optional filter by objective ID

Example:

"obj_01HXKD2E5NQM3T9AYWCFQAZGFV"

eventType
enum<string>

Optional filter by event type

Available options:
OBJECTIVE_EVENT_TYPE_UNSPECIFIED,
OBJECTIVE_EVENT_TYPE_USER_MESSAGE,
OBJECTIVE_EVENT_TYPE_TOOL_APPROVAL_REQUESTED,
OBJECTIVE_EVENT_TYPE_TOOL_APPROVED,
OBJECTIVE_EVENT_TYPE_TOOL_DENIED,
OBJECTIVE_EVENT_TYPE_TOOL_CALLED,
OBJECTIVE_EVENT_TYPE_ERROR,
OBJECTIVE_EVENT_TYPE_ASSISTANT_MESSAGE,
OBJECTIVE_EVENT_TYPE_TOOL_RESULT,
OBJECTIVE_EVENT_TYPE_TOOL_ERROR,
OBJECTIVE_EVENT_TYPE_CONTEXT_WINDOW_COMPACTED,
OBJECTIVE_EVENT_TYPE_MEMORY_READ,
OBJECTIVE_EVENT_TYPE_CANCELLED,
OBJECTIVE_EVENT_TYPE_SUB_AGENT_SPAWNED,
OBJECTIVE_EVENT_TYPE_SUB_AGENT_UPDATED,
OBJECTIVE_EVENT_TYPE_FINALIZED,
OBJECTIVE_EVENT_TYPE_NOTICE,
OBJECTIVE_EVENT_TYPE_TIMED_OUT
labels
string

Filters by metadata labels. Comma-separated key=value pairs, e.g. "env=prod,team=ai". A resource matches only if every pair matches exactly (AND semantics).

Response

OK

items
object[]
pagination
object

Page carries cursor-based pagination state. There is no total: the cursor walks the result set without ever counting it, and a count would cost a second query on every list.