Next CapNext Cap

Webhooks

Real-time event notifications pushed to your server when leads are created, tickets are updated, and more.

Overview

Webhooks push real-time event notifications to your server when things happen in your Next Cap account — a lead is captured, a ticket is created or updated, a conversation completes, etc.

Enterprise plan only. Pro plan organizations have access to the REST API but not webhooks. Upgrade to Enterprise to enable real-time event delivery.
Recently added (May 2026): Three new call-back request events — call_request.created, call_request.updated, call_request.completed — fire whenever a visitor submits a callback through the widget or your team updates one. The payload data matches the /external/call-requests response, including any custom visitor-form fields your organization configured.
Recently added (July 2026): Thirteen help desk content events — help_center.*, help_collection.*, help_category.*, and help_article.* — fire whenever help center content changes. They power the incremental sync flow of the Helpdesk Content API.

Setting Up Webhooks

You can create and manage webhooks from the Next Cap Dashboard or programmatically via the API using a Data API key.

From the Dashboard (recommended):

  1. Go to Settings → API Keys → Webhooks tab.
  2. Click Create Webhook.
  3. Enter your endpoint URL and select the events you want to receive.
  4. Copy the signing secret immediately — it is shown only once.

Alternatively, you can register webhooks via the API:

Register a webhook (API)bash
curl -X POST -H "X-Api-Key: sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://your-server.com/webhooks/nextcap", "events": ["lead.created", "ticket.created"]}' \
https://api.nextcap.ai/api/v1/external/webhooks
Response — 201 Createdjson
{
"data": {
"id": "uuid",
"url": "https://your-server.com/webhooks/nextcap",
"secret": "a1b2c3...your-signing-secret...z9y8",
"events": ["lead.created", "ticket.created"],
"is_active": true,
"created_at": "2026-04-01T12:00:00.000Z"
}
}
The secret is shown only once on creation. Store it securely — you will need it to verify webhook signatures.

Event Types

lead.createdevent

A new lead was captured (pre-chat form, in-chat, manual, or Telegram).

ticket.createdevent

A new support ticket was created.

ticket.updatedevent

A ticket was modified (any field change).

ticket.status_changedevent

A ticket's status changed (e.g., open → resolved).

ticket.assignedevent

A ticket was assigned or reassigned to an agent.

ticket.department_changedevent

A ticket was transferred to a different department.

ticket.reopenedevent

A resolved or closed ticket was reopened.

ticket.replyevent

An agent replied to a ticket (includes content and actor ID).

ticket.customer_replyevent

A customer replied to a ticket via widget or email.

conversation.createdevent

A new chat conversation was started.

conversation.completedevent

A conversation was resolved.

conversation.handed_offevent

A conversation was escalated to human support (entered handoff queue).

visitor.identifiedevent

A visitor's identity was captured (email, name, etc.).

call_request.createdevent

A visitor submitted a call-back request from the widget.

call_request.updatedevent

A call request was modified — status change, assignment, or note added.

call_request.completedevent

A call request reached the 'completed' status (callback finished).

help_center.createdevent

A help center was created.

help_center.updatedevent

A help center's settings changed (name, locales, domain, theme). A restore fires this with restored: true.

help_center.deletedevent

A help center was deleted.

help_collection.createdevent

A collection was added to a help center.

help_collection.updatedevent

A collection changed, including AI translation fills (locales_filled).

help_collection.deletedevent

A collection was deleted (children are promoted to its parent).

help_category.createdevent

A legacy category was added under a collection.

help_category.updatedevent

A legacy category changed.

help_category.deletedevent

A legacy category was deleted.

help_article.createdevent

An article was created (payload includes its status).

help_article.updatedevent

An article changed, including AI translation fills (locales_filled).

help_article.publishedevent

An article transitioned to published — the typical 'rebuild my help site' trigger.

help_article.deletedevent

An article was soft-deleted; it stays fetchable with deleted_at set.

Payload Format

Webhook payloadjson
{
"event": "lead.created",
"timestamp": "2026-04-01T12:05:00.000Z",
"data": {
"id": "uuid",
"email": "john@acme.com",
"name": "John Doe",
"company": "Acme Inc",
"source": "pre_chat_form",
"created_at": "2026-04-01T12:05:00.000Z"
}
}

The data field uses the same shape as the corresponding REST API response for that entity.

Signature Verification

Every webhook request includes an X-Webhook-Signature header containing an HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret.

Verify signature (Node.js)javascript
const crypto = require("crypto");
function verifyWebhook(body, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected),
);
}
// In your Express handler:
app.post("/webhooks/nextcap", (req, res) => {
const sig = req.headers["x-webhook-signature"];
if (!verifyWebhook(req.rawBody, sig, WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
// Process the event
console.log(req.body.event, req.body.data);
res.status(200).send("OK");
});
Verify signature (Python)python
import hmac, hashlib
def verify_webhook(body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(signature, expected)
# In your Flask handler:
@app.post("/webhooks/nextcap")
def handle_webhook():
sig = request.headers.get("X-Webhook-Signature")
if not verify_webhook(request.data, sig, WEBHOOK_SECRET):
abort(401)
payload = request.json
print(payload["event"], payload["data"])
return "OK", 200

Retries & Auto-Disable

Failed deliveries are retried 3 times with exponential backoff (5s, 30s, 2 min). After 10 consecutive failures, the webhook is automatically disabled. You can re-enable it by deleting and re-creating it.

Management Endpoints

GET/external/webhooksAPI Key

List all registered webhooks for your organization.

POST/external/webhooksAPI Key

Register a new webhook.

urlstringrequired

HTTPS URL to receive webhook events.

eventsstring[]required

Array of event types to subscribe to.

DELETE/external/webhooks/:idAPI Key

Remove a registered webhook.

POST/external/webhooks/:id/testAPI Key

Send a test event to verify your endpoint is receiving payloads.