Skip to content

Webhooks ​

A webhook is a web address on your server that KiliChat calls whenever something happens, like a customer sending a message. Your system can then react straight away: create a ticket, update an order, notify a salesperson.

Only admins can add webhooks. Each WhatsApp number can have up to 5 webhooks.

How do I add a webhook? ​

  1. Choose the WhatsApp number in the left sidebar, then click API & webhooks.
  2. In the Webhooks card, click Add webhook.
  3. Type the Endpoint URL: a public https:// address on your server, like https://example.com/kilichat-webhook.
  4. Under Send me, tick the events you want.
  5. Click Add webhook.
  6. Copy the signing secret (it starts with whsec_). It's shown once. Your endpoint uses it to check requests really come from KiliChat.
  7. Click I've saved it.

Then click Send test to check your endpoint answers. You'll see "Test delivered (answered 200)" or "Test failed: …".

Which events can I get? ​

EventWhen it's sent
message.receivedA customer sends a message
message.sentA message goes out from your team, a bot, a broadcast, a sequence or the API
message.statusA sent message is delivered, read or fails
contact.createdA new contact is added
contact.opted_outA contact opts out, by keyword, by your team or through the API
contact.opted_inA contact opts back in
pingOnly from Send test

What does a request look like? ​

Each event is a POST with a JSON body:

http
POST /kilichat-webhook HTTP/1.1
Content-Type: application/json
User-Agent: KiliChat-Webhooks/1.0
X-KiliChat-Event: message.received
X-KiliChat-Delivery: 9a7e0d52-…
X-KiliChat-Timestamp: 1762596000
X-KiliChat-Signature: sha256=5f2b…
json
{
  "id": "9a7e0d52-…",
  "event": "message.received",
  "numberId": "…",
  "createdAt": "2026-11-08T10:00:00.000Z",
  "data": {
    "message": {
      "id": "…",
      "conversationId": "…",
      "direction": "in",
      "type": "text",
      "text": "Is the blue saree available?",
      "status": "received",
      "error": null,
      "sentBy": "contact",
      "createdAt": "2026-11-08T10:00:00.000Z"
    },
    "contact": {
      "id": "…",
      "phone": "919876543210",
      "name": "Priya",
      "optedOut": false,
      "attributes": { "city": "Chennai" },
      "lastMessageAt": "2026-11-08T10:00:00.000Z",
      "createdAt": "2026-10-01T09:12:00.000Z"
    }
  }
}
  • Message events (message.received, message.sent, message.status) carry message and contact.
  • Contact events carry contact only.
  • ping carries {"message": "Test from KiliChat"}.

Headers ​

HeaderValue
X-KiliChat-EventThe event name
X-KiliChat-DeliveryA unique id for this delivery, the same as the body's id. Use it to ignore repeats.
X-KiliChat-TimestampWhen it was sent, in Unix seconds
X-KiliChat-Signaturesha256= and the HMAC-SHA256 of <timestamp>.<raw body> with your signing secret. See Verify signatures.

Message fields ​

FieldValues
directionin (from the customer) or out
typetext, template, image, video, audio, document, sticker, location, address, buttons, list, link… Button and list taps arrive as text with the option's title.
textThe text, caption, or for templates the filled-in message
statusreceived for incoming; queued, sent, delivered, read or failed for outgoing
errorMeta's reason when failed, otherwise null
sentBycontact, user (your team), bot, broadcast, system (automatic replies) or api

How should my endpoint answer? ​

  • Answer with any 2xx status within 10 seconds. Do the slow work afterwards, for example in a background job.
  • Check the signature before trusting the request.
  • Use X-KiliChat-Delivery to skip deliveries you've already handled. A retry has the same id.
  • Events can arrive out of order. For example, message.status with read might come before delivered. Go by the status value rather than the order.

Redirects aren't followed, so give the final URL.

Which URLs are allowed? ​

Endpoints must be public https:// addresses. Private, local and link-local addresses (like localhost, 192.168.x.x or 10.x.x.x) are refused with "Use a public address, not a private network". Usernames and passwords in the URL aren't allowed.

To test on your own computer, use a tunnelling tool that gives you a public https:// address.

How do I see what was sent? ​

Click Deliveries on the webhook. It shows the last 50 deliveries with their Event, Result (Delivered, Retrying or Failed), number of Tries and When. Click a row to see the exact body that was sent. Click Retry on a failed delivery to send it again.

The webhook card also shows when it last sent, what your endpoint answered, and how many were delivered and failed today.

How do I change, pause or delete a webhook? ​

  • Edit: change the URL or events.
  • Turn off / Turn on: pause and resume. While a webhook is off, new events aren't queued for it.
  • New secret: makes a new signing secret. "The old one stops working straight away", so update your server at the same moment.
  • Bin icon: deletes the webhook.

Can I receive photos and files customers send? ​

The message.received event tells you a file arrived (type is image, document and so on, and text has any caption), but it doesn't include the file itself. Your team can open it in the KiliChat inbox. To collect files automatically, use a flow's Ask for a file step, which saves a link on the contact.

See also Rate limits and retries for what happens when your endpoint is down.