Events
Set Webhook
Creates or updates a webhook (up to 3 enabled per instance) with event filtering, base64 media and its own Authorization header
POST
Set Webhook
Auth:
Envelope:
TokenAccount or TokenInstance • Rate limit: Global (100/min) • Idempotent: yes (upsert by label)
Description
Creates or updates the(instance, label) row in webhook_configs. Each instance accepts up to 3 simultaneously enabled webhooks, identified by a free-form label. Webhooks with enabled=false are kept in the database but do not count toward the limit and do not receive deliveries.
Use cases:
- Create a new webhook: send a
labelnot used yet. - Update existing: send the same
label, all new fields overwrite the old ones. - Soft-disable: send the same
labelwith{"enabled": false}(clearsurl,authorization,events,mediaBase64, but preserves the row). - Parallel migration: run the old webhook while validating the new one under a different
label; once confirmed, disable the old one.
Examples
Minimum
Enables thedefault webhook pointing to https://meuapp.com/webhook. Without events, it receives the 6 types; without authorization, it sends no auth header.
With label, filter and Authorization
Creates a webhook namedanalytics-pipeline that only receives message.exchange and message.status, sends the header Authorization: Bearer svc-token-xyz on each delivery, and turns off the base64 backup.
byEvents = true (URL-based routing)
Turns onbyEvents: true so each delivery is sent with the event name as a URL suffix (e.g., https://meuapp.com/wh/message.exchange), allowing server-side routing per endpoint without inspecting the payload.
Soft-disable preserving the label
Disables theanalytics-pipeline webhook by sending only enabled: false. The row stays in the database but url, authorization, events and mediaBase64 are cleared, and the entry no longer counts toward the limit of 3 active webhooks.
Base64 media (raw backup)
Configures a webhook dedicated to backup that only receivesmessage.exchange with mediaBase64: true, so each message with media includes the binary content base64-encoded inside the payload.
Success response
The response returns thewebhook object with the configuration actually persisted (label, enabled, url, authorization, byEvents, events, mediaBase64), mirrors the request body after the upsert. When enabled=false, the url, authorization, events and mediaBase64 fields come back cleared. The dispatcher starts using the new config immediately (the internal 30s cache is invalidated on save).
200 OK
Path parameters
Instance name (e.g.,
$Instance_Name).Headers
TokenAccount or TokenInstance.application/jsonRequest body
Local identifier. Max 50 chars; accepts
[a-zA-Z0-9_-]. Empty or omitted becomes "default". Allows multiple webhooks per instance.Turns the webhook on/off. When
false, the url, authorization, byEvents, events and mediaBase64 fields are cleared before saving.Destination URL. Required when
enabled=true. Goes through the SSRF guard (see below), blocks localhost, private IPs, link-local, multicast.Literal content of the
Authorization header sent on each delivery (e.g., Bearer secret-key-123). Encrypted at rest with AES-256-GCM when ENCRYPTION_KEY is configured.If
true, the URL receives the /<event-name> suffix on each delivery, useful for endpoint-based routing without inspecting the payload (https://app/wh/message.exchange).Filter. Empty array = receive all 6 types. Each entry must be in
{message.exchange, message.status, call.update, group.flow, instance.state, label.update}.When
true, message.exchange events with media include media.base64 (increases payload, may exceed 100KB).SSRF guard
Theurl is validated at configuration time and before each delivery. It blocks destinations that point to internal infrastructure:
| Range | Example |
|---|---|
| Loopback | localhost, 127.0.0.1, ::1 |
| Private IPv4 | 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
| Link-local IPv4 | 169.254.0.0/16 |
| Link-local IPv6 | fe80::/10 |
| Multicast / broadcast | 224.0.0.0/4, 255.255.255.255 |
Notes
- Empty
authorizationvs.null: sendnullor omit it to skip the header. An empty string""would result in an emptyAuthorization:header, which some proxies reject. enabled=falseclears the fields: re-enabling the samelabellater requires re-sending theurl(and any other fields you want to preserve).- There is no
DELETE: to “remove” a webhook,POSTwith{"enabled": false}keeping thelabel. Operators can inspect/clean the row directly in the database when needed. - Optional encryption: if
ENCRYPTION_KEYis not configured,authorizationis stored in plain text. In production, always configure the key. - Cache invalidated: the new config becomes visible to the dispatcher immediately (the internal 30s TTL is invalidated on save).
Errors
| HTTP | error.message |
|---|---|
| 400 | Invalid request body |
| 400 | URL is required when enabled is true |
| 400 | URL must not target localhost or private network |
| 400 | invalid event type: <value> |
| 400 | label too long (max 50 chars) |
| 400 | label may only contain letters, digits, underscore or dash |
| 401 | Invalid token |
| 404 | Instance not found |
| 409 | webhook limit reached (max 3 enabled per instance) |
| 429 | Rate limit exceeded. Try again later. |
| 500 | Failed to get instance |
The 3-webhook limit check is only enforced when creating a new row with
enabled=true. Editing an existing row (same label) never triggers the limit.Next
List webhooks
GET /api/events/getWebhook/:instance, all or by ?label=.Event catalog
What each
event carries in data.