Webhooks
Signed events for orders, refunds, check-ins and pages.
Konecto sends signed POST requests to your endpoints and retries with backoff for about 72 hours (1 min, 5 min, 15 min, 1 h, 3 h, 6 h, 12 h, then daily). Answer with any 2xx within 10 seconds.
| Event | When | data |
|---|---|---|
| order.paid | A checkout completed and tickets were issued | order_id, event_id, total_minor, currency, tickets |
| order.refunded | An order was fully or partly refunded | order_id, amount_minor, currency |
| attendee.registered | A guest was added by import | event_id, email, source |
| ticket.checked_in | A ticket was scanned at the door | ticket_id, event_id, device_id |
| event.published | An event was published | event_id, public_url |
| event.updated | Event details changed | event_id, changed[] |
| event_page.published | The event page was published | event_id |
| module.enabled | A module was enabled for an event | event_id, module |
| challenge.completed | An attendee completed a challenge | event_id, challenge_id |
| booth.scanned | An exhibitor scanned an attendee at a booth | event_id, booth_id |
Payload
{
"id": "whd_9f2c…",
"type": "order.paid",
"created": "2026-11-14T18:02:11.412Z",
"data": { "order_id": "ord_91x…", "event_id": "evt_2Lm…", "total_minor": 4000, "currency": "GBP", "tickets": 2 }
}
Fetch the full order with GET /v1/orders/{order_id} when you need more than the ids.
Manage endpoints
Create endpoints in the app under Settings, Developers, Webhooks, or with the API:
curl https://api.konec.to/v1/webhook-endpoints -H "Authorization: Bearer sk_live_..." -H "Idempotency-Key: 7b4e..." \
-H "Content-Type: application/json" -d '{ "url": "https://example.com/konecto", "events": ["order.paid", "ticket.checked_in"] }'
The response carries the signing secret once. POST /webhook-endpoints/{id}/test sends a sample event and reports the status code your endpoint returned; GET /webhook-endpoints/{id}/deliveries lists attempts; POST .../deliveries/{id}/retry resends one; POST .../rotate-secret issues a new secret.
Verify the signature
Each request has a Konecto-Signature header: t=<unix seconds>,v1=<hex HMAC-SHA256 of "t.body"> with your endpoint secret. Reject requests older than five minutes and compare in constant time. The SDK does this for you:
import { constructWebhookEvent } from '@konecto/sdk';
const event = await constructWebhookEvent(rawBody, req.headers.get('Konecto-Signature'), process.env.KONECTO_WEBHOOK_SECRET);
Without the SDK:
import crypto from 'node:crypto';
export function verify(body: string, header: string, secret: string) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
const expected = crypto.createHmac('sha256', secret).update(parts.t + '.' + body).digest('hex');
const fresh = Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
return fresh && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
Use the raw request body, not a re-serialised object.
Plain-text version for agents: llm.konec.to/docs/api/webhooks.md