Webhooks

Create a webhook

Register an endpoint and subscribe it to one or more event types. The response carries secret — the signing key, in plaintext. This is the only time it is returned. Store it where your receiver can read it; if you lose it, rotate rather than re-create, so the endpoint keeps its delivery history. Send secret yourself to sign with a key your receiver already holds; the response then returns that one. A project holds at most 20 webhooks, inactive ones included; the 21st is refused with 409 webhook_limit_reached. Returns 501 on a deployment with no credential-sealing key configured, since the secret could not then be stored safely.

post/v1/projects/{project_id}/webhooks

Request

  • Base URL: https://api.naturali.ai
  • URL: https://api.naturali.ai/v1/projects/{project_id}/webhooks
  • Auth: one of:
    • HTTP bearer
    • OAuth 2 (authorization code, authorization URL https://api.naturali.ai/authorize, token URL https://api.naturali.ai/token, scopes: mcp:access)

Request body

urlstring uri required

An https:// endpoint (http:// is accepted for localhost, so a tunnel works in development).

eventsstring[] required

Which events this endpoint receives. Each entry is an exact type (generation.completed), a resource wildcard (generation.*), or * for everything. A bare resource name (generation) matches nothing and is rejected.

descriptionstring nullable
activeboolean
secretstring

A signing key of your choosing, 32 to 256 characters with no whitespace. Omit it on create to have one generated.

Example request

{
  "url": "https://example.com/hooks/naturali",
  "events": [
    "generation.*",
    "message.received"
  ],
  "description": "billing service",
  "active": true,
  "secret": "my-receiver-signing-key-0123456789ab"
}

Response

Webhook created. The signing secret is included, once.

idstring required

Public webhook ID (whk_ prefix).

project_idstring required
urlstring uri required

Where deliveries are POSTed.

eventsstring[] required

Which events this endpoint receives. Each entry is an exact type (generation.completed), a resource wildcard (generation.*), or * for everything. A bare resource name (generation) matches nothing and is rejected.

descriptionstring nullable required

Operator-facing label.

activeboolean required

Whether deliveries are attempted.

created_atstring date-time required
updated_atstring date-time required
secretstring required

The signing key, returned only by create and rotate. A generated one carries the whsec_ prefix; a chosen one is returned as sent. Never readable afterwards.

Example response

{
  "id": "whk_V1StGXR8Z5jdHi6B",
  "project_id": "proj_V1StGXR8Z5jdHi6B",
  "url": "https://example.com/hooks/naturali",
  "events": [
    "generation.*",
    "message.received"
  ],
  "description": "billing service",
  "active": true,
  "created_at": "2026-07-31T00:00:00.000Z",
  "updated_at": "2026-07-31T00:00:00.000Z",
  "secret": "whsec_V1StGXR8Z5jdHi6BQe4kL2mN"
}

Changes

No recorded changes to this operation across all 1 revision of this API.