Skip to main content
Webhooks let you receive real-time HTTP notifications when events occur in your IllumiChat workspace. Instead of polling the API, configure a webhook endpoint and IllumiChat will send a POST request to your URL each time a subscribed event fires.

List Webhooks

Returns all webhooks configured for the workspace.
curl -X GET "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks" \
  -H "Authorization: Bearer <your-api-key>"
Response 200 OK
{
  "data": [
    {
      "id": "wh_aaa111",
      "url": "https://api.acme.com/webhooks/illumichat",
      "events": ["message.created", "conversation.created", "contact.created"],
      "active": true,
      "createdAt": "2025-08-01T12:00:00Z"
    }
  ],
  "total": 1,
  "limit": 25,
  "offset": 0
}

Create Webhook

Registers a new webhook endpoint. Requires owner or admin role.
curl -X POST "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://api.acme.com/webhooks/illumichat",
    "events": ["message.created", "conversation.created", "contact.created"],
    "secret": "whsec_your_signing_secret"
  }'
ParameterTypeRequiredDescription
urlstringYesThe HTTPS endpoint URL that receives webhook payloads.
eventsstring[]YesList of event types to subscribe to. Use ["*"] for all events.
secretstringNoSigning secret for HMAC verification. Auto-generated if omitted.
activebooleanNoWhether the webhook is active. Default true.
Response 201 Created
The secret field is only returned in the create response. Store it securely — you will need it to verify webhook signatures. It cannot be retrieved later.

Get Webhook

Retrieves a webhook by ID.
curl -X GET "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks/wh_aaa111" \
  -H "Authorization: Bearer <your-api-key>"
Response 200 OK with the webhook object (excluding secret).

Update Webhook

Updates a webhook’s configuration. Requires owner or admin role.
curl -X PATCH "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks/wh_aaa111" \
  -H "Authorization: Bearer <your-api-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["message.created", "conversation.created", "conversation.ended", "contact.created"],
    "active": true
  }'
Response 200 OK with the updated webhook object.

Delete Webhook

Permanently removes a webhook and all its delivery history. Requires owner or admin role.
curl -X DELETE "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks/wh_aaa111" \
  -H "Authorization: Bearer <your-api-key>"
Response 204 No Content

List Deliveries

Returns recent delivery attempts for a webhook. Uses cursor-based pagination.
curl -X GET "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks/wh_aaa111/deliveries?limit=20" \
  -H "Authorization: Bearer <your-api-key>"
Response 200 OK
{
  "data": [
    {
      "id": "del_aaa111",
      "event": "message.created",
      "status": "success",
      "statusCode": 200,
      "attempt": 1,
      "duration": 234,
      "createdAt": "2025-09-15T10:00:01Z"
    }
  ],
  "nextCursor": "eyJpZCI6ImRlbF9iYmIyMjIifQ==",
  "hasMore": true
}

Retry Delivery

Manually retries a failed webhook delivery.
curl -X POST "https://beta.illumichat.com/api/workspaces/ws_abc123/webhooks/wh_aaa111/deliveries/del_bbb222/retry" \
  -H "Authorization: Bearer <your-api-key>"
Response 202 Accepted

Event Types

Subscribe to any combination of the following event types.
EventDescription
message.createdA new message was sent in a conversation (user or assistant).
message.updatedA message was edited or its metadata changed.
conversation.createdA new conversation was started.
conversation.endedA conversation was closed or a widget session ended.
contact.createdA new contact was created (e.g., via widget lead form).
contact.updatedA contact’s information was updated.
ticket.createdA support ticket was created from a conversation.
ticket.updatedA ticket’s status or assignment changed.
ticket.resolvedA ticket was marked as resolved.
assistant.updatedAn assistant’s configuration was changed.
member.joinedA new member joined the workspace.
member.leftA member was removed or left the workspace.
Use ["*"] as the events array to subscribe to all current and future event types.

Payload Format

Every webhook delivery sends a JSON payload with a consistent structure.
{
  "id": "evt_aaa111",
  "event": "message.created",
  "timestamp": "2025-09-15T10:00:00.123Z",
  "workspaceId": "ws_abc123",
  "data": {
    "id": "msg_xyz",
    "conversationId": "conv_aaa111",
    "role": "user",
    "content": "How do I update my payment method?",
    "assistantId": "ast_abc123",
    "createdAt": "2025-09-15T10:00:00Z"
  }
}
FieldTypeDescription
idstringUnique event ID. Use this to deduplicate deliveries.
eventstringThe event type that triggered this delivery.
timestampstringISO 8601 timestamp of when the event occurred.
workspaceIdstringThe workspace where the event originated.
dataobjectEvent-specific payload. Structure varies by event type.

Signature Verification

Every webhook request includes an X-IllumiChat-Signature header containing an HMAC-SHA256 signature of the request body. Always verify this signature to ensure the payload was sent by IllumiChat. The signature is computed as:
HMAC-SHA256(webhook_secret, raw_request_body)

Verification Examples

import crypto from "node:crypto";

function verifyWebhookSignature(rawBody, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(rawBody)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express.js example
app.post("/webhooks/illumichat", express.raw({ type: "application/json" }), (req, res) => {
  const signature = req.headers["x-illumichat-signature"];
  const secret = process.env.ILLUMICHAT_WEBHOOK_SECRET;

  if (!verifyWebhookSignature(req.body, signature, secret)) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const event = JSON.parse(req.body);
  // Process the event...

  res.status(200).json({ received: true });
});
Always use a constant-time comparison function (such as crypto.timingSafeEqual or hmac.compare_digest) when verifying signatures. Standard string comparison is vulnerable to timing attacks.

Retry Policy

If your endpoint does not return a 2xx status code within 30 seconds, IllumiChat retries the delivery with exponential backoff.
AttemptDelayTotal Elapsed
1Immediate0 seconds
260 seconds~1 minute
3300 seconds~6 minutes
After 3 failed attempts, the delivery is marked as failed. You can manually retry failed deliveries at any time using the Retry Delivery endpoint.
Return 200 quickly. Acknowledge the webhook immediately and process the event asynchronously.Deduplicate by event ID. The same event may be delivered more than once during retries. Use the id field to detect duplicates.Verify the signature. Always validate the X-IllumiChat-Signature header before processing.Handle unknown events gracefully. New event types may be added in the future. Return 200 for events you do not recognize.
If a webhook consistently fails (more than 50 consecutive failures over 7 days), IllumiChat automatically disables the webhook and notifies workspace admins.