Skip to content

System Webhooks

System webhooks deliver event notifications across all tenants to a single subscriber URL. They are the cross-tenant equivalent of the per-tenant Outbound Webhooks feature and are intended for platform-wide automation that does not want to maintain a separate subscription on every tenant.

The most common use case is provisioning automation in front of an SBC or Kamailio router: a single subscriber receives every extension.created, extension.updated, and extension.deleted event from every tenant on the platform, learns the SIP URI to provision, and routes new REGISTERs to the correct PBX worker.

When to use system vs. tenant webhooks

Tenant webhookSystem webhook
ScopeOne tenantAll tenants
Managed byTenant administratorPlatform administrator
Configured underTenant > Integrations > Outbound WebhooksSystem > General Settings > System Webhooks
Available eventsCRM, configuration, communicationsProvisioning + tenant lifecycle (a focused subset)
Tenant lifecycle events (tenant.created/updated/deleted)not delivereddelivered
Per-payload tenant + cluster contextnot addedalways added

A subscription that needs to be aware of new extensions across the platform should use a single system webhook rather than configuring N tenant webhooks.

Available events

The system webhook event picker is intentionally a focused subset of the platform-wide events — the ones that actually affect cross-tenant SIP routing or tenant fan-out. They are presented as a single flat checkbox list:

  • extension.* - created, updated, deleted
  • did.* - created, updated, deleted
  • trunk.* - created, updated, deleted
  • tenant.* - created, updated, deleted (tenant lifecycle)

Wildcards are supported (extension.*, tenant.*, etc.).

Per-tenant call-flow events (queue, hunt group, IVR), admin events, and CRM/communications events (contact, deal, call, voicemail, WhatsApp, SMS) are deliberately not exposed at the system level — they are tenant-internal concerns and would generate cross-tenant noise. Subscribe to them on individual tenants instead via the tenant-level Outbound Webhooks screen.

Payload format

Every system webhook delivery uses the same JSON envelope as tenant webhooks:

{
"event": "extension.created",
"timestamp": 1778756270.42411,
"data": {
"tenant": "ai_verde",
"name": "ai_verde-704108",
"extension": "704108",
"first_name": "Chris",
"last_name": "Edwards",
"phone_username": "704108-ai_verde",
"location": "uk-south",
"primary_server": "worker-uk-south-2"
}
}

The fields specific to system delivery are:

  • tenant - the tenant the event originated in (always present on all system deliveries)
  • phone_username - the SIP peer name in ext-tenant format (extension events only). This is the value the device authenticates with on REGISTER and the value an SBC/Kamailio router should match on.
  • location - the cluster/location tag of the tenant (handy for routing in multi-cluster deployments)
  • primary_server - the worker that hosts the tenant

tenant.* events have a smaller data payload because there is no extension context yet:

{
"event": "tenant.created",
"timestamp": 1778756400.0,
"data": {
"tenant": "ai_verde",
"name": "AI Verde Communications",
"id": 47,
"location": "uk-south",
"primary_server": "worker-uk-south-2"
}
}

The same HTTP headers used for tenant webhooks (X-Webhook-Event, X-Webhook-Timestamp, X-Webhook-Signature) are sent on every system delivery.

Tenant-scoped vs. system-scoped subscribers

Tenant-scoped subscriptions and system-scoped subscriptions are stored in the same table but matched independently. When an event fires for a given tenant, the delivery engine selects:

  • the tenant subscriptions that subscribe to the event AND belong to that tenant, plus
  • the system subscriptions that subscribe to the event (regardless of tenant)

The same event can therefore be delivered to multiple subscribers (one per tenant rule + one per system rule). Each subscriber receives an independent HTTP POST.

Verifying signatures

If a signing secret is configured, every payload is signed with HMAC-SHA256 using timestamp.payload as the message and the secret as the key. Verification is identical to tenant webhooks - see Verifying Signatures on the tenant webhook page for an example.

Testing

Click Test Webhook on the system webhook grid to send a sample webhook.test payload to the configured URL. The test delivery includes "scope": "system" in the data so the receiver can confirm it came from a system-level subscription. The result is recorded in the delivery log.

Trying it without a real receiver

The fastest way to validate end-to-end delivery is to point the URL at a public request inspector and inspect the incoming POST:

  • webhook.site - generates a unique URL on load and shows every incoming request (headers + body) in real time. Paste the URL into the URL field, save, click Test Webhook, switch back to the webhook.site tab.
  • requestbin.com - same idea with a different UI.
  • https://httpbin.org/post - returns 200 and echoes the request back in the response body. Useful when you want a clean “Test delivered: HTTP 200” result without leaving the webhook screen.

Once the test reaches your inspector, repeat the verification with a real event by adding or saving an extension on any tenant - the resulting extension.created or extension.updated payload uses the same delivery path and shows the production fields (tenant, phone_username, location, primary_server).

About redirects (HTTP 301 / 302)

Webhook delivery does not follow HTTP redirects on POST. A 301 or 302 from the receiver is reported as a failed test rather than re-POSTing to the redirect target - silent redirect-following is a security and reliability hazard for webhook receivers. If you see a 301 in the test result, the URL is almost certainly typed with the wrong scheme (http:// vs https://), the wrong trailing slash, or a vanity host that redirects to its canonical form. Run curl -i -X POST '<your-url>' and copy the Location: header into the URL field.

Delivery log

The delivery log behaves the same as the tenant webhook delivery log. Every system delivery is recorded with timestamp, event, HTTP status, payload and response body. Click the Deliveries badge on the row to open the log; click Clear Log inside the log to truncate it.

Permissions

Access to system webhooks is gated on the existing system_preferences permission — the same permission that governs other items under General Settings (Branding, Email Templates, Communication Logs, Services, etc.). It is held by the Global Admin and System Admin roles by default. Tenant administrators do not have system_preferences and therefore do not see the System Webhooks screen.

Tenant administrators continue to manage their own tenant-scoped subscriptions via Outbound Webhooks under tenant settings; the two screens are independent.

REST API

System webhooks are also available via the REST API at /api/system-outbound-webhooks. See the System Webhooks section in the OpenAPI reference for the full schema. The endpoints require an API key whose owning admin holds the system_preferences permission.