WebhookSubscription
object type
A WebhookSubscription — the documented non-GraphQL edge OUT (mirrors the inbound Stripe webhook edge): the merchant registers an https target URL + a filtered set event names (the DERIVED deliverable universe — transition success events + per-construct birth names; enumerate it via the integrator docs), and the delivery lane POSTs HMAC-signed THIN payloads at-least-once with retries/backoff/DLQ. The payload names {id, event, occurredAt, construct{type,id}, revision, subscriptionId} — the receiver dedupes on id and READS the record through this SAME API with its ApiKey (no fat payloads, no parallel surface). Signing mirrors the Stripe scheme (almondtill-signature: t=<unix>,v1=<hex HMAC-SHA256 of <t>.<body> under the secret>); the secret shows ONCE at create/rotate and lives in the non-streamed credential store, never on the record. GROUP-parented (parentId === rootId); born active; 20 consecutive delivery failures fire the automatic active → suspended flip (system:repeated_delivery_failure — the deliverer, never a caller); reactivate serves both inactive → active and suspended → active (fix the endpoint, then reactivate; missed events do NOT replay — re-sync via the API). Owner-gated end to end (the mintApiKey posture); NOT searchable (integration config — reached via the owner-gated list).
Fields
| Field | Type | Notes |
|---|---|---|
id | ID ID! | The record’s id — a UUID the platform assigned when the record was created; every reference to this record uses it. |
sysId | String String! | The group-scoped human-facing system id (WH-…). |
type | String String! | The kind of record — always WebhookSubscription here. |
caption | String String! | The record’s display name — what people see it called. |
status | String String! | The FSM state: active | inactive | suspended | doomed. |
parentId | ID ID! | The parent = the org GROUP (the parent-is-the-org-group clause); parentId === rootId always (the Affiliate class — deliveries span the whole group’s orgs). |
rootId | ID ID! | The org-group family root. |
createdAt | String String! | When the record was created, as a UTC timestamp. |
updatedAt | String String! | When the record last changed, as a UTC timestamp. |
revisionNum | Int Int! | How many times this record has been edited; the first save is 0. |
revision | ID ID! | The OCC revision token — supply it on every mutation of this record; rotates on every write. |
refCaptions | RefCaption [RefCaption!]! | The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption. |
targetUrl | String String! | The https delivery endpoint (the egress law: https only, no credentials, no explicit port, no IP-literal/localhost/private-suffix hosts; ≤512 chars). Mutable via update — fixing the endpoint is the suspended-repair flow. |
eventTypes | String [String!]! | The event-name filter set (1..64, deduped) — each name must be in the DERIVED deliverable universe (transition success events + at.<domain>.<entity>.create.ok.v1 birth names over the whole construct catalog). |
consecutiveFailures | Int Int! | Consecutive delivery-attempt failures (the deliverer’s counter — reset by the first success after failures; NEVER written on steady-state success). At 20 the automatic suspend fires. |
lastFailureAt | String | The last failed delivery attempt’s instant (failure-path-only; stands as history after recovery until the next failure overwrites). |
lastFailureCode | String | The last failure’s short token — an HTTP status (http_500) or a fetch-error class (timeout, network); never a response body. |
suspendedAt | String | Stamped by the automatic suspend flip; cleared by reactivate. |
secretRotatedAt | String | The last signing-secret rotation’s instant; null until the first rotation. |
pluginId | ID | The owning Plugin (optional): this subscription is part of that plugin’s declared event feed; IMMUTABLE at birth (a re-bind = a new subscription); an un-doomed bound subscription blocks the plugin’s doom. |