Skip to content
Get an API key
Reference

Webhooks

9 endpoints in this family.

List your webhook subscriptions

GET/api/v1/webhooks

Returns where Nodium calls you and for which events, plus the list of every event name you can subscribe to. Secrets are never returned.

Response

The subscriptions, the event catalogue and the latest deliveries.

  • data.eventsstring[]

    Every event name you can subscribe to.

  • data.subscriptionsWebhookSubscription[]

    Your subscriptions, newest first.

  • data.deliveriesWebhookDelivery[]

    The 50 most recent deliveries. The full log is GET /webhooks/deliveries.

Refusals

  • 404not_foundThe key acts on "My company" but is pinned to it: those subscriptions also carry the events of every client, so they need a key that is not pinned.
curl https://nodium.io/api/v1/webhooks \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "events": [ "…" ], "subscriptions": [ {} ], "deliveries": [ {} ] }}

Subscribe to events

POST/api/v1/webhooks

Registers an HTTPS address that Nodium calls when something happens. Without this your software has to poll, which is slower and heavier for both of us.

The response carries the signing secret once and never again: store it now. Each call is signed with it, and is retried up to six times with growing delays (1 min, 5 min, 30 min, 2 h, 12 h).

Body

  • urlstringrequired

    Where to call. Must start with https://.

  • eventsstring[]required

    Which events to receive. * means all of them.

  • channelIdsstring[]

    Only receive the events of these channels (numbers). Empty or absent: all channels. An event that belongs to no channel (a template status, a consent change) is not delivered to a limited subscription.

  • labelstring

    A name for you, shown in Nodium.

Response

The subscription id and its signing secret — shown only here.

  • data.idstring

    The subscription id.

  • data.secretstring

    The signing secret, whsec_…. Shown only here.

Refusals

  • 404not_foundThe key acts on "My company" but is pinned to it: that subscription also carries the events of every client, so it needs a key that is not pinned.
  • 422webhook_url_not_httpsThe address must start with https://.
  • 422invalid_requestNo event, an unknown event name, or a channel outside this client (on "My company": outside your account).
curl -X POST https://nodium.io/api/v1/webhooks \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "…", "events": [ "…" ] }'

Response

200 OK
{ "data": { "id": "…", "secret": "…" }}

Unsubscribe

DEL/api/v1/webhooks/{id}

Removes the subscription. Nothing more is delivered to that address.

Path parameters

  • idstring

    The subscription id.

Response

Confirmation that it is gone.

  • data.okboolean

    Always true.

Refusals

  • 404not_foundNo such subscription, or not one this key can reach (on "My company", the key must not be pinned).
curl -X DELETE https://nodium.io/api/v1/webhooks/<id> \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "ok": true }}

Get a subscription

GET/api/v1/webhooks/{id}

One webhook subscription: where Nodium calls you, for which events and numbers, and how its last deliveries went. The secret is never returned.

Path parameters

  • idstring

    The subscription id.

Response

The subscription.

Refusals

  • 404not_foundNo such subscription, or not one this key can reach (on "My company", the key must not be pinned).
curl https://nodium.io/api/v1/webhooks/<id> \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "subscription": { "id": "…", "url": "…", "events": [], "channelIds": [], "label": "…", "isActive": true, "lastDeliveredAt": "…", "lastError": "…", "previousSecretValidUntil": "…", "createdAt": "…" } }}

Change a subscription

PATCH/api/v1/webhooks/{id}

Moves the address, changes the events, renames, or pauses the subscription. Send only the fields you change. The secret does not change — rotate it with POST /webhooks/{id}/rotate-secret.

Path parameters

  • idstring

    The subscription id.

Body

  • urlstring

    A new https address.

  • eventsstring[]

    The events to receive from now on. * means all of them.

  • labelstring

    A name for you, shown in Nodium.

  • channelIdsstring[]

    Limit the subscription to the events of these channels (numbers); an empty list means all channels.

  • isActiveboolean

    False pauses delivery: events keep queuing and are sent, in order, when set back to true. Nodium also pauses a subscription by itself after 50 consecutive failed attempts with nothing delivered for 24 h (see disabledReason).

Response

The subscription, updated.

  • data.idstring

    The subscription id.

  • data.urlstring

    The https address called.

  • data.eventsstring[]

    The events delivered; * means all.

  • data.channelIdsstring[]

    The channels (numbers) whose events are delivered; empty means all channels.

  • data.labelstring

    Its name.

  • data.isActiveboolean

    A paused subscription receives nothing.

  • data.lastDeliveredAtstring

    The last successful call, ISO 8601, or null.

  • data.lastErrorstring

    What went wrong last time, or null.

  • data.previousSecretValidUntilstring

    During a rotation: until when the old secret still signs. null otherwise.

  • data.createdAtstring

    ISO 8601.

Refusals

  • 404not_foundNo such subscription, or not one this key can reach (on "My company", the key must not be pinned).
  • 422webhook_url_not_httpsThe address must start with https://.
  • 422invalid_requestNothing to change, an unknown event, or a field of the wrong type.
