Skip to main content
POST
Register an endpoint and mint its signing secret.

Authorizations

Authorization
string
header
required

Authorization: Bearer vsk_live_…. Chosen over a bespoke X-API-KEY header because every client, proxy and log-redaction rule already knows this one. What a key may DO is its scopes — see x-scopes at the root of this document and x-required-scope on each operation. The scope list is not written here because OpenAPI reserves a requirement’s scope array for oauth2 and openIdConnect and requires it to be empty for an http scheme.

Body

application/json

Where to deliver, what to deliver, and optionally which brand only.

The registration.

url
string
required

An https:// URL we will POST to. It must be reachable from the public internet and must not carry credentials in the URL — the signature is how a delivery proves it came from us.

Example:

"https://api.example.test/hooks/vumasign"

events
enum<string>[]
required

At least one event type. ⚠️ An empty array is refused rather than read as "everything": an endpoint subscribed to nothing is a support ticket, and this API already has one place where an empty list means "all" (an API key’s scopes) — two opposite readings of an empty array is how somebody eventually gets one of them wrong. Duplicates are collapsed.

One event type.

Available options:
envelope.sent,
envelope.completed,
envelope.declined,
envelope.voided,
envelope.expired,
envelope.sealed,
envelope.sealing_failed,
recipient.completed
brand_id
string<uuid> | null

Optional, default null. Filter deliveries to one brand. ⚠️ ROUTING, NOT ISOLATION — see the property of the same name on the endpoint.

Example:

null

Response

The endpoint, and the signing secret — for the only time.

The endpoint and its secret.

id
string<uuid>
required

The endpoint’s id. A bare uuid.

url
string
required

Where deliveries are POSTed. https:// only, no credentials, and not a private or loopback address — deliveries are made from inside our network.

subscribed_events
enum<string>[]
required

What this endpoint hears about. Never empty. ⚠️ An unknown name is refused at registration rather than accepted and never delivered.

One event type.

Available options:
envelope.sent,
envelope.completed,
envelope.declined,
envelope.voided,
envelope.expired,
envelope.sealed,
envelope.sealing_failed,
recipient.completed
brand_id
string<uuid> | null
required

Deliver only envelopes carrying this brand; null for every envelope in the organisation.

⚠️ THIS IS ROUTING, NOT ISOLATION. Any key on this organisation can read every envelope in it whatever brand it carries — there is no brand predicate in any access rule anywhere. Filtering decides which events are POSTed to which URL; it does not, and cannot, stop a consumer learning about another brand by asking. Do not build a permission boundary out of it.

active
boolean
required

Whether we are delivering. False either because you deactivated it or because it was auto-disabled after failing for the whole health window — disabled_reason says which, in prose.

consecutive_failures
integer
required

⚠️ DELIVERIES THAT EXHAUSTED THE WHOLE LADDER SINCE THE LAST SUCCESS, not individual attempts. One unreachable host over one event counts once here, not seven times.

last_success_at
string<date-time> | null
required

The last 2xx we received. Null if there has never been one.

last_failure_at
string<date-time> | null
required

The last delivery that used up its ladder.

disabled_at
string<date-time> | null
required

When delivery stopped. Null while active.

disabled_reason
string | null
required

Why, in prose for a person. Null while active. ⚠️ This is the field that answers "why did my endpoint stop receiving events" without a support ticket.

created_at
string<date-time>
required

ISO 8601, UTC.

secret
string
required

⚠️ SHOWN ONCE, HERE. This is the key the Vumasign-Signature header is computed under. Treat it as a credential: it is not in any log of ours and it must not be in one of yours.