Skip to content

Webhooks

Receive webhooks

Subscribe to committed changes, verify signatures, and recover failed deliveries.

On this page

Subscribe

In Brigg webhook settings, add a public HTTPS endpoint and select the events and resource types your integration needs. An authorized administrator approves the export. An agent can discover event schemas and prepare the configuration for review.

Webhook subscriptions carry explicit access permissions. Adding a resource type or event later does not silently expand an existing subscription. Resource notifications export shared workspace records. Personal private streams are not supported.

Read the event reference for exact event schemas. The existing meeting.completed contract and signature remain supported for existing subscriptions.

Choose resource types

A resource type identifies a kind of record. For example, core:Company means customer companies; it is different from the public operation namespace customers. Workspace apps have their own qualified type identifiers. Copy these values from discovery rather than constructing them.

  1. Call GET https://api.brigg.app/v1/operations using a key permitted to read the records you need.
  2. Collect the distinct resource values on those record operations. An operation such as customers.ListCompanies declares resource: "core:Company".
  3. Pass the exact selected values as resource_types to Prepare webhook, then open the returned approval_url on your Brigg application origin. An administrator reviews the destination, event and data access before the subscription is created.
{
  "url": "https://example.com/webhooks/brigg",
  "event": "resource.updated",
  "resource_types": ["core:Company"]
}

The key needs both webhooks.PrepareWebhook and read access to each selected type. If a needed resource is missing from discovery, review the key's permissions with an administrator. Private records and unpublished types cannot be subscribed to. App-specific types depend on the apps released in your workspace, so there is no universal static enum.

resource.created, resource.updated and resource.deleted require at least one resource type. For legacy meeting.completed, omit resource_types: that event uses its existing approval and payload contract. New types are never subscribed automatically.

Creating a webhook remains a human approval step in Settings. CreateWebhook is not an HTTP operation; the API prepares a proposal and can inspect or replay an already approved stream.

Find the approved subscription

After the administrator approves a proposal, call List webhook subscriptions. Your key needs that operation and read access to every resource type on the subscription. The response includes webhook_id, event, selected types, enabled state and delivery timestamps. It does not reveal the destination or signing secret.

Use webhook_id with the event, delivery and replay operations. An administrator supplies the signing secret to the receiving service through a secure channel. Subscriptions outside the key's current permissions are absent from the list; removing a permission also removes access to their delivery history.

Coverage

Resource events cover committed changes to published shared records, including API calls, imports, enrichment and background updates. Events capture the database change in the same transaction; rolled-back writes, unchanged values, drafts, private records, project records and internal member profiles do not produce resource notifications. changed_fields uses the same published names as the record API. The curated meeting.completed notification remains supported independently.

Treat notifications as prompts to read the current record. Reconcile periodically to recover from receiver downtime, changes made before your subscription existed, or periods when it was disabled.

Process notifications

Verify the signature against the exact raw request bytes before parsing JSON. Deduplicate using the stable event identifier, persist or queue the event, and respond with a successful status promptly. Your endpoint must respond within 10 seconds; redirects are not followed.

Notifications may arrive more than once or out of order. Use the resource identifier and version where provided, and retrieve current data through an API credential with the required access. Deletion notifications identify the deleted resource without requiring it to remain readable through the record API.

Verify signatures

Resource event deliveries use these headers:

Header Value
X-Webhook-Signature v1= followed by the hexadecimal HMAC-SHA256 signature
X-Webhook-Timestamp Unix time in seconds for this delivery attempt
X-Webhook-Event-Id Stable event identifier; use it for deduplication
X-Webhook-Delivery-Id Delivery identifier for diagnostics

The JSON body contains the event name. Sign the timestamp, a period, and the exact raw body bytes: HMAC-SHA256(secret, timestamp + "." + rawBody). Check that the timestamp is within five minutes of your receiver's clock. Each retry has a fresh timestamp and signature; the event identity and payload remain unchanged.

This Node.js example verifies a resource event before JSON parsing. Pass the raw request body as a Buffer and the incoming HTTP headers:

import { createHmac, timingSafeEqual } from "node:crypto";

export function verifyBriggWebhook(rawBody, headers, secret, now = Date.now()) {
  const timestamp = headers["x-webhook-timestamp"];
  const signature = headers["x-webhook-signature"];
  if (typeof timestamp !== "string" || !/^\d+$/.test(timestamp)) return false;
  if (typeof signature !== "string" || !/^v1=[0-9a-f]{64}$/.test(signature)) return false;
  if (Math.abs(now / 1000 - Number(timestamp)) > 300) return false;

  const expected = createHmac("sha256", secret)
    .update(timestamp + ".")
    .update(rawBody)
    .digest();
  const received = Buffer.from(signature.slice(3), "hex");
  return timingSafeEqual(expected, received);
}

The existing meeting.completed contract uses its original hexadecimal HMAC-SHA256 signature over the raw body, without the v1= prefix or timestamp input. Keep that verifier for legacy subscriptions. Moving to a new signing contract requires an explicit configuration change.

Treat signing secrets as server credentials. Compare signatures in constant time, reject invalid signatures, and enforce the documented timestamp tolerance for timestamped signatures. Never verify a reserialized JSON object: whitespace and field ordering affect the signed bytes.

Recover deliveries

Failed deliveries have up to eight attempts across approximately 24 hours. After the first attempt, the nominal retry times are 30 seconds, 2 minutes 30 seconds, 10 minutes 30 seconds, 30 minutes, 2 hours, 8 hours and 24 hours. Brigg respects longer Retry-After values on 429 and 503 responses. Retries keep the same event and delivery identifiers.

Ten consecutive deliveries that exhaust this retry window disable a subscription. An active workspace owner or administrator receives a notice in their Brigg conversation. A late failure cannot override a more recent successful attempt. Repair and test the endpoint in Settings, then enable it again; this clears the failure count. While disabled, it receives no new events. Replay retained failures and reconcile records changed during the gap.

Inspect delivery outcomes and attempts through the webhook operations. Replay an eligible failed event after repairing your endpoint. Replays can cause effects in your receiving system, so apply the same deduplication rules.

Keep the endpoint's delivery identifiers and error details in your logs. Resource delivery history and replay availability are retained for 30 days. Delivery attempts are limited to 600 per workspace per minute and 60 per subscription per minute. Revoked access is not restored by replaying a delivery.

Search by operation name or what you want to build.

Use arrow keys to browse. Enter opens a result.