Core Conceptsv1

Webhooks

Send Connect events to your own systems the moment something happens, and check that each one really came from Nexra.

Updated 11/10/2026

On this page

Webhooks let Nexra tell your other systems when something happens in Connect: a flow run fails, an approval is needed, a connection starts having trouble, a reconciliation finds something to review or a contract obligation falls due. Instead of checking the console, your system receives a message straight away and can raise an alert, open a ticket or start its own process.

Add an endpoint

An endpoint is a web address on a system you own. Open Webhooks in the console and choose Add endpoint:

Name: something your team will recognise, up to 120 characters.

Web address: must start with https://.

Test or Live: a Test endpoint receives events from test-mode runs and test connections. A Live endpoint receives events from live (production) activity. Start with Test while you set things up, then add a Live endpoint.

Events: tick the events it should hear about (up to 30). Each group has Select all in group.

When you add the endpoint, Nexra shows its signing secret once. Copy it and give it to whoever looks after the receiving system; it is not shown again.

Use Send a test event to check the endpoint works. The result appears in its delivery list straight away.

Events

EventSent when
flow.run.succeededA flow run finished and every record went through
flow.run.failedA flow run stopped before it could finish
flow.run.partially_succeededA flow run finished, but some records did not go through
record.dead_letteredA record could not be processed after several tries and is set aside
approval.requestedA change is waiting for someone to approve it
approval.decidedSomeone approved or rejected a change
connection.health_changedA connection became healthy again or started having trouble
connection.live_check.failedNexra could not reach a connected app during a live check
integration.pausedSomeone paused an integration
integration.resumedA paused integration is running again
integration.suspendedAn integration was stopped for safety
integration.deletedSomeone deleted an integration
reconciliation.run.completedA reconciliation finished checking your records
reconciliation.item.needs_reviewA reconciliation found a difference someone should look at
go_live.completedAn integration finished going live
obligation.due_soonA contract obligation comes within its reminder time
obligation.overdueA contract obligation passes its due date without being marked done
workspace.daily_digestOnce a day: the workspace digest, the same summary the console shows

Once money movement is switched on for your workspace, payment.initiated, payment.completed and payment.failed are offered too (see Stablecoins with Circle and Yellow Card).

Test sends use the type sandbox.test. The console's What the events look like section shows an example of every event.

Obligation reminders

obligation.due_soon and obligation.overdue come from Nexra's daily reminder check (see Obligations and reminders). Each is sent once per due date, to both Test and Live endpoints that choose it, so you can open a ticket or post to a channel without any risk of duplicates for the same date. The message carries the contract reference, counterparty, clause, due date, how often it repeats, the reminder time and a plain sentence such as "Send the monthly volume statement (Gas supply agreement GSA-2024-07, Northfield Power) is due in 14 days, on 31 October 2026." It never names the owner.

json
{
  "id": "evt_8c1d2e3f4a5b6c7d8e9f0a1b",
  "type": "obligation.due_soon",
  "version": "2026-10-01",
  "createdAt": "2026-10-17T06:00:12.000Z",
  "mode": "live",
  "workspaceId": "cmworkspace01",
  "data": {
    "obligation": {
      "id": "obl_01",
      "reference": "Gas supply agreement GSA-2024-07",
      "counterparty": "Northfield Power",
      "sourceClause": "7.2",
      "dueDate": "2026-10-31",
      "recurrence": "monthly",
      "reminderLeadDays": 14
    },
    "reminder": {
      "kind": "due_soon",
      "summary": "Send the monthly volume statement (Gas supply agreement GSA-2024-07, Northfield Power) is due in 14 days, on 31 October 2026."
    },
    "links": { "obligation": "https://<your console>/dashboard/connect/obligations/obl_01" }
  }
}

The daily digest (workspace.daily_digest) has an Obligations section listing what is overdue and due soon, with the counts obligationsDueSoon and obligationsOverdue.

What a message looks like

Nexra sends a POST request with a JSON body. Every event shares the same envelope:

FieldMeaning
idThe event ID (evt_…). Use it to ignore duplicates.
typeThe event, for example flow.run.failed
versionThe event format version, currently 2026-10-01
createdAtWhen the event happened
modetest or live
workspaceIdThe workspace the event belongs to
dataDetails of what happened

Example flow.run.failed event:

