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.
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):
- Go to Settings → API Keys → Webhooks tab.
- Click Create Webhook.
- Enter your endpoint URL and select the events you want to receive.
- Copy the signing secret immediately — it is shown only once.
Alternatively, you can register webhooks via the API:
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
{"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"}}
secret is shown only once on creation. Store it securely — you will need it to verify webhook signatures.Event Types
lead.createdeventA new lead was captured (pre-chat form, in-chat, manual, or Telegram).
ticket.createdeventA new support ticket was created.
ticket.updatedeventA ticket was modified (any field change).
ticket.status_changedeventA ticket's status changed (e.g., open → resolved).
ticket.assignedeventA ticket was assigned or reassigned to an agent.
ticket.department_changedeventA ticket was transferred to a different department.
ticket.reopenedeventA resolved or closed ticket was reopened.
ticket.replyeventAn agent replied to a ticket (includes content and actor ID).
ticket.customer_replyeventA customer replied to a ticket via widget or email.
conversation.createdeventA new chat conversation was started.
conversation.completedeventA conversation was resolved.
conversation.handed_offeventA conversation was escalated to human support (entered handoff queue).
visitor.identifiedeventA visitor's identity was captured (email, name, etc.).
Payload Format
{"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.
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 eventconsole.log(req.body.event, req.body.data);res.status(200).send("OK");});
import hmac, hashlibdef 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.jsonprint(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.