AlmondTill/G3N API

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

FieldTypeNotes
idID ID!The record’s id — a UUID the platform assigned when the record was created; every reference to this record uses it.
sysIdString String!The group-scoped human-facing system id (WH-…).
typeString String!The kind of record — always WebhookSubscription here.
captionString String!The record’s display name — what people see it called.
statusString String!The FSM state: active | inactive | suspended | doomed.
parentIdID 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).
rootIdID ID!The org-group family root.
createdAtString String!When the record was created, as a UTC timestamp.
updatedAtString String!When the record last changed, as a UTC timestamp.
revisionNumInt Int!How many times this record has been edited; the first save is 0.
revisionID ID!The OCC revision token — supply it on every mutation of this record; rotates on every write.
refCaptionsRefCaption [RefCaption!]!The server-composed captions of this record's declared references (the referenced-caption rule) — one row per referenced id; see RefCaption.
targetUrlString 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.
eventTypesString [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).
consecutiveFailuresInt 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.
lastFailureAtStringThe last failed delivery attempt’s instant (failure-path-only; stands as history after recovery until the next failure overwrites).
lastFailureCodeStringThe last failure’s short token — an HTTP status (http_500) or a fetch-error class (timeout, network); never a response body.
suspendedAtStringStamped by the automatic suspend flip; cleared by reactivate.
secretRotatedAtStringThe last signing-secret rotation’s instant; null until the first rotation.
pluginIdIDThe 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.

Used by