Connect
API & webhooks
Quincer AI is API-first. Everything you can do in the dashboard — take over a live chat, update a lead, read the activity log — you can do via REST. This page is the map. For request/response previews against your real workspace, open Developer APIs inside the dashboard.
Authentication
All API requests use a workspace developer key. Generate one under Dashboard → Developers → API Keys, choose scopes, and pass it as a Bearer token:
Authorization: Bearer cw_dev_<your-key>
Two kinds of credentials exist: widget keys (cw_live_) are
embedded in the page script and only identify a widget to the public chat endpoint.
Developer keys (cw_dev_) are scoped to an organization, carry
explicit scopes like leads:read or conversations:takeover, and
must stay server-side.
Base URL
https://chat.quincer.com
External agent (takeover) endpoints
Use these to let an outside AI (OpenClaw, a custom agent, or your own backend) take over a live conversation, reply as a human, and hand back to the Quincer AI. These are how the OpenClaw integration works under the hood.
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /api/v1/conversations/:id | conversations:read | Fetch full transcript + metadata. |
POST | /api/v1/conversations/:id/takeover | conversations:takeover | Claim a conversation — AI stops responding. |
POST | /api/v1/conversations/:id/reply | conversations:reply | Post a human-agent message (auto-translated to visitor's language). |
POST | /api/v1/conversations/:id/handback | conversations:handback | Release the takeover — AI resumes. |
Leads & tasks
| Method | Path | Scope | Purpose |
|---|---|---|---|
GET | /api/v1/leads | leads:read | List leads. Filters: widget_id, stage, temperature, assigned_to, updated_since. Cursor-paginated — see Pagination below. |
GET | /api/v1/leads/:id | leads:read | Full lead record (BANT, tags, assigned task history). |
POST | /api/v1/leads/:id | leads:write | Update fields: stage, temperature, tags, score, assignment, contact info. PATCH on the same path is also accepted (legacy alias). |
GET | /api/v1/tasks | tasks:read | Agent task log. Filters: widget_id, lead_id, status, type, updated_since. Mounted at /api/v1/activities too as a legacy alias. |
GET | /api/v1/tasks/:id | tasks:read | Full task record with execution + result data. Mounted at /api/v1/activities/:id too as a legacy alias. |
All update operations use POST on the resource path
(POST /api/v1/leads/:id). PATCH on the same path stays
accepted for one major version so existing integrations don’t break, but
POST is the canonical method going forward.
Resource type discriminator
Every resource response carries a read-only object field naming the
resource type ("lead", "conversation", "task",
"message"). List responses carry object: "list" at the
envelope and per-item object fields inside data[]. Use it to
deserialize polymorphic payloads (e.g., webhooks, mixed-resource responses).
{
"object": "lead",
"id": "clx...",
"stage": "qualified",
"temperature": "warm"
}
Pagination
List endpoints return a data array plus a has_more boolean and
a url field naming the endpoint. Use cursor pagination via
starting_after=<resource_id> — the API returns the next page of
items created before that cursor. limit is bounded at 200 (default 50).
GET /api/v1/leads?limit=20&starting_after=clx_abc123
{
"object": "list",
"data": [ { "object": "lead", "id": "clx_xyz789", ... }, ... ],
"has_more": true,
"url": "/api/v1/leads",
// Legacy fields surfaced alongside the new envelope for one major
// version. New consumers should read `data` + `has_more`.
"leads": [ /* same items as data[] */ ],
"total": 142,
"limit": 20,
"offset": 0
}
Naming conventions
Query parameters, request body fields, and response field names use
snake_case. Existing camelCase aliases on list filters
(widgetId, assignedTo, leadId, updatedSince) and on
PATCH bodies (jobTitle, assignedTo) continue to work for one
major version — new code should use snake_case.
Rate limits
Developer keys are rate-limited per key: 100 reads/min and 30 writes/min. Every authenticated response carries the current state in headers so well-behaved clients can self-throttle:
Quincer-RateLimit-Limit: 100
Quincer-RateLimit-Remaining: 87
Quincer-RateLimit-Reset: 1714435260
Over the limit returns 429 Too Many Requests with both the standard
Retry-After header (seconds until reset) and the
Quincer-RateLimit-* headers. The error body indicates the remaining count.
HTTP/1.1 429 Too Many Requests
Retry-After: 42
Quincer-RateLimit-Limit: 100
Quincer-RateLimit-Remaining: 0
Quincer-RateLimit-Reset: 1714435260
{
"error": "Rate limit exceeded. 0 read requests remaining. Retry after 42 seconds."
}
Webhooks
Subscribe to events under Dashboard → Settings → Webhooks. Quincer AI signs every
payload with HMAC-SHA256 using the secret you set. Requests include
Quincer-Signature (sha256=...), Quincer-Event, and
Quincer-Timestamp. The legacy X-Quincer-* variants are also sent
for one major version (RFC 6648 deprecated the X- prefix — existing
subscribers reading X-Quincer-* keep working unchanged).
Events
| Event | Fires when |
|---|---|
conversation.message_received | Visitor sends any message. Payload includes status (active or human_active) so subscribers know whether an external agent is driving. |
lead.created | A new lead record is captured. |
lead.updated | Any lead field changes. |
lead.stage_changed | Lead moves between pipeline stages. Payload includes both previous_stage (canonical) and previousStage (legacy alias). |
task.created | An agent task (follow-up, qualification, CRM sync, etc.) is scheduled. |
task.completed | A task finishes successfully. |
email.sent | A lead email goes out. |
email.draft_created | An AI-drafted email is ready for review. Email resources are managed via the dashboard — the payload is fully self-contained for downstream notification use. |
Verifying signatures
const signature = req.headers["quincer-signature"];
// (or "x-quincer-signature" if you set up your webhook before April 2026)
const expected = "sha256=" + crypto
.createHmac("sha256", process.env.QUINCER_WEBHOOK_SECRET)
.update(req.rawBody)
.digest("hex");
if (signature !== expected) {
return res.status(401).send("invalid signature");
}
OpenClaw integration
Quincer AI ships a first-class OpenClaw skill so any OpenClaw agent can take over Quincer AI conversations, query leads, and log activity. Setup takes about a minute:
- In Quincer AI, open Dashboard → Integrations → OpenClaw and click Connect OpenClaw. This creates a dedicated "OpenClaw" team member in your workspace and issues an API token bound to it.
- Download SKILL.md and drop it in
~/.openclaw/workspace/skills/quincer/. - Add the token to
~/.openclaw/openclaw.jsonunderskills.entries.quincer.env.QUINCER_API_KEY. - Restart the OpenClaw gateway. The
quincertool is now available.
OpenClaw actions (takeovers, replies) appear in your Quincer AI inbox under the OpenClaw team member, with their own avatar and audit trail — not as a generic "external agent."