Webhooks

Receive real-time notifications when events happen in your workspace. Configure webhook endpoints to receive HTTP POST requests whenever a ticket is created, a message is sent, an SLA is breached, or any other supported event occurs. Webhooks let you integrate Keme with your own infrastructure without polling the API.

Each delivery is an HTTP POST to your configured URL containing a signed JSON payload. Keme includes an x-keme-signature header on every request so you can verify that the delivery originated from Keme and has not been tampered with in transit.

Events

The following event types are available for subscription. Subscribe to one or more events when creating a webhook endpoint. Wildcard subscriptions (*) are not supported — you must enumerate the specific events you want to receive.

Event TypeTrigger
ticket.createdA new support ticket is created in your workspace.
ticket.assignedA ticket is assigned or reassigned to an agent.
ticket.resolvedA ticket status is changed to resolved.
ticket.closedA ticket is closed, either manually or by automation.
message.createdA new message is added to a ticket by a player or agent.
player.createdA new player profile is registered in your workspace.
sla.breachedA ticket has exceeded its SLA response or resolution deadline.

Webhook Payload

Every webhook delivery uses a standard envelope regardless of the event type. The data object contains the resource-specific fields for the event. The id field is unique per delivery and can be used for deduplication in your handler.

Standard webhook envelope
1{
2 "id": "evt_xxxxxxxxxxxxxxxxxxxx",
3 "event": "ticket.created",
4 "workspaceId": "ws_xxxxxxxxxxxx",
5 "timestamp": "2026-06-15T10: 23: 45Z",
6 "data": {
7 "ticketId": "tkt_xxxxxxxxxxxx",
8 "title": "Purchase failed",
9 "status": "open",
10 "priority": "high",
11 "playerId": "player_12345"
12 }
13}
Note:The shape of data varies by event type. For ticket.* events it contains the ticket object; for message.created it contains the message object; for player.created it contains the player profile; and for sla.breached it includes the ticket ID, breached policy name, and breach timestamp.

Signature Verification

All webhook deliveries include an x-keme-signature header containing an HMAC-SHA256 hex digest of the raw request body, signed with your webhook's shared secret. You must verify this signature before processing any event to protect your endpoint from spoofed requests.

The shared secret is returned once when you create the webhook endpoint (in the secret field). Store it securely — it is not retrievable again via the API. If you lose it, rotate by deleting and recreating the webhook.

Warning:Always use a constant-time comparison function (such as crypto.timingSafeEqual) when comparing signatures. Standard string equality is vulnerable to timing attacks and must not be used.
Signature verification — Node.js / Express
1const crypto = require('crypto');
2
3function verifyWebhookSignature(payload, signature, secret) {
4 const expected = crypto
5 .createHmac('sha256', secret)
6 .update(payload, 'utf8')
7 .digest('hex');
8 return crypto.timingSafeEqual(
9 Buffer.from(signature),
10 Buffer.from(expected)
11 );
12}
13
14// Express.js example
15app.post('/webhooks/keme', express.raw({ type: 'application/json' }), (req, res) => {
16 const sig = req.headers['x-keme-signature'];
17 if (!verifyWebhookSignature(req.body, sig, process.env.KEME_WEBHOOK_SECRET)) {
18 return res.status(401).send('Invalid signature');
19 }
20 const event = JSON.parse(req.body);
21 // Handle event...
22 res.status(200).send('OK');
23});
Note:Use express.raw() (or the equivalent raw body parser in your framework) rather than express.json() when reading the request body for signature verification. Parsing the body as JSON before verifying will modify the byte representation and cause all signature checks to fail.

Create Webhook Endpoint

POST/v1/webhooks🔒 Auth required

Registers a new webhook endpoint for your workspace. The response includes a secret field containing the HMAC signing key. This secret is shown only once — store it securely immediately after creation.

