API reference: Webhooks

Webhooks. Hear about events as they happen.

Add an HTTPS endpoint and SimplyBoost sends it a signed request when a conversation is handed over or resolved, a lead is captured, or knowledge is ready.

lead.captured
POST https://example.com/hooks/simplyboost
200 OK
SimplyBoost-Event: lead.captured
SimplyBoost-Delivery: evt_9b2…
SimplyBoost-Signature: t=1791…,v1=5f3a…
Signature verified

Events

EventWhen`data` contains
conversation.escalatedA conversation is handed to your teamconversation, and escalation with reason, category and urgency
conversation.resolvedA conversation is marked resolvedconversation
lead.capturedA visitor leaves an email or phone number (once per lead)lead
knowledge.syncedA knowledge source is ready, or failedsource
Request body
{
  "id": "evt_9b2f6c1e8a4d4f7b9e3c1a5d7f2b4e6c",
  "type": "conversation.escalated",
  "createdAt": "2026-10-07T09:35:12+00:00",
  "data": {
    "conversation": { "threadId": "3f0c…", "channel": "web", "mode": "human", "escalated": true, … },
    "escalation": { "reason": "The visitor was charged twice and asked for a person.", "category": "billing", "urgency": "high" }
  }
}

conversation, lead and source have the same fields as in the API responses. The id is the same on every retry of one event.

Verify the signature

Each request has three headers: SimplyBoost-Event (the type), SimplyBoost-Delivery (the event id) and SimplyBoost-Signature: t=<unix time>,v1=<signature>. The signature is the hex HMAC-SHA256 of <t>.<raw body> with the endpoint's secret. Check it against the raw body before parsing it, and refuse timestamps older than five minutes.

Node.js
import crypto from "node:crypto";

export function verifySimplyBoost(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const timestamp = Number(parts.t);
  if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;
  const expected = crypto.createHmac("sha256", secret).update(`${parts.t}.${rawBody}`).digest("hex");
  const given = Buffer.from(parts.v1 || "", "hex");
  return given.length === 32 && crypto.timingSafeEqual(given, Buffer.from(expected, "hex"));
}
Python
import hashlib, hmac, time

def verify_simplyboost(raw_body: bytes, header: str, secret: str, tolerance_seconds: int = 300) -> bool:
    parts = dict(part.split("=", 1) for part in header.split(","))
    timestamp = parts.get("t", "")
    if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > tolerance_seconds:
        return False
    signed = f"{timestamp}.".encode() + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Delivery and retries

  • Reply with any 2xx status within 10 seconds. Do slow work after replying.
  • A failed delivery is retried up to 6 times, waiting longer each time (about half an hour in total).
  • After 20 failed deliveries in a row the endpoint is switched off (active: false, with disabledReason). Add it again once it is fixed.
  • Redirects are not followed, and the address must stay public: an endpoint that starts pointing at a private network is switched off.
  • An event can arrive more than once and out of order. Use its id to skip repeats and createdAt to order.

Add a webhook endpoint

POST/webhooks

Webhook endpoints belong to the account and receive events from all its chatbots.

Permission: webhooks:write

Body (JSON)

url
stringrequired

A public https:// address, up to 500 characters.

events
string[]required

At least one of conversation.escalated, conversation.resolved, lead.captured, knowledge.synced.

Request
curl -X POST https://get-api.simplyboost.io/api/v1/webhooks \
  -H "Authorization: Bearer $SIMPLYBOOST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/hooks/simplyboost", "events": ["conversation.escalated", "lead.captured"]}'

Response 201 Created

{
  "ok": true,
  "data": {
    "webhook": {
      "id": "5e8a2c1d-7f3b-4a9e-b6d0-1c4f8e2a9b73",
      "url": "https://example.com/hooks/simplyboost",
      "events": ["conversation.escalated", "lead.captured"],
      "active": true,
      "disabledReason": null,
      "lastDeliveryAt": null,
      "lastStatusCode": null,
      "createdAt": "2026-10-07T11:00:00+00:00",
      "secret": "whsec_…"
    }
  },
  "meta": { "requestId": "req_7c1e4b2a9f0d4e6c8b3a5d7f9e1c2b4a" }
}

Response fields

data.webhook.id
string

The endpoint's ID.

