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

# Webhooks overview

> Receive real-time notifications when database events occur

Subscribe to database events and receive an HTTP POST at your URL instead of polling. To create a subscription, see [Create Webhook](/api/webhooks/create-webhook).

## Event types

| Event | Fires when |
| - | - |
| `record.created` | A record is added to a table |
| `record.updated` | An existing record is modified |
| `record.deleted` | A record is deleted |
| `table.created` | A table is added |
| `table.updated` | A table's properties (e.g. name) change |
| `table.deleted` | A table is deleted |
| `field.created` | A field is added to a table |
| `field.updated` | A field's properties or configuration change |
| `field.deleted` | A field is removed |

## Payload

Each delivery is a JSON POST body:

```json theme={"system"}
{
  "id": "evt_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "type": "record.created",
  "timestamp": "2025-01-15T10:30:00.000Z",
  "data": {
    "tableId": "tbl_abc123",
    "recordIds": ["rec_xyz789"],
    "records": [
      { "id": "rec_xyz789", "data": { "Name": "John Doe", "Email": "john@example.com" } }
    ]
  },
  "metadata": {
    "webhookId": 123,
    "organizationId": 456,
    "baseId": "base_def456",
    "attempt": 1,
    "source": "ui"
  }
}
```

| Field | Type | Description |
| - | - | - |
| `id` | string | Unique event ID, use it for idempotency |
| `type` | string | Event type (e.g. `record.created`) |
| `timestamp` | string | ISO 8601 time the event occurred |
| `data` | object | Event-specific data (see below) |
| `metadata.webhookId` | number | ID of the webhook subscription |
| `metadata.organizationId` | number | Your organization ID |
| `metadata.baseId` | string | The database ID |
| `metadata.attempt` | number | Delivery attempt (1 = first) |
| `metadata.source` | string | Origin: `ui`, `public_api`, `zapier`, `make`, `import` |

The `data` object varies by event family:

| Event family | `data` fields | Also present on `*.updated` |
| - | - | - |
| Record | `tableId`, `recordIds`, `records[]` | `previousRecords[]` |
| Table | `tableId`, `table` `{ id, name, order, primaryFieldId }` | `previousTable` |
| Field | `tableId`, `fieldId`, `field` `{ id, name, type, order }` | `previousField` |

## Request headers

| Header | Value |
| - | - |
| `Content-Type` | `application/json` |
| `X-Webhook-Signature` | HMAC-SHA256 signature of the payload |
| `X-Webhook-Event` | The event type |
| `X-Webhook-ID` | The unique event ID |
| `User-Agent` | `Zite-Webhooks/1.0` |

## Verifying signatures

Every request carries an `X-Webhook-Signature` header: an HMAC-SHA256 of the payload keyed with your webhook secret (returned once on [creation](/api/webhooks/create-webhook)). Verify it before processing:

```javascript theme={"system"}
const crypto = require('crypto');

function verifyWebhookSignature(payload, signature, secret) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(JSON.stringify(payload))
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// In your webhook handler
app.post('/webhooks/zite', (req, res) => {
  const signature = req.headers['x-webhook-signature'];
  if (!verifyWebhookSignature(req.body, signature, YOUR_WEBHOOK_SECRET)) {
    return res.status(401).send('Invalid signature');
  }
  res.status(200).send('OK'); // then process asynchronously
});
```

## Delivery, retries & limits

* Return a **2xx within 30 s** to acknowledge; process asynchronously if needed. Use HTTPS.
* Non-2xx or timeout is retried up to **5 times** with exponential backoff: 5s, 10s, 20s, 40s, 80s.
* Deduplicate on the event `id`, because retries reuse it.

| Limit | Value |
| - | - |
| Max webhooks per database | 100 |
| Max events per webhook | 20 |
| Max URL length | 2,048 characters |
| Max payload size | 256 KB |
| Delivery timeout | 30 seconds |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.