curl -X PATCH https://nodium.io/api/v1/webhooks/<id> \ -H "Authorization: Bearer $NODIUM_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "…", "events": [ "…" ] }'

Response

200 OK
{ "data": { "id": "…", "url": "…", "events": [ "…" ], "channelIds": [ "…" ], "label": "…", "isActive": true, "lastDeliveredAt": "…", "lastError": "…", "previousSecretValidUntil": "…", "createdAt": "…" }}

Rotate the signing secret

POST/api/v1/webhooks/{id}/rotate-secret

Issues a new signing secret, returned once. For the next 24 hours every call carries two signatures — v1= with the new secret, then v1= with the old one — so you can deploy the new secret without missing a call. Accept a call when any v1 matches.

Rotating twice in a row forgets the oldest secret straight away.

Path parameters

  • idstring

    The subscription id.

Response

The new secret, and until when the old one still signs.

  • data.secretstring

    The new signing secret, whsec_…. Shown only here.

  • data.previousValidUntilstring

    ISO date until which the old secret still signs.

Refusals

  • 404not_foundNo such subscription, or not one this key can reach (on "My company", the key must not be pinned).
curl -X POST https://nodium.io/api/v1/webhooks/<id>/rotate-secret \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "secret": "…", "previousValidUntil": "…" }}

Send a test call

POST/api/v1/webhooks/{id}/test

Fires one signed message.received call at your address right now (the sample from the event catalogue, with data.test set to true) and reports what came back: status code, round trip, and the error if there was one. Use it to prove your endpoint and your signature check before going live.

Path parameters

  • idstring

    The subscription id.

Response

What your endpoint answered: status, duration, and any error.

  • data.okboolean

    Whether it answered 2xx.

  • data.statusinteger

    The HTTP status, or null when unreachable.

  • data.msinteger

    The round trip.

  • data.errorstring

    What went wrong, or null.

Refusals

  • 404not_foundNo such subscription, or not one this key can reach (on "My company", the key must not be pinned).
curl -X POST https://nodium.io/api/v1/webhooks/<id>/test \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "ok": true, "status": 0, "ms": 0, "error": "…" }}

List deliveries

GET/api/v1/webhooks/deliveries

Every call Nodium made — or is about to make — to your addresses: which event, how many attempts, what your server answered, and when the next attempt is due. Newest first.

This is what settles "we never received it": a failed delivery with lastError tells you what your endpoint said; no delivery at all means the event did not happen.

Query parameters

  • subscriptionIdstring

    Only this subscription.

  • statusstring

    Only deliveries in this state.

    pendingdeliveredfailed

  • eventstring

    Only this event, e.g. message.received.

  • limitinteger

    Page size, 1 to 100. Default 50.

  • cursorstring

    The nextCursor of the previous page.

Response

A page of deliveries, newest first.

  • The deliveries.

  • data.nextCursorstring

    Pass it as cursor for the next page; null at the end.

  • data.hasMoreboolean

    Whether another page exists.

Refusals

  • 404not_foundThe key acts on "My company" but is pinned to it: those deliveries also carry the events of every client, so they need a key that is not pinned.
curl https://nodium.io/api/v1/webhooks/deliveries \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "items": [ {} ], "nextCursor": "…", "hasMore": true }}

Redeliver an event

POST/api/v1/webhooks/deliveries/{id}/redeliver

Queues the same event again for the same subscription — typically after your endpoint was down and the delivery ended failed. It goes out within a minute, with fresh retries.

The payload is identical, including its id: if you already processed it, your deduplication on id will skip it.

Path parameters

  • idstring

    The delivery id.

Response

The new delivery, pending.

  • data.idstring

    The delivery id, also sent as X-Nodium-Delivery.

  • data.subscriptionIdstring

    The subscription.

  • data.eventstring

    The event name.

  • data.eventIdstring

    The event's own id (evt_…), the same across redeliveries: deduplicate on it.

  • data.statusstring

    failed after six attempts.

    pendingdeliveredfailed

  • data.attemptsinteger

    Attempts so far.

  • data.responseStatusinteger

    The HTTP status your server answered, or null.

  • data.lastErrorstring

    What went wrong, or null.

  • data.nextAttemptAtstring

    When the next attempt is due, for a pending delivery.

  • data.createdAtstring

    ISO 8601.

  • data.deliveredAtstring

    ISO 8601, or null.

Refusals

  • 404not_foundNo such delivery in this workspace, not one this key can reach (on "My company", the key must not be pinned), its subscription is paused or gone, or its payload was already erased by content retention.
curl -X POST https://nodium.io/api/v1/webhooks/deliveries/<id>/redeliver \ -H "Authorization: Bearer $NODIUM_KEY"

Response

200 OK
{ "data": { "id": "…", "subscriptionId": "…", "event": "…", "eventId": "…", "status": "pending", "attempts": 0, "responseStatus": 0, "lastError": "…", "nextAttemptAt": "…", "createdAt": "…", "deliveredAt": "…" }}