Skip to content

Device webhooks — configure, rotate, delete

Manages where a rented number’s WhatsApp events are delivered. All four methods need the webhook scope and an active/past_due rental for the device.

{
"ok": true,
"webhook": { "id": "rwh_…", "deviceId": "gwd_…", "url": "https://…",
"events": ["message"], "active": true, "createdAt": "…", "updatedAt": "…" },
"availableEvents": ["message", "message.reaction", "message.revoked", "message.edited", "message.ack",
"message.deleted", "chat_presence", "group.participants", "group.joined",
"label.edit", "label.association", "newsletter.joined", "newsletter.left",
"newsletter.message", "newsletter.mute", "call.offer"],
"gatewayWired": true
}

webhook is null when nothing is configured. gatewayWired reports whether the gateway has been confirmed wired to MauKirim — if it is false, events are not flowing yet and that is not your endpoint’s fault. The signing secret is never returned by a read.

The destination belongs to the current lease, not just the current account. A number rented again — even by the same account — does not carry the previous destination into its settings: a read returns null, and the first POST deletes the previous destination and its deliveries, then issues a fresh signing secret.

For per-chat typing events on a rented number, subscribe to chat_presence alongside any other events you want. See the chat presence webhook example for the signed delivery envelope. To show typing from your rented number, use POST /devices/{id}/chat-presence.

Field Type Required Validation
url string yes Parseable, https, no userinfo, no query, no fragment, not an IP literal and not localhost/*.localhost/*.local
events string[] no Defaults to [], which means all events. Duplicates are removed; unknown names are rejected.
active boolean no Defaults to true on create; on an edit the existing value is kept unless you send one
{ "ok": true, "webhook": { "…": "…" }, "secret": "…64 hex characters…" }

secret appears only when the destination was newly created. Editing an existing destination keeps the secret and returns no secret field — which is why storing the value the first time matters.

No body. Returns the same shape with a new secret. The previous secret stops verifying immediately, so deploy the new one before rotating unless you can tolerate a failed delivery.

404 webhook_not_configured when there is nothing to rotate.

{ "ok": true, "removed": true }

Events stop being forwarded and the destination is removed. The device and its rental are untouched, but the delivery log goes with the destination — its rows are deleted alongside it, so export anything you still need first. 404 webhook_not_configured when nothing was configured.

HTTP Code Condition
400 invalid_input url missing, unparseable, not https, carrying credentials/query/fragment, an IP literal or localhost; events not a list of known names
404 rental_not_found No usable rental for this device and account
404 webhook_not_configured PUT/DELETE with no destination
401/403 auth codes Needs scope webhook
500 server_error Unexpected