Receive messages
هذا المحتوى غير متوفر بلغتك بعد.
Polling for new messages does not scale and is always slightly out of date. Webhooks push each event to you as it happens.
-
Build an endpoint
Section titled “Build an endpoint”One public HTTPS URL that accepts
POSTwith a JSON body.app.post('/hooks/kmessage', express.raw({ type: 'application/json' }), (req, res) => {// Verify first, using the raw bytes. See the signature guide.if (!verify(req.body, req.headers)) return res.sendStatus(401)// Answer immediately, work afterwards. We time out, and a slow// endpoint turns into retries and duplicates.res.sendStatus(200)const { event, data } = JSON.parse(req.body)queue.push({ event, data })})Two rules matter more than anything else here: verify before trusting, and reply before working.
-
Subscribe
Section titled “Subscribe”In the dashboard, Settings → Webhooks → Add webhook, or through the API:
Terminal window curl https://k-message.kerneltics.com/v1/webhooks \-H "Authorization: Bearer km_live_YOUR_KEY" \-H "Content-Type: application/json" \-d '{"name": "Order updates","url": "https://api.example.com/hooks/kmessage","events": ["message.incoming", "message.delivered", "message.failed"]}'The response carries the signing
secret, once. Store it. -
Test it
Section titled “Test it”Use the Send test button, or
POST /v1/webhooks/{id}/test. It reports the status your own server returned and what it said, so a failing endpoint is diagnosable without reading your logs. -
Handle the events
Section titled “Handle the events”switch (event) {case 'message.incoming':await onCustomerReply(data.contact_phone, data.content)breakcase 'message.delivered':await markDelivered(data.message_id)breakcase 'message.failed':await markFailed(data.message_id, data.error_message)break}Ignore events you do not recognise rather than failing on them. New event types are added over time, and a
500on an unknown one turns an addition into an outage.
Retries and duplicates
Section titled “Retries and duplicates”A 5xx or a timeout is retried three times with backoff: 1s, 2s, 4s. A 4xx
is not retried, because a request that was malformed will still be malformed.
Deduplicate on X-KM-Delivery-Id. All attempts at one event share it, so
storing the ids you have processed makes a retry harmless. Assume you will see
duplicates: a retry after your server processed the event but before its
response reached us is a normal outcome, not an error.
When nothing arrives
Section titled “When nothing arrives”The delivery history is the first place to look, not the last. Open the webhook in the dashboard, or:
curl https://k-message.kerneltics.com/v1/webhooks/{id}/deliveries \ -H "Authorization: Bearer km_live_YOUR_KEY"Every attempt is there with the exact payload we sent and what your server replied, kept for 7 days. In practice it is nearly always one of:
status_code: 0— we never reached you. DNS, a firewall, or an expired TLS certificate.status_code: 500— your handler threw.response_bodyusually contains the stack trace.status_code: 401— your signature check is rejecting us. See Verify webhook signatures; it is almost always a body that was parsed before being verified.- Nothing at all — the event is not in the webhook’s subscription list, or the webhook is switched off.
Local development
Section titled “Local development”Your endpoint must be reachable from the internet, so private and loopback
addresses are refused. Use a tunnel (ngrok http 3000 or similar) and register
the public URL it gives you.