data.webhook.url
string

Where events are sent.

data.webhook.events
string[]

The events it receives.

data.webhook.active
boolean

False when it was switched off after repeated failures.

data.webhook.disabledReason
string | null

Why it was switched off.

data.webhook.lastDeliveryAt
string | null

When the last event was sent.

data.webhook.lastStatusCode
integer | null

Your server's last response status.

data.webhook.createdAt
string (date-time)

When it was added.

data.webhook.secret
string

The signing secret, whsec_…. Shown only in this response: store it.

Errors

StatusCodeWhen
400validation_errorurl is not a public https:// address, or events is empty or has an unknown event.
400endpoint_limitThe account already has 10 endpoints.

List webhook endpoints

GET/webhooks

The account's endpoints (without their secrets) and the events you can subscribe to.

Permission: webhooks:read

Request
curl https://get-api.simplyboost.io/api/v1/webhooks \
  -H "Authorization: Bearer $SIMPLYBOOST_TOKEN"

Response 200 OK

{
  "ok": true,
  "data": {
    "webhooks": [{ "id": "5e8a…", "url": "https://example.com/hooks/simplyboost", "events": ["conversation.escalated", "lead.captured"], "active": true, … }],
    "events": ["conversation.escalated", "conversation.resolved", "knowledge.synced", "lead.captured"]
  },
  "meta": { "requestId": "req_7c1e4b2a9f0d4e6c8b3a5d7f9e1c2b4a" }
}

Response fields

data.webhooks[].id
string

The endpoint's ID.

data.webhooks[].url
string

Where events are sent.

data.webhooks[].events
string[]

The events it receives.

data.webhooks[].active
boolean

False when it was switched off after repeated failures.

data.webhooks[].disabledReason
string | null

Why it was switched off.

data.webhooks[].lastDeliveryAt
string | null

When the last event was sent.

data.webhooks[].lastStatusCode
integer | null

Your server's last response status.

data.webhooks[].createdAt
string (date-time)

When it was added.

data.events
string[]

Every event type you can subscribe to.

Errors

Only the common errors (see Responses and errors).

Send a test event

POST/webhooks/{webhookId}/test

Sends a signed webhook.test event to the endpoint now and reports what your server answered.

Permission: webhooks:write

Path parameters

webhookId
string (uuid)required

The webhook endpoint, from webhook.id.

Request
curl -X POST https://get-api.simplyboost.io/api/v1/webhooks/WEBHOOK_ID/test \
  -H "Authorization: Bearer $SIMPLYBOOST_TOKEN"

Response 200 OK

{
  "ok": true,
  "data": { "delivered": true, "statusCode": 200 },
  "meta": { "requestId": "req_7c1e4b2a9f0d4e6c8b3a5d7f9e1c2b4a" }
}

Response fields

data.delivered
boolean

True when your server answered with a 2xx.

data.statusCode
integer | null

Your server's status, or null when it could not be reached.

Errors

StatusCodeWhen
404not_foundNo such webhook endpoint, or this token may not see it.
400validation_errorThe address now points at a private or internal network.

Remove a webhook endpoint

DELETE/webhooks/{webhookId}

Stops sending events to the endpoint.

Permission: webhooks:write

Path parameters

webhookId
string (uuid)required

The webhook endpoint, from webhook.id.

Request
curl -X DELETE https://get-api.simplyboost.io/api/v1/webhooks/WEBHOOK_ID \
  -H "Authorization: Bearer $SIMPLYBOOST_TOKEN"

Response 200 OK

{
  "ok": true,
  "data": { "id": "5e8a2c1d-7f3b-4a9e-b6d0-1c4f8e2a9b73", "deleted": true },
  "meta": { "requestId": "req_7c1e4b2a9f0d4e6c8b3a5d7f9e1c2b4a" }
}

Response fields

data.id
string

The removed endpoint's ID.

data.deleted
boolean

Always true.

Errors

StatusCodeWhen
404not_foundNo such webhook endpoint, or this token may not see it.

Try SimplyBoost with your own content

Start a 7-day free trial with 100 AI replies. Add your website, install the widget and see how the agent answers your customers.

See pricing
  • No credit card required
  • 7 days, 100 AI replies
  • From €39 a month
  • Hosted in Europe