> ## Documentation Index
> Fetch the complete documentation index at: https://docs.terminus.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Outbound webhook connectors

> Push approved records to your own HTTPS endpoint automatically, with signed, idempotent deliveries and no manual exporting.

<Info>
  An outbound connector pushes your governed records to another system as they change. When a submission is approved, or an approved record is later edited, archived, or deleted, Terminus Hub sends a signed JSON POST to your HTTPS endpoint. Connectors are managed by account **owners and admins** under **Settings**, then **Outbound Connectors**, and are available on every plan.
</Info>

## What gets delivered, and when

A connector delivers one request per record change on the taxonomies you bind it to:

* **Approving a submission** delivers each of its records.
* **Editing an approved record** delivers the updated record.
* **Archiving or deleting a record** delivers a tombstone, so the receiving system hears about removals instead of silently drifting.
* **Unchanged records are skipped.** Terminus Hub fingerprints each exported payload and does not redeliver a record whose exported content is identical to what the connector last received.

The request body is the record's **public API representation**: byte-for-byte the same JSON that `GET /api/v1/records/:id` returns. Whatever parses your API pulls parses your webhooks too. Field values are keyed by the field's stable ID with the field's name and type alongside, so renaming a field later does not break your integration. Dropdown values arrive as `{ code, label }` pairs, and values are delivered exactly as stored on the record, never recomputed.

## Set up a connector

<Steps>
  <Step title="Create the connector">
    In **Settings**, then **Outbound Connectors**, click **New**. Give it a name and the destination **URL**. The URL must be `https`; plain `http` is rejected. The connector starts out **pending** and cannot receive real deliveries yet.
  </Step>

  <Step title="Copy the signing secret">
    The signing secret is shown **once**, on creation. Store it in the receiving system now; every request is signed with it. If you lose it, use **Regenerate secret**, which invalidates the old secret immediately, so update the receiver at the same time.
  </Step>

  <Step title="Bind it to data">
    In the connector's **Bindings** section, choose the taxonomy whose records should sync, optionally narrowed to a single workspace. Leaving the workspace on "All workspaces" covers every workspace using that taxonomy. A connector with no enabled binding receives nothing, no matter its status.
  </Step>

  <Step title="Send a test">
    Click **Test**. Terminus Hub sends a request with `X-Terminus-Action: test` to your URL, signed exactly like a real delivery. Your endpoint must respond successfully at least once.
  </Step>

  <Step title="Activate">
    Click **Activate**, which is enabled only after a successful test. From then on, approvals and record changes on the bound taxonomies deliver automatically.
  </Step>
</Steps>

## Verify deliveries on your end

Every request carries three headers:

| Header                 | Purpose                                                                                                                                          |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| `X-Terminus-Signature` | `sha256=` followed by the hex HMAC-SHA256 of the raw request body, computed with your signing secret. Proves the request came from Terminus Hub. |
| `Idempotency-Key`      | A stable key for this exact payload. Deduplicate on it: a retried or replayed delivery reuses the same key.                                      |
| `X-Terminus-Action`    | `create`, `update`, `delete`, or `test`.                                                                                                         |

To verify a request, compute HMAC-SHA256 over the **raw** body with your signing secret, hex-encode it, and compare against the header value after its `sha256=` prefix, using a constant-time comparison. For example, in Node.js:

```javascript theme={null}
import { createHmac, timingSafeEqual } from "node:crypto";

function verifyTerminusSignature(rawBody, signatureHeader, signingSecret) {
  const expected = createHmac("sha256", signingSecret).update(rawBody).digest("hex");
  const received = signatureHeader.replace(/^sha256=/, "");
  if (received.length !== expected.length) return false;
  return timingSafeEqual(Buffer.from(received, "hex"), Buffer.from(expected, "hex"));
}
```

Verify against the raw bytes of the body, before any JSON parsing or re-serialization; a reformatted body produces a different signature.

## Delivery guarantees and retries

* **Failed deliveries retry automatically**, roughly every 5 minutes, up to 8 attempts per record change. A record that exhausts its retries is picked up again the next time it is approved or changed.
* **Nothing is lost while a connector is paused.** A paused connector keeps queuing deliveries; reactivating it flushes the queue, so records approved during the pause arrive then.
* **Changing the URL pauses an active connector** and clears its test proof. The new destination must pass a test and be reactivated before deliveries resume. Renaming the connector or editing bindings does not interrupt delivery.
* **Deletes always arrive.** A tombstone delivers even if the record was permanently removed in the meantime; it identifies the record by its Terminus ID.
* **A locked account defers, not drops.** If the account is locked over billing, deliveries queue during the lock and flush on reactivation.

## Current limits

* **Webhook destinations only.** There are no built-in destinations for specific SaaS tools; point the connector at your own endpoint or an automation platform that accepts webhooks.
* **Immediate delivery only.** There is no batched or scheduled cadence.
* **No delivery log in the UI.** The connector shows when it last flushed and when its last test succeeded, but there is no per-delivery history screen. Log deliveries on the receiving side if you need an audit trail.
* **Full records only.** Bindings select taxonomies and workspaces, not individual fields; every field of a bound record is exported.

## Gotchas

* **Respond quickly with a 2xx.** Acknowledge the request, then process the payload asynchronously. A slow endpoint risks timing out and being retried, which your idempotency handling should absorb anyway.
* **Expect retries and duplicates.** At-least-once delivery means the same payload can arrive more than once. The `Idempotency-Key` header is identical across retries of the same payload; store processed keys and skip repeats.
* **Records reflect the revision they were created under.** A record approved under an older published revision of the governance model exports with that revision's structure, the same as the public API returns it.

## Related

* [API reference: records](/api-reference/endpoints/records/show-a-record): the payload shape, shared by pull and push.
* [Review and approve submissions](/guides/review-and-approve-submissions): approval is what triggers delivery.
* [Account administration](/account/overview): the rest of the admin area.
