> For the complete documentation index, see [llms.txt](https://codemash.gitbook.io/codemash/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://codemash.gitbook.io/codemash/cloud/project/settings/webhooks.md).

# Webhooks

Send signed event notifications from the project to your own HTTP endpoints — signing secret, extra headers, destinations.

**Where:** Project → Settings → **Webhooks** · `/projects/<project>/settings?tab=Webhooks`

The project has **one** webhook integration: one signing secret, one set of extra headers, and any number of **destinations**. Every delivery is a signed JSON POST to each destination that subscribed to the event. The badge says **Configured** once the signing secret exists, **Not configured** before.

## Before you start

* An account role that may update the project settings.
* An endpoint that accepts a JSON POST, for example `https://hooks.acme.example.com/norbix`.

## Steps

1. Open **Settings → Webhooks**. Under **Signing secret** press **Generate**. Copy the secret into your receiver now — the page says *Store this secret in your subscriber before closing the page.* Later, **Reveal** shows it again.

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-2d9134d6ea400c95a9acb30efdcd987d091e60d9%2Fwebhooks-2.png?alt=media" alt="Webhooks tab right after Generate: the new secret (hidden in this picture) and the note to store it"><figcaption><p>The secret is generated (blanked here).</p></figcaption></figure>
2. (Optional) Under **Extra headers**, press **+ Add Variable**, enter a name and a value (for example `X-Api-Key`), and press **Save Headers**. They are sent with every delivery.
3. Under **Destinations**, press **Add Destination** and fill in the form:

   | Field             | Required | What it does                                                                                                                                                                                                                                                                                                                                                                    | Example                                 |
   | ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |
   | Display name      | yes      | How the destination is listed.                                                                                                                                                                                                                                                                                                                                                  | `Order service`                         |
   | Endpoint URL      | yes      | The full http(s) URL that receives the POST.                                                                                                                                                                                                                                                                                                                                    | `https://hooks.acme.example.com/norbix` |
   | Subscribed events | no       | Tick the events to deliver: **Database** (`database.record.inserted`, `…updated`, `…deleted`, `…replaced`, `…responsibilityChanged`, `database.records.inserted`, `…updated`, `…deleted`), **Membership** (`membership.user.registered`, `…invited`, `…verified`, `…updated`, `…deleted`, `…blocked`, `…reactivated`), **Files** (`files.file.uploaded`, `files.file.deleted`). | `database.record.inserted`              |
   | Extra headers     | no       | Headers for this destination only; they win over the shared ones.                                                                                                                                                                                                                                                                                                               | `X-Tenant` = `acme`                     |
   | Enabled           | —        | Off pauses deliveries.                                                                                                                                                                                                                                                                                                                                                          | on                                      |

   <figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-68bc5ec646041ef96ee8bcb9f0f57910df23d7b8%2Fwebhooks-3.png?alt=media" alt="Add Destination dialog with Order service, the endpoint URL, the event checkboxes, Extra headers and Enabled"><figcaption><p>A new destination.</p></figcaption></figure>
4. Press **Add Destination**.

## Result

Cloud shows **Destination has been added** and the destination is listed with its URL, an **Enabled** switch and **Change**. The badge reads **Configured**.

<figure><img src="https://712692422-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FHy372bqsaex2cqS3ikhL%2Fuploads%2Fgit-blob-fac604f396253d8d04fe3cb4578d641ac57afbdf%2Fwebhooks-4.png?alt=media" alt="Webhooks tab: Configured, hidden secret with Reveal and Regenerate, Extra headers, and the Order service destination"><figcaption><p>One destination.</p></figcaption></figure>

Every delivery is a JSON POST with the headers `X-Norbix-Timestamp` and `X-Norbix-Signature`. Compute HMAC-SHA256 of `{timestamp}.{body}` with the signing secret and compare it with the signature before you trust the body. The body:

```json
{
  "id": "6f1c2b0e9a4d4c7e8f3a1b2c3d4e5f60",
  "eventId": "0a9b8c7d6e5f40312a1b2c3d4e5f6a7b",
  "event": "database.record.inserted",
  "createdOn": "2026-10-06T08:15:00Z",
  "accountId": "acc_Cz5oZpeeTeLtkYHYTJrZ4",
  "projectId": "pr_7FUKofhEBNMnISkqust2De",
  "triggerId": null,
  "data": { "title": "The Hobbit" }
}
```

`id` is one per delivery (a retry keeps it); `eventId` is one per change. A database change can reach a destination twice — from the event subscription and from a schema trigger's **Call Webhook** action — with the same `eventId`; skip an `eventId` you already handled. Destinations saved before the secret exists stay silent until you press **Generate**.

## Change or remove it later

* **Pause** — the destination's **Enabled** switch.
* **Edit** — **Change** on its row (the form button reads **Save Changes**).
* **Delete** — **Change**, then the red **Delete…** button and the confirmation; deliveries to that endpoint stop at once.
* **Regenerate** the secret — confirm **Regenerate signing secret?**; the old secret stops working immediately, so update every receiver.

## Do it from code

```ts
const { item } = await norbix.hub.webhooks.getWebhookIntegration({ projectId: 'pr_7FUKofhEBNMnISkqust2De' });
console.log(item.destinations.map((d) => [d.destinationName, d.endpointUrl, d.isEnabled]));
// [["Order service","https://hooks.acme.example.com/norbix",true]]
```

```sh
norbix hub webhooks integration get
```

The client setup is on the [Account page](/codemash/cloud/account.md#use-it-from-code). API: [Get Webhook Integration](/codemash/api-reference/webhooks/integration/get-webhook-integration.md) · [Rotate Webhook Integration Secret](/codemash/api-reference/webhooks/integration/rotate-webhook-integration-secret.md) · [Save Webhook Destination](/codemash/api-reference/webhooks/destinations/save-webhook-destination.md) · [Remove Webhook Destination](/codemash/api-reference/webhooks/destinations/remove-webhook-destination.md)
