Skip to main content

Webhooks (api/webhook)

A webhook subscription tells Agility to send an HTTP request to a URL you control whenever something you care about happens. It is the push alternative to polling query.v1 on a timer.

Subscriptions can be as broad or as narrow as you like: every Story status change in the instance, or only status changes on Stories in one project that are owned by one person.

How It Fits Together​

A subscription has two halves:

  1. Where to deliver — the url, an optional authorizationHeader, an optional secret for payload signing, and a webhookId you choose to identify it.
  2. What to deliver — an eventTypes array. Each entry describes a class of change using the same vocabulary as a query: from, attributes, filter, with, userContext and select.

When a matching change happens, Agility POSTs a JSON body describing the event — who did it, what changed, and a projection of the asset shaped by your select.

Operations​

OperationEndpoint
Create a subscriptionPOST ~/api/webhook
Query subscriptionsGET ~/api/webhook
Update a subscriptionPOST ~/api/webhook/:id
Delete a subscriptionPOST ~/api/webhook/delete/:id
Check delivery statusGET ~/api/webhook/status/:id

Supporting reference:

  • Event types — how to describe what you want to be notified about
  • Webhook payload — what arrives at your endpoint, and how to verify it
warning
These are POST endpoints, including delete

There is no PUT, PATCH or DELETE verb anywhere in this API. Update is a POST to the subscription URL, and delete is a POST to .../api/webhook/delete/:id — the id is in the path after the word delete. This is unusual, it is deliberate, and sending DELETE ~/api/webhook/:id will get you a 405. See delete.

Permissions​

Every endpoint in this API requires the ManageConfig privilege — the same administrative privilege that governs instance configuration. Webhook subscriptions are an instance-level integration surface, not a per-user one.

Instance Limits and Configuration​

LimitDefaultEffect
Maximum enabled subscriptionsunlimitedCreating past the limit fails.
Delivery retry attempts5Attempts per delivery — see retries and automatic disabling.

These are instance configuration, adjustable by an administrator on on-premise installations.

The "limit of 5 subscriptions" is out of date

The original reference stated that "in the first release of webhook subscriptions, your instance can have up to 5 enabled webhook subscriptions at a time". That restriction has since been lifted: MaxActiveSubscriptions now defaults to unlimited and the cap only applies where an administrator has explicitly configured one.

If you do hit a configured cap, creation fails with a message naming the limit. Check the setting rather than assuming the number is 5. The unrelated 5 that is still real is the retry count.

Webhooks can also be disabled instance-wide. When they are, every endpoint in this section returns 404 rather than an explanatory error — a blanket 404 from a correctly-formed request usually means the feature is switched off, not that your subscription is missing.

Delivery Semantics​

Understand these before you build against webhooks:

  • Non-200 means failure. Responding with anything other than 200 OK counts as a failed delivery. Return 200 as soon as you have durably accepted the payload; do your processing afterwards.
  • Repeated failure eventually disables the subscription — through the retry and probation model below. If a webhook has "stopped working", check its retryCount and its delivery receipts first.
  • Order is not guaranteed. Events may arrive out of order. Every event carries a sequenceId so you can reorder them yourself. Do not infer ordering from arrival time.
  • Delivery is at-least-once in effect. A retry after a response you actually processed will redeliver the event. Make your handler idempotent, keyed on webhookId plus sequenceId.
  • Your endpoint must be reachable from the Agility instance. For cloud-hosted instances that means publicly routable, or reachable through whatever egress path your instance is configured with.

Retries and Automatic Disabling​

Two separate mechanisms, often conflated:

Retries happen per delivery. Each delivery is attempted up to 5 times (default), with exponential backoff starting at 5 seconds — so the gaps run 5, 10, 20, 40, 80 seconds. A successful delivery resets the retry count to zero.

Disabling happens on probation. When a delivery exhausts its retries:

  1. The first exhausted delivery puts the subscription on probation (default 12 hours) and sends a failure-warning email to the owner.
  2. A successful delivery during probation clears it — with a recovery email. Nothing was lost but the failed deliveries themselves.
  3. A delivery that exhausts its retries after the probation window has elapsed — meaning the endpoint has been failing for the whole window — disables the subscription, with a final notification email.

A disabled subscription stops producing receipts; fix the receiver, then re-enable via update. The retry count, backoff quantum and probation length are configurable on on-premise instances — ask your administrator if your instance behaves differently from the defaults above.