Request Body
ParameterTypeRequiredDescription
workspaceIdstringRequiredThe workspace this webhook belongs to. All events will be scoped to this workspace.
urlstringRequiredThe HTTPS URL that Keme will POST events to. Must be publicly reachable and use HTTPS.
eventsstring[]RequiredList of event types to receive (e.g. ["ticket.created", "sla.breached"]). At least one event is required.
descriptionstringOptionalHuman-readable label for this endpoint. Useful when managing multiple webhooks in the same workspace.
activebooleanOptionalWhether the endpoint should receive events immediately. Defaults to true. Set false to register the endpoint in a paused state.
Response
201
json
1{
2 "id": "wh_xxxx",
3 "workspaceId": "ws_xxxxxxxxxxxx",
4 "url": "https://yourserver.com/webhooks",
5 "events": ["ticket.created", "ticket.resolved"],
6 "description": "Production support events",
7 "active": true,
8 "secret": "whsec_xxxx",
9 "createdAt": "2026-06-15T10: 23: 45Z"
10}

List Webhooks

GET/v1/webhooks🔒 Auth required

Returns all webhook endpoints registered for the specified workspace. The secret field is omitted from list responses — it is only returned at creation time.

Query Parameters
ParameterTypeRequiredDescription
workspaceIdstringRequiredThe workspace whose webhook endpoints you want to retrieve.
Response
200
json
1{
2 "total": 2,
3 "data": [
4 {
5 "id": "wh_xxxx",
6 "workspaceId": "ws_xxxxxxxxxxxx",
7 "url": "https://yourserver.com/webhooks",
8 "events": ["ticket.created", "ticket.resolved"],
9 "description": "Production support events",
10 "active": true,
11 "createdAt": "2026-06-15T10: 23: 45Z"
12 },
13 {
14 "id": "wh_yyyy",
15 "workspaceId": "ws_xxxxxxxxxxxx",
16 "url": "https://staging.yourserver.com/webhooks",
17 "events": ["ticket.created", "message.created", "sla.breached"],
18 "description": "Staging — all ticket and SLA events",
19 "active": false,
20 "createdAt": "2026-06-14T08: 00: 00Z"
21 }
22 ]
23}

Delete Webhook

DELETE/v1/webhooks/:id🔒 Auth required

Permanently removes a webhook endpoint. No further events will be delivered to the associated URL. Returns 204 No Content on success. In-flight deliveries that are already queued may still arrive at your endpoint shortly after deletion.

Path Parameters
ParameterTypeRequiredDescription
idstringRequiredThe unique identifier of the webhook endpoint to delete (e.g. wh_xxxx).

Retry Policy

If your endpoint returns a non-2xx HTTP status code, times out (30-second limit), or is unreachable, Keme will retry the delivery using exponential backoff. The retry schedule is:

  • Attempt 1: Immediately after the initial failure.
  • Attempt 2: 5 minutes after attempt 1.
  • Attempt 3: 30 minutes after attempt 2.
  • Attempt 4: 2 hours after attempt 3.
  • Attempt 5: 8 hours after attempt 4.

After 5 failed attempts the delivery is marked as permanently failed. The total retry window is approximately 24 hours. Failed and succeeded deliveries are retained in the delivery log for 7 days and are viewable from your workspace settings.

Warning:Keme treats any 2xx HTTP response code as a successful acknowledgement. Your endpoint should respond with a 200 (or 204) as quickly as possible — within the 30-second timeout — and process the event asynchronously. Long-running synchronous processing inside the request handler is the most common cause of unnecessary retries.

Testing

Keme provides two tools to help you develop and validate your webhook handler before going live.

Test mode: Enable test mode on any webhook endpoint from Workspace Settings → Integrations → Webhooks. In test mode, Keme sends synthetic event payloads to your endpoint using real envelope structure and valid HMAC signatures, but no live workspace data is involved. This is safe to use against a local development server.

Event simulator: The event simulator lets you manually fire a specific event type to a registered endpoint on demand. Navigate to your webhook endpoint in workspace settings and click Send test event. Select the event type, optionally customise the payload fields, and click Send. The delivery result and response code are shown immediately in the UI.

Note:For local development, use a tunnelling tool such as ngrok or cloudflared tunnel to expose your local server via a public HTTPS URL. Keme requires HTTPS for all webhook endpoints — plain HTTP URLs will be rejected at registration time.
Last updated: June 15, 2026Edit this page