Skip to main content
POST
Create a webhook subscription

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json

A subscription is either job-based or app-based, chosen by type. The two kinds carry different filters and cannot be mixed in one subscription.

type
enum<string>
required
Available options:
webhook_subscription_jobs
url
string<uri>
required

The HTTPS endpoint Narrative POSTs each event to. It should return a 2xx quickly; anything else is retried.

job_ids
string<uuid>[] | null

Deliver events only for these jobs. Omit to match any job.

Minimum array length: 1

Unique identifier for the job.

job_types
string[] | null

Deliver events only for jobs of these types. Omit to match any type. Job types are open-ended strings — new ones are added as the platform grows — so this is not validated against a fixed list. Common values include datasets_deliver_data, datasets_sample, datasets_calculate_column_stats, datasets_delete_table, materialize-view, model_training_run, model_inference_run and nql-forecast.

Minimum array length: 1
Maximum string length: 255
states
enum<string>[] | null

Deliver events only when a job enters one of these states. Omit to match any state.

Minimum array length: 1

Where a job is in its lifecycle.

  • pending — enqueued and waiting to be picked up.
  • scheduled — claimed by an executor but not yet started.
  • running — being executed.
  • pending_cancellation — cancellation has been requested and the data plane has yet to stop the work.
  • completed, cancelled, failed — terminal states.
Available options:
pending,
scheduled,
running,
pending_cancellation,
completed,
cancelled,
failed
name
string | null

A label for your own use. Narrative does not interpret it.

Response

The subscription was created.

A webhook subscription. The job_* filters are only set on job subscriptions and app_id only on app subscriptions; the unused ones come back as null rather than being omitted.

id
string<uuid>
required
secret
string<uuid>
required

Sent back on every delivery in the X-Narrative-Secret header. Compare it against this value to confirm a callback came from Narrative.

status
enum<string>
required

Archiving is one-way. The read endpoints only return active subscriptions, so in practice this is always active — an archived subscription responds 404.

Available options:
active,
archived
company_id
integer<int64>
required

The company that owns the subscription.

url
string<uri>
required

The endpoint events are delivered to.

created_at
string
required

An ISO 8601 local date-time with no offset or zone — 2025-04-29T16:12:45.123456. Read it as UTC. This is deliberately not format: date-time, which means RFC 3339 and would require an offset the server does not send. Note that the delivered event envelope uses a different format: its created_at does carry a Z.

Pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$
Example:

"2025-04-29T16:12:45.123456"

updated_at
string
required

An ISO 8601 local date-time with no offset or zone — 2025-04-29T16:12:45.123456. Read it as UTC. This is deliberately not format: date-time, which means RFC 3339 and would require an offset the server does not send. Note that the delivered event envelope uses a different format: its created_at does carry a Z.

Pattern: ^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?$
Example:

"2025-04-29T16:12:45.123456"

app_id
integer<int64> | null

The app this subscription follows. Null on job subscriptions.

name
string | null

The label supplied at creation time. Null if none was given.

job_ids
object | null

The job_ids filter, or null if the subscription does not filter by job.

Example:
job_states
object | null

The states filter, or null if the subscription does not filter by state.

Example:
job_types
object | null

The job_types filter, or null if the subscription does not filter by type.

Example: