# Webhooks

Endpoints that receive notifications of an organization's events

Base URL: `https://api.cv-transformer.com/v1`. Endpoints: `GET /webhooks`, `POST /webhooks`, `DELETE /webhooks`, `PATCH /webhooks`. Authenticate with the header `Authorization: Bearer YOUR_API_KEY` (see [authentication](https://www.cv-transformer.com/zh/api-reference/authentication.md)).

## The webhook object

| Attribute | Type | Description |
| --- | --- | --- |
| `id` | `uuid` | Unique identifier. |
| `grant_id` | `uuid \| null` | Identifier of the OAuth grant that created the webhook. Revoking the grant, or its access to the organization, disables the webhook. References [`oauth_grants.id`](https://www.cv-transformer.com/zh/api-reference/oauth_grants.md). |
| `organization_id` | `uuid` | Identifier of the related organization. References [`organizations.id`](https://www.cv-transformer.com/zh/api-reference/organizations.md). |
| `created_at` | `timestamp with time zone` | Creation timestamp. |
| `updated_at` | `timestamp with time zone` | Last modification timestamp. |
| `description` | `text` | Description of the webhook, if any. |
| `disabled_at` | `timestamp with time zone \| null` | When the webhook was disabled, because its endpoint kept failing or the OAuth grant that created it lost access. A disabled webhook gets no notifications; set this to null to enable it again. |
| `endpoint` | `text` | URL notifications are sent to. |
| `events` | `Array<WebhookEvent>` | Events to which the webhook is subscribed. |
| `signing_secret` | `text` | Secret used to sign each notification sent to the webhook. Verify notifications with the Standard Webhooks headers (webhook-id, webhook-timestamp, webhook-signature: HMAC-SHA256 with this secret as key). The X-Signature header (MD5) is deprecated and will be removed in the future. Read-only. |
| `source` | `text` | Where the webhook was registered: the admin, the API or an external tool such as Zapier. |

```json
{
  "id": "00000000-0000-0000-0000-000000000000",
  "grant_id": "00000000-0000-0000-0000-000000000000",
  "organization_id": "00000000-0000-0000-0000-000000000000",
  "created_at": "2026-01-01T12:00:00+00:00",
  "updated_at": "2026-01-01T12:00:00+00:00",
  "description": "",
  "disabled_at": null,
  "endpoint": "",
  "events": [
    "candidates.created",
    "members.updated"
  ],
  "signing_secret": "",
  "source": ""
}
```

### Types

```typescript
type WebhookEvent = 
  | "candidates.created"
  | "candidates.updated"
  | "layouts.created"
  | "layouts.updated"
  | "members.created"
  | "members.updated";
```

### Related resources

Embed related resources with the [`select` parameter](https://www.cv-transformer.com/zh/api-reference/selecting.md), for example `select=*,organizations(*)`. Resources related through more than one column need the column as a hint, like `table!column(*)`.

| Embed | Type | Description |
| --- | --- | --- |
| `organizations(*)` | `object \| null` | The [organization](https://www.cv-transformer.com/zh/api-reference/organizations.md) referenced by `organization_id`. |
| `webhook_notifications(*)` | `array` | The [webhook notifications](https://www.cv-transformer.com/zh/api-reference/webhook_notifications.md) referencing this webhook through `webhook_notifications.webhook_id`. |

## List webhooks

`GET /v1/webhooks` · requires the `webhooks:read` scope

Filter on any attribute with `column=operator.value` (see [filtering](https://www.cv-transformer.com/zh/api-reference/filtering.md)). Choose columns and embed related resources with `select` (see [selecting](https://www.cv-transformer.com/zh/api-reference/selecting.md)), and sort and paginate with `order`, `limit` and `offset` (see [sorting and pagination](https://www.cv-transformer.com/zh/api-reference/sorting-pagination.md)).

```bash
curl "https://api.cv-transformer.com/v1/webhooks?limit=10&select=*" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Responses:

- `200`: A list of webhooks with the selected columns. The `Content-Range` header holds the range returned and the total count, like `0-9/42`.
- `206`: Partial Content
- `400`: The request is malformed, for example an unknown column or an invalid filter.
- `401`: The API key is missing or invalid.
- `403`: The API key doesn't have the scope this request needs.
- `429`: The API key made more requests per minute than its rate limit allows. Retry after the number of seconds in the `Retry-After` header.

## Create webhooks

`POST /v1/webhooks` · requires the `webhooks:write` scope

Insert one webhook or an array of webhooks. The body is a `Partial` webhook object, so columns with a default can be left out. Read-only attributes can't be written.

```bash
curl "https://api.cv-transformer.com/v1/webhooks" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "organization_id": "00000000-0000-0000-0000-000000000000",
    "description": "",
    "endpoint": "",
    "events": ["candidates.created", "members.updated"],
    "source": ""
  }'
```

Responses:

- `201`: Created. With the header `Prefer: return=representation`, the body holds the created webhooks with the selected columns.
- `400`: The request is malformed, for example an unknown column, an invalid filter or an invalid body.
- `401`: The API key is missing or invalid.
- `403`: The API key doesn't have the scope this request needs, or no permission for this change, for example when writing rows of another organization.
- `409`: The change conflicts with existing data, for example a duplicate key or a reference to a row that does not exist.
- `429`: The API key made more requests per minute than its rate limit allows. Retry after the number of seconds in the `Retry-After` header.

## Delete webhooks

`DELETE /v1/webhooks` · requires the `webhooks:write` scope

Filter on any attribute with `column=operator.value` (see [filtering](https://www.cv-transformer.com/zh/api-reference/filtering.md)). Without filters, this request deletes all webhooks the API key has access to. Always filter on at least one column, like `id=eq.{id}`.

```bash
curl -X DELETE "https://api.cv-transformer.com/v1/webhooks?id=eq.00000000-0000-0000-0000-000000000000" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Responses:

- `204`: Deleted. With the header `Prefer: return=representation`, the response is a `200` whose body holds the deleted webhooks with the selected columns.
- `400`: The request is malformed, for example an unknown column or an invalid filter.
- `401`: The API key is missing or invalid.
- `403`: The API key doesn't have the scope this request needs, or no permission for this change, for example when writing rows of another organization.
- `429`: The API key made more requests per minute than its rate limit allows. Retry after the number of seconds in the `Retry-After` header.

## Update webhooks

`PATCH /v1/webhooks` · requires the `webhooks:write` scope

Filter on any attribute with `column=operator.value` (see [filtering](https://www.cv-transformer.com/zh/api-reference/filtering.md)). Without filters, this request updates all webhooks the API key has access to. Always filter on at least one column, like `id=eq.{id}`. The body holds the attributes to change.

```bash
curl -X PATCH "https://api.cv-transformer.com/v1/webhooks?id=eq.00000000-0000-0000-0000-000000000000" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "description": "" }'
```

Responses:

- `204`: Updated. With the header `Prefer: return=representation`, the response is a `200` whose body holds the updated webhooks with the selected columns.
- `400`: The request is malformed, for example an unknown column, an invalid filter or an invalid body.
- `401`: The API key is missing or invalid.
- `403`: The API key doesn't have the scope this request needs, or no permission for this change, for example when writing rows of another organization.
- `409`: The change conflicts with existing data, for example a duplicate key or a reference to a row that does not exist.
- `429`: The API key made more requests per minute than its rate limit allows. Retry after the number of seconds in the `Retry-After` header.

Errors have a JSON body with a `message`, `details` and `hint`, and for database errors a `code`. See the [introduction](https://www.cv-transformer.com/zh/api-reference.md) for more on errors. The full API is described by the OpenAPI spec at https://api.cv-transformer.com/v1/openapi.json.
