Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.khaime.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhook Best Practices

1. Respond Fast

Return 200 OK within 5 seconds. Process the event asynchronously after acknowledging:
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  res.status(200).send('OK');           // Acknowledge immediately
  const payload = JSON.parse(req.body); // Process in background
  processEvent(payload);
});

2. Handle Duplicates

Use the event_id field (also sent as the X-Khaime-Event-Id header) for idempotency. The same event may be delivered more than once — retries reuse the same event_id:
async function handleEvent(payload) {
  const { event_id } = payload;

  // Use a database or Redis — not in-memory sets
  const alreadyProcessed = await redis.get(`webhook:${event_id}`);
  if (alreadyProcessed) return;

  await redis.set(`webhook:${event_id}`, '1', 'EX', 86400); // TTL: 24h
  // Process...
}

3. Verify Before Processing

Always verify the signature using the raw request body before acting on a webhook. Reject unverified requests with 401.

4. Handle Missing Events

If a webhook is missed and you used the Sessions API, you can check the payment status directly:
# Check session status (Sessions API only)
GET /api/v1/partner/payments/sessions/{session_id}
For payments created via the Charge API, webhook delivery is the only confirmation mechanism. Ensure your webhook endpoint is reliable and returns 200 promptly.

5. Use the Envelope Fields

Every webhook includes useful envelope fields beyond the event data:
  • api_version — confirms which payload schema version was used
  • is_live — distinguish sandbox events from production
  • business_id — identify which merchant the event belongs to (useful in marketplace setups)

6. Log Everything

Log raw webhook payloads for debugging. Include the event_id, event_type, and processing result.

7. Use HTTPS

Webhook URLs must use HTTPS in production. Khaime will not deliver webhooks to HTTP endpoints in live mode.

8. Plan for New Event Types

New event types may be added without a version change. Your webhook handler should gracefully ignore unknown event_type values rather than erroring:
switch (payload.event_type) {
  case 'payment.succeeded':
    handlePaymentSucceeded(payload.data);
    break;
  case 'payment.refunded':
    handlePaymentRefunded(payload.data);
    break;
  // ... other known events
  default:
    console.log(`Unhandled event type: ${payload.event_type}`);
}