json
{
  "id": "evt_3f9a1c2b7d4e5f60718293a4",
  "type": "flow.run.failed",
  "version": "2026-10-01",
  "createdAt": "2026-10-10T09:31:12.000Z",
  "mode": "live",
  "workspaceId": "cmworkspace01",
  "data": {
    "run": {
      "id": "cmexec01run",
      "status": "failed",
      "trigger": "schedule",
      "startedAt": "2026-10-10T09:30:00.000Z",
      "completedAt": "2026-10-10T09:31:12.000Z",
      "durationMs": 72000
    },
    "flow": { "id": "cmflow01orders", "name": "Shopify orders to Xero invoices" },
    "integration": { "id": "cmint01shop", "name": "Online shop to accounts" },
    "counts": { "received": 42, "succeeded": 0, "failed": 42, "skipped": 0 },
    "reason": {
      "code": "run_deadline_exceeded",
      "message": "The run reached its time limit, so Nexra stopped it before sending more."
    },
    "links": { "run": "https://<your console>/dashboard/connect/runs/cmexec01run" }
  }
}

Messages contain IDs, names, counts, statuses and links only. They never contain record contents, credentials or secrets; follow the link to see the details in the console.

Each request also carries these headers:

HeaderValue
Content-Typeapplication/json
X-Amakora-EventThe event type
X-Amakora-Event-IdThe event ID; use it to ignore duplicates
X-Amakora-Delivery-IdThe delivery's ID
X-Amakora-Signaturet=<unix seconds>,v1=<hex HMAC-SHA256>

Verify the signature

Check every message before you act on it. v1 is the hex HMAC-SHA256 of <t>.<raw request body>, made with the endpoint's signing secret. Reject the message if the signature does not match, or if t is more than five minutes old.

javascript
import crypto from "node:crypto";

export function verifyNexraSignature(rawBody, header, secret) {
  const parts = Object.fromEntries(
    header.split(",").map((part) => {
      const index = part.indexOf("=");
      return [part.slice(0, index).trim(), part.slice(index + 1).trim()];
    }),
  );
  const timestamp = Number(parts.t);
  if (!Number.isFinite(timestamp)) return false;
  // Reject anything more than 5 minutes old (or from the future).
  if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex");
  const received = Buffer.from(parts.v1 ?? "", "hex");
  const wanted = Buffer.from(expected, "hex");
  return received.length === wanted.length && crypto.timingSafeEqual(received, wanted);
}

Always verify against the raw body exactly as it arrived, before parsing the JSON.

Retries and resending

A delivery counts as delivered when your system answers with any 2xx status within 8 seconds. Do slow work after you answer.

If your system can't be reached, takes too long, or answers 408, 425, 429 or any 5xx, Nexra tries again with growing waits (about 5 seconds, then 10, 20 and so on, up to 5 minutes), up to 5 tries in total.

Any other 4xx answer means your system refused the event, so Nexra stops straight away and doesn't retry.

A message can occasionally arrive more than once or out of order. Use the event ID to ignore duplicates.

Each delivery shows a status, how many tries it had and, when something went wrong, why in plain words:

What you seeMeaning
Waiting to send, SendingOn its way. While it can still be retried, tries show as "2 of 5"
Waiting to retry, for example "Your endpoint had an error (503). Nexra will try again."A try failed with an answer worth retrying
DeliveredYour system answered with a 2xx
Stopped after 1 try: "Your endpoint refused the event (422), so Nexra stopped."Your system answered with a 4xx that isn't retried
Stopped after 5 tries: "Your endpoint had an error (503). Nexra used all its tries."Every try failed
Stopped: "The endpoint was turned off, so Nexra stopped sending."The endpoint was turned off before the delivery finished

Other reasons name the exact problem, such as "Your endpoint took too long to answer", "Nexra couldn't find your endpoint's address" or "Your endpoint's security certificate wasn't accepted".

Fix the problem, then choose Resend on the delivery to send it again with the same event ID and a fresh set of tries.

The delivery list for each endpoint shows the latest 100 deliveries, with the result, each try, the response code, how long it took and exactly what was sent. Endpoints show whether they are healthy or having trouble, and when they last received an event.

Change the signing secret

Choose Change secret on an endpoint to issue a new signing secret. The old secret stops working immediately, so update the receiving system straight away. The new secret is shown once.

Turn an endpoint off

Turn off stops all events to an endpoint and cancels deliveries still waiting to retry. Its delivery history stays in the console, and you can turn it back on at any time.

Only workspace owners, admins and developers can add endpoints, send test events, resend deliveries, change secrets or turn endpoints off. Other members can view endpoints and deliveries; the buttons they can't use are shown switched off, with the reason.

Need a hand?

Ask Nexra Agent for implementation steps or error guidance.

Ask Nexra Agent