See Agility CMS in action. Watch a product demo
Webhooks
Webhooks let external systems react to activity in an Agility instance — content being published, content being saved, and content moving through workflow. Instead of polling the API, you register a URL that Agility calls when those events happen. The Management SDK exposes webhookMethods so you can list, inspect, create, and remove those registrations programmatically.
JavaScript / TypeScript SDK only. Webhook management is currently available in the JavaScript/TypeScript Management SDK only — the .NET SDK does not include webhook methods. If you are working in .NET, manage webhooks in the Agility UI or call the Management API directly.
Secure delivery, retries and delivery history require
@agility/management-sdk0.1.40 or later.
All of the methods below take the instance guid as their first argument and are available on apiClient.webhookMethods.
List webhooks
Returns the webhooks registered for the instance. Results are paged.
//list the webhooks for the instance
const webhooks = await apiClient.webhookMethods.webhookList(guid);
console.log("Webhooks for Instance:");
console.log(webhooks);
webhookList(guid, take = 20, token = null) — pass the token from the previous result to fetch the next page.
Signing secrets are never returned by
webhookList. UsegetWebhookto read one, and see the permission note below.
Get a webhook
Retrieves a single webhook by its id.
//get a specific webhook
const webhook = await apiClient.webhookMethods.getWebhook(guid, webhooks[0].id);
console.log("Webhook Details:");
console.log(webhook);
Reading a signing secret requires Full Control. For callers with a lower permission level the secret is masked. The webhook itself is still returned and fully manageable.
Save (create) a webhook
Pass the instance guid and a webhook object. The saved webhook is returned, including its id.
//create a new webhook
const newWebhook = await apiClient.webhookMethods.saveWebhook(guid, {
name: "My New Webhook",
url: "https://example.com/webhook",
contentPublishEvents: true,
contentSaveEvents: true,
contentWorkflowEvents: true,
enabled: true,
instanceGuid: guid,
});
saveWebhook payload
| Field | Type | Description |
|---|---|---|
name | string | Display name for the webhook. |
url | string | The endpoint Agility calls when a subscribed event fires. |
contentPublishEvents | boolean | Subscribe to content publish events. |
contentSaveEvents | boolean | Subscribe to content save events. |
contentWorkflowEvents | boolean | Subscribe to content workflow events. |
enabled | boolean | Whether the webhook is active. |
instanceGuid | string | The GUID of the instance the webhook belongs to. |
secureDeliveryEnabled | boolean | Sign every delivery so your endpoint can verify it. Defaults to false. See Verifying Signed Webhooks. |
retriesEnabled | boolean | Retry a failed delivery. Defaults to false. |
retryCount | number | How many attempts, 1–8. Defaults to 3. Only used when retriesEnabled is true. |
retrySpeed | "fast" | "standard" | "slow" | Base interval between attempts — 30 seconds, 5 minutes or 30 minutes, growing exponentially with jitter. |
The server controls the signing secret. Any signingSecret you send is ignored.
Turning on secure delivery
Set secureDeliveryEnabled and save. Agility mints the secret and returns it on that response only, with signingSecretJustCreated: true — store it then, because a later getWebhook will not repeat it as a new value.
//enable secure delivery and capture the minted secret
const saved = await apiClient.webhookMethods.saveWebhook(guid, {
...webhook,
secureDeliveryEnabled: true,
});
if (saved.signingSecretJustCreated) {
console.log("Store this secret:", saved.signingSecret); // whsec_...
}
Get delivery history
Returns delivery attempts for a webhook, newest first. Defaults to the last 7 days; the range cannot exceed 366 days and take maxes out at 100. History is retained for 90 days.
//read the recent delivery history for a webhook
const history = await apiClient.webhookMethods.getWebhookHistory(guid, webhookID, {
take: 50,
});
for (const attempt of history.items) {
console.log(attempt.sendDate, attempt.httpResponseCode, attempt.success);
}
//fetch the next page
if (history.token) {
const next = await apiClient.webhookMethods.getWebhookHistory(guid, webhookID, {
take: 50,
token: history.token,
});
}
getWebhookHistory(guid, webhookID, options?) accepts fromDate, toDate, take and token, and returns a TokenPagedResult<WebhookHistory> — items plus a token for the next page.
Useful fields on each entry:
| Field | Description |
|---|---|
sendDate | When the delivery succeeded. Empty while a delivery is still being retried. |
success | Whether the attempt succeeded. |
httpResponseCode / responseText | What your endpoint returned. Response text is truncated. |
attemptCount | Attempts made so far. |
nextAttemptUtc | When the next retry is scheduled, if there is one. |
lastError | The failure reason for the most recent attempt. |
signed | Whether the last attempt carried signature headers. null means it has not been attempted yet. |
payload | The body that was sent. |
Delivery history is go-forward only. Deliveries from before this feature shipped are not returned, so a webhook you created earlier will show an empty history until it fires again.
Roll a signing secret
Generates a new signing secret immediately and returns it.
//roll the signing secret for a webhook
const rolled = await apiClient.webhookMethods.rotateWebhookSecret(guid, webhookID);
console.log("New secret:", rolled.signingSecret);
For 24 hours afterwards Agility signs each delivery with both the new and the previous secret, sending two space-separated signatures. That gives you a window to deploy the new secret without dropping deliveries. Verification code that accepts any matching signature in the header needs no change at all.
Rolling a secret requires Full Control.
Delete a webhook
Removes a webhook by its id.
//delete a webhook
await apiClient.webhookMethods.deleteWebhook(guid, newWebhook.id);
Deleting a webhook also removes its delivery history.