Skip to main content

Webhooks

Register HTTPS endpoints to receive events. Manage them with POST/GET /v1/webhooks, PATCH/DELETE /v1/webhooks/{id}, inspect GET /v1/webhooks/{id}/deliveries, and re-fire with POST /v1/webhooks/{id}/deliveries/{delivery_id}/replay.

Payload & signature​

Each delivery is POSTed as JSON { "event", "timestamp", "data" } with headers:

HeaderMeaning
X-Wapower-Eventthe event type
X-Wapower-Delivery-Idunique per delivery — dedupe on this (at-least-once)
X-Wapower-SignatureHMAC-SHA256 of the exact request body, keyed by your endpoint secret

Verify the signature by recomputing HMAC-SHA256 over the raw body with your secret and comparing in constant time. Failed deliveries retry with backoff until max_attempts.

Events​

Outbound / protection (existing): message.sent, message.blocked_by_protection, session.status, session.banned, session.warmup.disabled, warmup.stage.advanced, protection.state.changed, session.risk.alert.

Inbound / real-time: message.received, message.delivered, message.read, message.reaction, call.received, session.qr, group.participants.update, group.update. session.status also fires on spontaneous connection changes detected by the engine (disconnect/ban/reconnect), not only on API calls.

Subscribe to specific types or *.

Inbound payloads​

  • message.received — data: session_id, message_id, from, push_name, type, from_me, is_group, timestamp plus text?, media?{url,mime,size,sha256,file_name?,caption?}, location?, contact?, quoted_message_id?. Incoming media is re-hosted; media.url is a time-limited link. If a media download failed, media is { "error": "download_failed" }.
  • message.delivered / message.read — data: session_id, message_id, internal_id, to, timestamp. internal_id is the id returned when you sent the message via the API (null if it wasn't sent through us).
  • message.reaction — data: session_id, message_id, from, emoji, timestamp (emoji: "" means the reaction was removed).
  • call.received — data: session_id, call_id, from, is_video, status:"offer", timestamp.
  • session.qr — data: session_id, qr, timestamp.
  • group.participants.update — data: session_id, group_id, participants:[jid], action:"add"|"remove"|"promote"|"demote", timestamp.
  • group.update — data: session_id, group_id, changes:{subject?,description?}, timestamp.
  • message.received for a group message additionally has is_group:true and group_id; from is the participant who sent it (not the group jid).