Overview The Kanvo API is a REST API that allows external systems to read and write data in your Kanvo workspace. All requests must be authenticated with an API key generated in Settings → Advanced → API Keys .
All endpoints return JSON. The base URL for all API requests is:
text Copy
https://kanvocrm.com/api/v1The API follows conventional REST patterns — GET to read, POST to create, PATCH to update, and DELETE to remove.
Authentication All API requests must include your API key in the Authorization header as a Bearer token. Create and manage API keys at Settings → Advanced → API Keys inside your dashboard.
Each key has an assigned scope that controls what it can do:
Name Type Description readscope Fetch records, tasks, and schema. Cannot create, update, or delete. writescope All read permissions, plus create, update, and delete access for records and tasks. adminscope All write permissions, plus webhook management.
bash Copy
curl https://kanvocrm.com/api/v1/records \
-H "Authorization: Bearer kv_live_your_api_key_here"🔒 Keep your API keys secret. Never expose them in client-side code or public repositories. Rotate compromised keys immediately from the dashboard.
Errors & Status Codes All error responses use standard HTTP status codes and return a consistent JSON body.
Name Type Description 200OK Request succeeded. 400Bad Request Missing or invalid parameters. 401Unauthorized Missing or invalid API key. 403Forbidden API key lacks the required scope for this operation. 404Not Found Resource doesn't exist or belongs to a different workspace. 500Server Error Unexpected error. Contact support if it persists.
json Copy
{
"success": false,
"error": "Object type 'lead' not found"
}List endpoints are paginated. Use page and per_page query parameters.
Name Type Description pageinteger Page number, starting at 1. Defaults to 1. per_pageinteger Results per page. Defaults to 50, max 100.
json Copy
{
"success": true,
"data": [...],
"meta": {
"total": 237,
"page": 2,
"per_page": 50
}
}Records Records are the central data object in Kanvo — leads, jobs, estimates, clients, and any custom object types you create. Each record belongs to an object type identified by its slug, and optionally sits in a pipeline stage.
List records GET https://kanvocrm.com/api/v1/records
Name Type Description typestring Filter by object type slug (e.g. lead, job, estimate). searchstring Case-insensitive title search. assignee_iduuid Filter by assigned team member UUID. pageinteger Page number. Defaults to 1. per_pageinteger Results per page. Defaults to 50.
bash Copy
curl "https://kanvocrm.com/api/v1/records?type=lead&per_page=10" \
-H "Authorization: Bearer kv_live_..."json Copy
{
"success": true,
"data": [
{
"id": "b3e1a2f4-...",
"title": "Johnson Property - Lawn Care",
"object_type_id": "a1b2c3d4-...",
"stage_id": "f5e6d7c8-...",
"assignee_id": null,
"data": { "phone": "555-123-4567" },
"created_at": "2026-03-14T18:30:00.000Z",
"updated_at": "2026-03-14T18:30:00.000Z",
"object_types": { "name": "Lead", "slug": "lead", "icon": "👤" }
}
],
"meta": { "total": 84, "page": 1, "per_page": 10 }
}Get a record GET https://kanvocrm.com/api/v1/records/:id
bash Copy
curl "https://kanvocrm.com/api/v1/records/b3e1a2f4-..." \
-H "Authorization: Bearer kv_live_..."Create a record POST https://kanvocrm.com/api/v1/records
Name Type Description typerequired string Object type slug. Must match a type in your workspace (e.g. lead, job). titlestring Display name of the record. Defaults to 'Untitled'. dataobject Free-form JSONB data for any custom fields. assignee_iduuid UUID of the team member to assign this record to. stage_iduuid Direct stage UUID. Use this or pipeline + stage, not both. pipelinestring Pipeline name, slug, or UUID. Places the record in the first stage unless stage is also specified. stagestring Stage name, slug, or UUID within the specified pipeline.
bash Copy
curl -X POST https://kanvocrm.com/api/v1/records \
-H "Authorization: Bearer kv_live_..." \
-H "Content-Type: application/json" \
-d '{
"type": "lead",
"title": "Smith Residence - Spring Cleanup",
"pipeline": "main-sales",
"stage": "new",
"data": {
"phone": "555-999-0001",
"address": "42 Elm Street, Hartford CT"
}
}'Fires the record.created webhook event. If a pipeline stage is specified, also fires pipeline.stage_changed .
Update a record PATCH https://kanvocrm.com/api/v1/records/:id
Only include fields you want to change. Omitted fields are left untouched.
Name Type Description titlestring New display name. dataobject Replaces the entire data object. Fetch first if you need to merge. assignee_iduuid Reassign the record. Pass null to unassign. stage_iduuid Move to a new pipeline stage.
bash Copy
curl -X PATCH https://kanvocrm.com/api/v1/records/b3e1a2f4-... \
-H "Authorization: Bearer kv_live_..." \
-H "Content-Type: application/json" \
-d '{ "stage_id": "c9d0e1f2-..." }'Fires record.updated . If stage_id changed, also fires pipeline.stage_changed .
Delete a record DELETE https://kanvocrm.com/api/v1/records/:id
Soft-deletes the record by setting deleted_at. Excluded from all future list queries.
bash Copy
curl -X DELETE https://kanvocrm.com/api/v1/records/b3e1a2f4-... \
-H "Authorization: Bearer kv_live_..."json Copy
{ "success": true, "data": { "deleted": true, "id": "b3e1a2f4-..." } }Tasks Tasks can be standalone or linked to a specific record via record_id.
List tasks GET https://kanvocrm.com/api/v1/records/tasks
Name Type Description record_iduuid Filter to tasks attached to a specific record. assignee_iduuid Filter by assigned team member. completedboolean true returns completed tasks only; false returns open tasks only. pageinteger Page number. per_pageinteger Results per page.
bash Copy
curl "https://kanvocrm.com/api/v1/records/tasks?record_id=b3e1a2f4-...&completed=false" \
-H "Authorization: Bearer kv_live_..."Get a task GET https://kanvocrm.com/api/v1/records/tasks/:id
Create a task POST https://kanvocrm.com/api/v1/records/tasks
Name Type Description titlerequired string Task title. record_iduuid Link to a record. assignee_iduuid Assign to a team member. due_dateISO 8601 Due date, e.g. 2026-06-30. notesstring Optional notes or description.
bash Copy
curl -X POST https://kanvocrm.com/api/v1/records/tasks \
-H "Authorization: Bearer kv_live_..." \
-H "Content-Type: application/json" \
-d '{
"title": "Follow up on estimate",
"record_id": "b3e1a2f4-...",
"due_date": "2026-07-01"
}'Update a task PATCH https://kanvocrm.com/api/v1/records/tasks/:id
Name Type Description titlestring New title. completedboolean true to mark complete, false to reopen. assignee_iduuid Reassign. due_dateISO 8601 Update due date. notesstring Update notes.
Delete a task DELETE https://kanvocrm.com/api/v1/records/tasks/:id
Webhooks Webhooks let Kanvo push real-time event notifications to your server. Register an HTTPS endpoint and subscribe to specific events. Webhook management requires the admin scope.
List webhooks GET https://kanvocrm.com/api/v1/webhooks
json Copy
{
"success": true,
"data": [
{
"id": "wh_abc123",
"url": "https://your-app.com/hooks/kanvo",
"events": ["record.created", "pipeline.stage_changed"],
"is_active": true,
"last_triggered_at": "2026-06-17T14:20:00Z",
"last_status": 200,
"failure_count": 0,
"created_at": "2026-03-01T10:00:00Z"
}
]
}Register a webhook POST https://kanvocrm.com/api/v1/webhooks
Name Type Description urlrequired string HTTPS endpoint URL to receive event payloads. eventsrequired string[] Array of event names to subscribe to.
bash Copy
curl -X POST https://kanvocrm.com/api/v1/webhooks \
-H "Authorization: Bearer kv_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/hooks/kanvo",
"events": ["record.created", "record.updated", "pipeline.stage_changed"]
}'The signing secret is only returned once — in the response to this creation request. Store it securely to verify future payloads.
Delete a webhook DELETE https://kanvocrm.com/api/v1/webhooks?id=:id
bash Copy
curl -X DELETE "https://kanvocrm.com/api/v1/webhooks?id=wh_abc123" \
-H "Authorization: Bearer kv_live_..."Event reference All subscribable event names:
record.created record.updated record.deleted task.created task.updated task.deleted task.completed pipeline.stage_changed contract.created contract.signed form.submitted contact.created contact.updated
Payload signing Every delivery includes a X-Kanvo-Signature header — an HMAC-SHA256 signature of the raw request body using your endpoint's signing secret. Verify it to confirm the request originated from Kanvo.
javascript Copy
import { createHmac } from "crypto";
function verifyKanvoWebhook(rawBody, signature, secret) {
const expected = createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return `sha256=${expected}` === signature;
}
// In your request handler:
const rawBody = await request.text();
const sig = request.headers.get("x-kanvo-signature");
if (!verifyKanvoWebhook(rawBody, sig, process.env.KANVO_WEBHOOK_SECRET)) {
return new Response("Forbidden", { status: 403 });
}
const event = JSON.parse(rawBody);
console.log(event.event, event.data);Payload shape for all events:
json Copy
{
"event": "record.created",
"workspace_id": "ws_abc123",
"timestamp": "2026-06-17T14:20:00.000Z",
"data": {
"id": "b3e1a2f4-...",
"title": "Smith Residence",
"object_type_id": "...",
"stage_id": "...",
"assignee_id": null,
"data": {},
"created_at": "2026-06-17T14:20:00.000Z"
}
}Schema Fetch your workspace's object types and pipeline structure. Useful when building integrations that need to know which types and stages exist before creating records.
GET https://kanvocrm.com/api/v1/schema
bash Copy
curl https://kanvocrm.com/api/v1/schema \
-H "Authorization: Bearer kv_live_..."json Copy
{
"success": true,
"data": {
"object_types": [
{ "id": "a1b2...", "name": "Lead", "slug": "lead", "icon": "👤" },
{ "id": "c3d4...", "name": "Job", "slug": "job", "icon": "🔧" },
{ "id": "e5f6...", "name": "Estimate", "slug": "estimate", "icon": "📋" }
],
"pipelines": [
{
"id": "p1q2...",
"name": "Main Sales",
"slug": "main-sales",
"stages": [
{ "id": "s1t2...", "name": "New", "slug": "new", "position": 0 },
{ "id": "s3t4...", "name": "Contacted", "slug": "contacted", "position": 1 },
{ "id": "s5t6...", "name": "Won", "slug": "won", "position": 2 }
]
}
]
}
}