Webhook event contract
Verify Connector signatures, interpret event identities and revisions, and handle retries, redaction, and journal expiry.
Connector signs each webhook attempt over its exact body bytes and a fresh delivery timestamp. Receivers verify the signature and scope before admitting the event to durable storage.
Event envelope
The envelope identifies the source observation independently of its delivery:
{
"schema_version": 1,
"event_id": "evt_store_42",
"type": "external.record.updated",
"organization_id": "org_store",
"connection_id": "con_catalog",
"grant_revision": 4,
"occurred_at": "2026-07-01T18:00:00Z",
"recorded_at": "2026-07-01T18:00:02Z",
"test": false,
"data": {
"resource_key": "res_store_release",
"source_revision": 2,
"state": "active"
}
}event_id stays the same across attempts and manual replay. A delivery has its
own delivery ID. occurred_at records the source observation; recorded_at
records journal admission. Neither timestamp guarantees arrival order.
Event types
Subscriptions select explicit types rather than a wildcard:
| Type | Meaning | Data references |
|---|---|---|
inventory.upserted | Permitted native inventory changed | Resource key and source revision |
inventory.removed | Source inventory left the visible set | Resource key |
security.summary.updated | A mapped security observation changed | Resource key, source revision, and permitted severity |
external.record.updated | A custom source accepted a record revision | Resource key and source revision |
external.record.removed | A custom source removed present context | Resource key |
connection.state.changed | Connection lifecycle or health changed | Connection state |
mapping.changed | A resource relationship changed | Affected resource key |
operation.completed | A Connector operation reached a terminal result | Operation ID and state |
subscription.test | A synthetic receiver test | Test state; test is true |
Source references can be absent when present authorization requires redaction. Read the current resource before a dependent action. A removal event establishes visibility loss; it does not distinguish a source deletion from reduced permission by itself.
Signature headers and signed bytes
Each request carries the following headers:
| Header | Value |
|---|---|
Connector-Timestamp | ASCII decimal Unix time in seconds |
Connector-Signature | 64 hexadecimal characters containing an HMAC-SHA256 digest |
Connector-Secret-Id | Signing-secret version used for this attempt |
Connector-Event-Id | Event ID that must match the signed body |
Connector-Delivery-Id | Attempt's delivery reference for diagnostics |
The signing secret decodes from base64 to 32 bytes. The signed message is the timestamp header, a period, and the unmodified body bytes. Compare the expected digest with the supplied signature using constant-time comparison. Reject timestamps more than 300 seconds from the receiver's clock in either direction.
Verify the signature before JSON parsing. Then require envelope version 1, the expected organization and connection, an allowed event type, and matching event IDs. Preserve the body through any reverse proxy without reserialization. Do not use the management API key as the signing secret.
Acknowledgement and retries
Any 2xx response acknowledges receiver admission. Persist the verified event
or enqueue it durably before acknowledging. The acknowledgement does not
establish that a catalog update or native response completed.
The response timeout is 10 seconds. Transport failures, 408, 429, and 5xx
responses retry up to 8 attempts within 24 hours. Connector honors Retry-After
within the remaining window. Other responses, including redirects, end the
delivery as failed. Connector does not follow redirects.
Retries and manual replay can repeat an event. Deduplicate by organization, connection, and event ID. Keep admission records for the 7-day replay horizon and until downstream processing finishes. Apply source revisions when updating state; an earlier revision cannot replace a later observation.
Scope changes and replay
Connector retains transport events and delivery payloads for 7 days. Replays recheck the active grant, receiver configuration, and caller authorization. Reduced permission redacts pending content or suppresses delivery; replay does not restore the earlier broader grant.
An expired event returns 410 event_expired. Refresh present state through a
complete resource snapshot instead of expecting
expired history to reappear. Destination copies follow their own retention.
Signing-secret rotation
A subscription can hold at most 2 active signing-secret versions. Creating a replacement makes it the signing version for subsequent attempts. Keep the previous verifier until a test using the replacement succeeds, then revoke the previous version and remove it from the receiver.
For a compromised secret, disable delivery and revoke the affected version before restoring the receiver. The Subscription API defines creation and revocation; Receive Connector events provides a runnable receiver and test procedure.