LeadTracker AI Developer
Version 1

Embed LeadTracker AI in your voice AI and automation stack.

Read live availability, create native bookings, synchronize CRM leads and inbound conversations, submit User Journey forms, and retain attribution, reminders, meeting links, and Telegram notifications in one system.

Base URL https://leadtrackerai.com/api/v1 Download OpenAPI 3.1
i
Built for server-to-server integrations

Use the Developer API from Vapi, Retell, Bland, n8n, Zapier code steps, or your own backend. Do not expose API keys in browser code or a client-side voice widget.

Authentication

Create an API key from LeadTracker AI app → Developer API. Keys are workspace-scoped, shown once, and use explicit permissions.

Workspace isolation

A key never accepts a workspace ID from the request. Its workspace is resolved from the credential.

Least privilege

Choose narrowly scoped scheduling, CRM, conversation, call, recording, script, voicemail, analytics, or workflow permissions for each integration.

Operational control

Set an expiry, inspect last use, rotate safely, and revoke a compromised key immediately.

Authorization header
curl https://leadtrackerai.com/api/v1/scheduling/brands \
  -H "Authorization: Bearer lt_live_..."
Alternative header
X-API-Key: lt_live_...
Write requests: send an Idempotency-Key header for every mutation. Booking reschedule/cancel and form funnel events now enforce replay-safe idempotency; duplicate keys replay the original result.
API keys are plan-limited: Starter allows 2, Team 5, Scale 15 (a free trial gets 1). Minting past the cap returns 402 quota_exceeded.
Metadata: GET /api/v1/openapi.json is public because the specification contains no credentials. /meta, /whoami, and /capabilities require a valid API key and report only safe contract, identity, and entitlement metadata.
Calendar OAuth: POST /scheduling/connections/{provider}/authorize creates durable, expiring state bound to the workspace, provider, client, redirect, nonce, and PKCE-S256 verifier. The callback accepts the provider's standard state and code redirect parameters; nonce proof comes from the cryptographically verified Google/Microsoft OIDC ID token, never from a client-supplied query nonce. The callback consumes state once; GET /scheduling/authorizations/{id} exposes status without state, verifier, provider credentials, or raw URLs. Disabled effects return deterministic simulation results.

SDKs and MCP

The JavaScript/TypeScript and Python SDKs are generated from the canonical OpenAPI document. They stay thin: authentication, request construction, safe retries, cursor pagination, job polling, approval status, request IDs, and structured errors are ergonomic client helpers; tenancy, scopes, entitlements, plans, and policy remain server-owned.

Install JavaScript / TypeScript
npm install @leadtracker/developer-api
Install Python
python -m pip install leadtracker-developer-api
Server-side JavaScript
import { LeadTrackerClient } from '@leadtracker/developer-api';

const api = new LeadTrackerClient({
  baseUrl: process.env.LEADTRACKER_API_BASE_URL ?? 'https://leadtrackerai.com/api/v1',
  bearerToken: process.env.LEADTRACKER_API_TOKEN,
});

for await (const lead of api.paginate('developer_crm_leads_list', {
  query: { limit: 50 },
})) {
  console.log(lead.id);
}
Retries and control flow: SDK retries are limited to safe reads and operations whose OpenAPI contract requires idempotency. For R3 or policy-evaluated R2 effects, call the server-provided plan, submit its exact operation_id to POST /approval-requests, then poll the returned request until an external human approval before executing. waitForJob/wait_for_job only poll public job status; waitForApproval/wait_for_approval never approves or bypasses a human decision.

MCP setup and authority

The MCP adapter is a separate HTTPS client over /api/v1. Configure a short-lived delegated token or least-privilege service credential in the MCP host; never give it a database connection, session cookie, platform-wide credential, or internal route access.

MCP host configuration
{
  "leadtracker": {
    "baseUrl": "https://leadtrackerai.com/api/v1",
    "tokenEnv": "LEADTRACKER_MCP_TOKEN",
    "scopes": ["leads:read", "jobs:read"]
  }
}

MCP tools are derived from the same x-mcp metadata and capability checks as the public API. Workspace tenancy, scope checks, entitlement gates, idempotency, If-Match, exact plan hashes, approvals, audit, and redaction still run on every request. Human approval ceremonies and OAuth callbacks remain outside direct MCP exposure; MCP may observe status but cannot self-approve.

Canonical operation inventory

The unified-authenticated v1 surface currently contains 579 operations (the existing 546-operation contract plus lead research/enrichment/bulk actions, conversation assignment and lifecycle controls, durable call queues, the supervisor live floor, server-owned marketing/SEO/calendar OAuth callbacks and status reads, exact integration/invitation/team/payment plans, and the generic immutable operation-plan endpoint). This list is kept in parity with the downloadable leadtracker-v1.yaml. Generic event webhook management is part of this public surface; legacy booking webhook configuration remains session-only and is documented separately below.

The MCP projection exposes 641 explicit tools: 575 direct public-operation tools plus 66 target-specific immutable plan tools. Every R2/R3 execute action has either its reviewed domain plan pair or a server-enforced generic exact-request plan; only the generic plan primitive itself and the three human OAuth callbacks are hidden from direct MCP registration.

GET/metaauthenticated
GET/whoamiauthenticated
GET/capabilitiesauthenticated
POST/operation-planstarget scope · R1 · immutable MCP plan
GET/scheduling/brandsscheduling:read
GET/scheduling/event-typesscheduling:read
GET/scheduling/availabilityscheduling:read
GET/scheduling/bookingsscheduling:read
GET/scheduling/bookings/{uid}scheduling:read
POST/scheduling/bookingsscheduling:write
POST/scheduling/bookings/{uid}/reschedulescheduling:write · R2 · Idempotency-Key
POST/scheduling/bookings/{uid}/cancelscheduling:write · R2 · Idempotency-Key
GET/scheduling/calendarsscheduling:read · R0 · cursor
POST/scheduling/calendarsscheduling:configure · R1 · Idempotency-Key
GET/scheduling/calendars/{id}scheduling:read · R0
PATCH/scheduling/calendars/{id}scheduling:configure · R1 · If-Match
POST/scheduling/calendars/{id}/archivescheduling:configure · R1 · If-Match
POST/scheduling/event-typesscheduling:configure · R1 · Idempotency-Key
GET/scheduling/event-types/{id}scheduling:read · R0
PATCH/scheduling/event-types/{id}scheduling:configure · R1 · If-Match
DELETE/scheduling/event-types/{id}scheduling:configure · R1 · If-Match
GET/scheduling/event-types/{id}/remindersscheduling:read · R0
PUT/scheduling/event-types/{id}/remindersscheduling:configure · R1 · If-Match
GET/scheduling/calendars/{id}/availability-rulesscheduling:read · R0
PUT/scheduling/calendars/{id}/availability-rulesscheduling:configure · R1 · If-Match
GET/scheduling/calendars/{id}/exceptionsscheduling:read · R0
POST/scheduling/calendars/{id}/exceptionsscheduling:configure · R1 · Idempotency-Key
PATCH/scheduling/calendars/{id}/exceptions/{exception_id}scheduling:configure · R1 · If-Match
DELETE/scheduling/calendars/{id}/exceptions/{exception_id}scheduling:configure · R1 · If-Match
GET/scheduling/time-offscheduling:read · R0
POST/scheduling/time-offscheduling:configure · R1 · Idempotency-Key
PATCH/scheduling/time-off/{id}scheduling:configure · R1 · If-Match
DELETE/scheduling/time-off/{id}scheduling:configure · R1 · If-Match
GET/scheduling/routing-poolsscheduling:read · R0 · cursor
POST/scheduling/routing-poolsscheduling:configure · R1 · Idempotency-Key
GET/scheduling/routing-pools/{id}scheduling:read · R0
PATCH/scheduling/routing-pools/{id}scheduling:configure · R1 · If-Match
PUT/scheduling/routing-pools/{id}/membersscheduling:configure · R1 · If-Match
GET/scheduling/connectionsscheduling:connections · R0
POST/scheduling/connections/{provider}/authorizescheduling:connections · R1 · Idempotency-Key
GET/scheduling/connections/{provider}/callbackpublic state/PKCE/OIDC-ID-token callback · MCP hidden
GET/scheduling/authorizations/{id}scheduling:connections · R0 · status only
POST/scheduling/connections/{id}/syncscheduling:connections · R2 · 202 · Idempotency-Key
PATCH/scheduling/connections/{id}/calendars/{calendar_id}scheduling:connections · R1 · If-Match
POST/scheduling/connections/{id}/disconnect/planscheduling:connections · R2 · Idempotency-Key
POST/scheduling/connections/{id}/disconnectscheduling:connections · R3 · If-Match
POST/scheduling/holdsscheduling:write · R1 · Idempotency-Key
POST/scheduling/bookings/{uid}/attendancescheduling:write · R1 · If-Match
GET/leads/searchleads:read
GET/leadsleads:read
GET/leads/{id}leads:read
GET/leads/{id}/taskstasks:read · R0 · cursor
POST/leads/{id}/researchleads:write · R2 · 202 · Idempotency-Key
POST/leads/{id}/enrichmentleads:write · R2 · 202 · Idempotency-Key
POST/leads/bulkleads:bulk · R1 · 202 · Idempotency-Key
POST/leadsleads:write
POST/leads/upsertleads:write
POST/leads/importsleads:bulk · R1 · 202 · Idempotency-Key
GET/leads/imports/{job_id}leads:bulk · R0
POST/leads/imports/{import_id}/commitleads:bulk · R1 · 202 · Idempotency-Key
POST/leads/exportsanalytics:export · R1 · 202 · Idempotency-Key
GET/leads/exports/{artifact_id}analytics:export · R0 · expires
GET/leads/exports/{artifact_id}/downloadanalytics:export · R0 · audited
PATCH/leads/{id}leads:write
POST/leads/{id}/archiveleads:archive
POST/leads/{id}/restoreleads:archive
GET/leads/{id}/notesleads:read
POST/leads/{id}/notesleads:write
PATCH/leads/{id}/notes/{note_id}leads:write
DELETE/leads/{id}/notes/{note_id}leads:write
GET/leads/{id}/activitiesleads:read
POST/leads/{id}/activitiesleads:write
POST/conversations/inboundconversations:write
POST/conversations/inbound-callsconversations:write
GET/conversationsconversations:read · R0 · cursor
GET/conversations/{id}conversations:read · R0
POST/conversations/{id}/assignconversations:write · R1 · Idempotency-Key
POST/conversations/{id}/closeconversations:write · R1 · Idempotency-Key
POST/conversations/{id}/reopenconversations:write · R1 · Idempotency-Key
GET/conversations/{id}/messagesconversations:read · R0 · cursor
GET/conversations/{id}/send-eligibilityconversations:send · R0
POST/conversations/{id}/messagesconversations:send · R2 · 202 · Idempotency-Key
POST/conversations/{id}/messages/scheduleconversations:send · R2 · 202 · Idempotency-Key
POST/conversations/{id}/messages/{message_id}/replyconversations:send · R2 · 202 · Idempotency-Key
GET/suppression/statusconversations:read · R0
POST/suppression/requestsconversations:write · R1 · Idempotency-Key
GET/callscalls:read · R0 · cursor
POST/callscalls:start · R2 · 201/202 · Idempotency-Key
GET/calls/{id}calls:read · R0
GET/calls/{id}/statuscalls:read · R0
POST/calls/{id}/statuscalls:control · R2 · Idempotency-Key
POST/calls/{id}/dtmfcalls:control · R2 · Idempotency-Key
POST/calls/{id}/hangupcalls:control · R2 · Idempotency-Key
POST/calls/{id}/dispositioncalls:control · R1 · Idempotency-Key
POST/calls/{id}/retrycalls:start · R2 · 201/202 · Idempotency-Key
GET/calls/{id}/recordingrecordings:read · R0 · signed expiry
GET/calls/{id}/transcriptrecordings:read · R0 · signed expiry
GET/calls/{id}/summarycalls:read · R0 · signed expiry
GET/scheduled-callscalls:read · R0 · cursor
POST/scheduled-callscalls:start · R1 · Idempotency-Key
PATCH/scheduled-calls/{id}calls:start · R1 · If-Match · Idempotency-Key
POST/scheduled-calls/{id}/completecalls:control · R1 · Idempotency-Key
POST/scheduled-calls/{id}/snoozecalls:control · R1 · Idempotency-Key
POST/scheduled-calls/{id}/skipcalls:control · R1 · Idempotency-Key
GET/call-queuescalls:read · R0 · cursor
POST/call-queuescalls:start · R1 · Idempotency-Key
GET/call-queues/{id}calls:read · R0
POST/call-queues/{id}/start-nextcalls:start · R2 · 202 · Idempotency-Key
POST/call-queues/{id}/pausecalls:control · R1 · If-Match · Idempotency-Key
POST/call-queues/{id}/resumecalls:control · R1 · If-Match · Idempotency-Key
GET/scriptsscripts:read · R0 · cursor
POST/scriptsscripts:write · R1 · Idempotency-Key
GET/scripts/{id}scripts:read · R0
PATCH/scripts/{id}scripts:write · R1 · If-Match · Idempotency-Key
POST/scripts/{id}/publishscripts:write · R1 · Idempotency-Key
POST/scripts/{id}/archivescripts:write · R1 · Idempotency-Key
POST/scripts/{id}/clonescripts:write · R1 · Idempotency-Key
GET/scripts/{id}/versionsscripts:read · R0 · cursor
GET/scripts/{id}/assignmentsscripts:read · R0
POST/scripts/{id}/assignscripts:write · R1 · Idempotency-Key
GET/voicemailsvoicemails:read · R0 · cursor
POST/voicemailsvoicemails:write · R1 · 201/202 · Idempotency-Key
GET/voicemails/{id}voicemails:read · R0
PATCH/voicemails/{id}voicemails:write · R1 · If-Match · Idempotency-Key
POST/voicemails/previewvoicemails:write · R2 · 200/202 · Idempotency-Key
POST/voicemails/{id}/previewvoicemails:read · R0 · Idempotency-Key
POST/voicemails/{id}/set-defaultvoicemails:write · R1 · Idempotency-Key
POST/voicemails/{id}/archivevoicemails:write · R1 · Idempotency-Key
GET/voicemails/{id}/versionsvoicemails:read · R0 · cursor
GET/campaignscampaigns:read · R0 · cursor
POST/campaignscampaigns:write · R1 · Idempotency-Key
GET/campaigns/{id}campaigns:read · R0
PATCH/campaigns/{id}campaigns:write · R1 · If-Match · Idempotency-Key
POST/campaigns/{id}/archivecampaigns:write · R1 · If-Match · Idempotency-Key
GET/campaigns/{id}/stepscampaigns:read · R0
PUT/campaigns/{id}/stepscampaigns:write · R1 · If-Match · Idempotency-Key
POST/campaigns/{id}/validatecampaigns:write · R1 · Idempotency-Key
POST/campaigns/{id}/activatecampaigns:execute · R2 · If-Match · Idempotency-Key
POST/campaigns/{id}/pausecampaigns:execute · R2 · If-Match · Idempotency-Key
POST/campaigns/{id}/resumecampaigns:execute · R2 · If-Match · Idempotency-Key
POST/campaigns/{id}/launch/plancampaigns:execute · R2 · plan · Idempotency-Key
POST/campaigns/{id}/launchcampaigns:execute · R3 · approved · 202 · Idempotency-Key
POST/campaigns/{id}/enrollmentscampaigns:execute · R2 · 202 · Idempotency-Key
GET/campaigns/{id}/enrollmentscampaigns:read · R0 · cursor
POST/campaigns/{id}/enrollments/{enrollment_id}/pausecampaigns:execute · R2 · If-Match · Idempotency-Key
POST/campaigns/{id}/enrollments/{enrollment_id}/resumecampaigns:execute · R2 · If-Match · Idempotency-Key
POST/campaigns/{id}/enrollments/{enrollment_id}/removecampaigns:execute · R2 · If-Match · Idempotency-Key
GET/campaigns/{id}/analyticsanalytics:read · R0
GET/workflowsworkflows:read · R0 · cursor
POST/workflowsworkflows:write · R1 · Idempotency-Key
GET/workflows/{id}workflows:read · R0
PATCH/workflows/{id}workflows:write · R1 · If-Match · Idempotency-Key
POST/workflows/{id}/cloneworkflows:write · R1 · Idempotency-Key
POST/workflows/{id}/archiveworkflows:write · R1 · If-Match · Idempotency-Key
PUT/workflows/{id}/nodesworkflows:write · R1 · If-Match · Idempotency-Key
POST/workflows/{id}/validateworkflows:write · R0 · Idempotency-Key
POST/workflows/{id}/activate/planworkflows:execute · R2 · plan · Idempotency-Key
POST/workflows/{id}/activateworkflows:execute · R2 · If-Match · Idempotency-Key
POST/workflows/{id}/deactivate/planworkflows:execute · R2 · plan · Idempotency-Key
POST/workflows/{id}/deactivateworkflows:execute · R2 · If-Match · Idempotency-Key
POST/workflows/{id}/trigger/planworkflows:trigger · R2 · plan · Idempotency-Key
POST/workflows/{id}/triggerworkflows:trigger · R2 · 202 · Idempotency-Key
POST/workflows/{id}/test-runworkflows:execute · R2 · simulated · 202 · Idempotency-Key
GET/workflows/{id}/runsworkflows:read · R0 · cursor
GET/workflow-runs/{id}workflows:read · R0
GET/workflow-runs/{id}/stepsworkflows:read · R0 · cursor
POST/workflow-runs/{id}/cancelworkflows:execute · R2 · Idempotency-Key
POST/workflow-runs/{id}/retryworkflows:execute · R2 · lineage · 202 · Idempotency-Key
GET/meetingsmeetings:read · R0 · cursor
POST/meetingsmeetings:write · R1 · 201 · Idempotency-Key
GET/meetings/{id}meetings:read · R0
PATCH/meetings/{id}meetings:write · R1 · If-Match · Idempotency-Key
POST/meetings/{id}/cancelmeetings:write · R2 · policy · If-Match
GET/meetings/{id}/inviteesmeetings:read · R0 · cursor
POST/meetings/{id}/inviteesmeetings:write · R2 · external timezone required · Idempotency-Key
DELETE/meetings/{id}/invitees/{invitee_id}meetings:write · R2 · Idempotency-Key
POST/meetings/{id}/join-tokenmeetings:write · R1 · short-lived grant
POST/meetings/{id}/endmeetings:write · R2 · artifacts · If-Match
GET/meetings/{id}/recordingsmeeting_artifacts:read · R0
GET/meetings/{id}/transcriptmeeting_artifacts:read · R0
GET/meetings/{id}/summarymeeting_artifacts:read · R0
GET/meetings/{id}/action-itemsmeeting_artifacts:read · R0
GET/meetings/{id}/send-notes/eligibilitymeetings:write · R0 · policy check
POST/meetings/{id}/send-notes/planmeetings:write · R2 · plan · Idempotency-Key
POST/meetings/{id}/send-notesmeetings:write · R2 · 202 · Idempotency-Key
GET/performance/leaderboardanalytics:read · R0 · cursor
GET/performance/reps/{user_id}analytics:read · R0
GET/coaching/templatescoaching:read · R0
POST/coaching/templatescoaching:write · R1 · Idempotency-Key
PATCH/coaching/templates/{id}coaching:write · R1 · If-Match · Idempotency-Key
GET/coaching/sessionscoaching:read · R0 · cursor
POST/coaching/sessionscoaching:write · R1 · Idempotency-Key
GET/coaching/sessions/{id}coaching:read · R0
POST/coaching/sessions/{id}/startcoaching:write · R1 · If-Match · Idempotency-Key
POST/coaching/sessions/{id}/completecoaching:write · R1 · If-Match · Idempotency-Key
POST/coaching/sessions/{id}/ai-insightscoaching:write · R2 · 202 · Idempotency-Key
GET/closer-assist/sessionscoaching:read · R0 · cursor
GET/closer-assist/sessions/{id}coaching:read · R0
GET/roleplay/nichesroleplay:read · R0
GET/roleplay/certificationsroleplay:read · R0
POST/roleplay/certifications/{mode}/startroleplay:execute · R1 · If-Match · Idempotency-Key
POST/roleplay/certifications/{mode}/completeroleplay:execute · R1 · If-Match · Idempotency-Key
POST/roleplay/sessionsroleplay:execute · R2 · simulated/202 · Idempotency-Key
GET/roleplay/sessionsroleplay:read · R0 · cursor
GET/roleplay/sessions/{id}roleplay:read · R0
POST/roleplay/sessions/{id}/messagesroleplay:execute · R2 · simulated/202 · Idempotency-Key
POST/roleplay/sessions/{id}/endroleplay:execute · R2 · If-Match · Idempotency-Key
GET/roleplay/sessions/{id}/scoreroleplay:read · R0
POST/roleplay/sessions/{id}/scoreroleplay:execute · R2 · Idempotency-Key
GET/supervisor/presencecoaching:read · R0 · owner/admin
GET/supervisor/agents/{user_id}coaching:read · R0 · owner/admin
POST/supervisor/agents/{user_id}/monitorcoaching:write · R2 · 202 · Idempotency-Key
POST/supervisor/agents/{user_id}/monitor/endcoaching:write · R2 · Idempotency-Key
GET/projectsprojects:read · R0 · offset
POST/projectsprojects:write · R1 · Idempotency-Key
GET/projects/{id}projects:read · R0 · project member
PATCH/projects/{id}projects:write · R1 · admin · If-Match · Idempotency-Key
POST/projects/{id}/archiveprojects:write · R2 · admin · If-Match · Idempotency-Key
POST/projects/{id}/restoreprojects:write · R2 · admin · If-Match · Idempotency-Key
GET/projects/{id}/membersprojects:read · R0 · member
PUT/projects/{id}/membersprojects:write · R2 · admin · If-Match · Idempotency-Key
GET/projects/{id}/columnsprojects:read · R0 · member
POST/projects/{id}/columnsprojects:write · R1 · admin · Idempotency-Key
PATCH/projects/{id}/columns/{column_id}projects:write · R1 · admin · If-Match · Idempotency-Key
POST/projects/{id}/columns/reorderprojects:write · R1 · admin · If-Match · Idempotency-Key
GET/projects/{id}/tasksprojects:read · R0 · offset
POST/projects/{id}/tasksprojects:write · R1 · Idempotency-Key
GET/projects/{id}/tasks/{task_id}projects:read · R0 · member
PATCH/projects/{id}/tasks/{task_id}projects:write · R1 · If-Match · Idempotency-Key
POST/projects/{id}/tasks/{task_id}/moveprojects:write · R1 · If-Match · Idempotency-Key
POST/projects/{id}/tasks/{task_id}/archiveprojects:write · R2 · If-Match · Idempotency-Key
PUT/projects/{id}/tasks/{task_id}/assigneesprojects:write · R1 · If-Match · Idempotency-Key
PUT/projects/{id}/tasks/{task_id}/labelsprojects:write · R1 · If-Match · Idempotency-Key
POST/projects/{id}/tasks/{task_id}/checklistprojects:write · R1 · Idempotency-Key
PATCH/projects/{id}/tasks/{task_id}/checklist/{item_id}projects:write · R1 · If-Match · Idempotency-Key
DELETE/projects/{id}/tasks/{task_id}/checklist/{item_id}projects:write · R1 · If-Match · Idempotency-Key
GET/projects/{id}/tasks/{task_id}/commentsprojects:read · R0 · member
POST/projects/{id}/tasks/{task_id}/commentsprojects:write · R1 · Idempotency-Key
POST/files/uploadsfiles:write · R1 · validated private intent · Idempotency-Key
GET/files/{id}files:read · R0 · tenant-owned metadata
GET/files/{id}/downloadfiles:read · R0 · resource-bound expiry
POST/files/{id}/archivefiles:write · R1 · If-Match · Idempotency-Key
GET/chat/userschat:read · R0
GET/chat/roomschat:read · R0
POST/chat/channelschat:write · R1 · admin · Idempotency-Key
GET/chat/channels/{id}chat:read · R0 · room access
PATCH/chat/channels/{id}chat:write · R1 · admin · If-Match · Idempotency-Key
POST/chat/channels/{id}/archivechat:write · R1 · admin · If-Match · Idempotency-Key
GET/chat/channels/{id}/memberschat:read · R0 · room access
PUT/chat/channels/{id}/memberschat:write · R1 · admin · Idempotency-Key
POST/chat/dmschat:write · R1 · human actor · Idempotency-Key
GET/chat/rooms/{id}/messageschat:read · R0 · room access · cursor
POST/chat/rooms/{id}/messageschat:write · R1 · client UUID · Idempotency-Key
PATCH/chat/messages/{id}chat:write · R1 · authorship · If-Match · Idempotency-Key
DELETE/chat/messages/{id}chat:write · R1 · authorship/admin · If-Match · Idempotency-Key
POST/chat/messages/{id}/reactionschat:write · R1 · Idempotency-Key
POST/chat/rooms/{id}/readchat:write · R1 · Idempotency-Key
GET/invoicesfinance:read · R0 · cursor
POST/invoicesinvoices:write · R1 · draft · Idempotency-Key
GET/invoices/{id}finance:read · R0
PATCH/invoices/{id}invoices:write · R1 · If-Match · Idempotency-Key
POST/invoices/{id}/issue/planinvoices:write · R2 · exact plan · Idempotency-Key
POST/invoices/{id}/issueinvoices:write · R2 · approved plan · If-Match · Idempotency-Key
POST/invoices/{id}/void/planinvoices:write · R3 · exact plan · Idempotency-Key
POST/invoices/{id}/voidinvoices:write · R3 · approved plan · If-Match · Idempotency-Key
GET/paymentsfinance:read · R0 · cursor
GET/payments/{id}finance:read · R0
POST/payments/record/planpayments:write · R2 · exact tenant payment plan · Idempotency-Key
POST/paymentspayments:write · R2 · hosted/tokenized · Idempotency-Key
POST/payments/{id}/refund/planpayments:write · R3 · exact plan · Idempotency-Key
POST/payments/{id}/refundpayments:write · R3 · approved plan · If-Match · Idempotency-Key
GET/subscriptionsfinance:read · R0 · cursor
GET/subscriptions/{id}finance:read · R0
GET/documentsfinance:read · R0 · cursor
POST/documentsdocuments:write · R1 · draft · Idempotency-Key
GET/documents/{id}finance:read · R0
POST/documents/{id}/send/plandocuments:write · R2 · exact plan · Idempotency-Key
POST/documents/{id}/senddocuments:write · R2 · approved plan · If-Match · Idempotency-Key
GET/commissionscommissions:read · R0 · cursor
GET/commissions/{id}commissions:read · R0
PATCH/commissions/{id}commissions:write · R1 · If-Match · Idempotency-Key
POST/commissions/{id}/approve/plancommissions:approve · R3 · exact plan
POST/commissions/{id}/approvecommissions:approve · R3 · separate approver · Idempotency-Key
POST/commissions/{id}/mark-paid/plancommissions:approve · R3 · exact plan
POST/commissions/{id}/mark-paidcommissions:approve · R3 · separate approver · Idempotency-Key
POST/commissions/bulk-mark-paid/plancommissions:approve · R3 · exact set/total plan
POST/commissions/bulk-mark-paidcommissions:approve · R3 · separate approver · Idempotency-Key
GET/phone-numbersphone_numbers:read · R0 · cursor
GET/phone-numbers/{id}phone_numbers:read · R0
POST/phone-numbers/searchphone_numbers:manage · R0 · provider read
POST/phone-numbers/purchases/planphone_numbers:manage · R3 · plan
POST/phone-numbers/purchasesphone_numbers:manage · R3 · approved · Idempotency-Key
POST/phone-numbers/{id}/health-checkphone_numbers:manage · R2 · provider read
GET/phone-numbers/{id}/health-historyphone_numbers:read · R0 · cursor
GET/phone-numbers/local-presence-policyphone_numbers:read · R0
PUT/phone-numbers/local-presence-policyphone_numbers:manage · R2 · If-Match · Idempotency-Key
POST/phone-numbers/{id}/replacement/planphone_numbers:manage · R3 · plan
POST/phone-numbers/{id}/replacementphone_numbers:manage · R3 · approved · If-Match
POST/phone-numbers/{id}/retire/planphone_numbers:manage · R3 · plan
POST/phone-numbers/{id}/retirephone_numbers:manage · R3 · approved · If-Match
POST/phone-numbers/{id}/quarantine/planphone_numbers:manage · R2 · plan
POST/phone-numbers/{id}/quarantinephone_numbers:manage · R2 · If-Match · Idempotency-Key
GET/receptionist/agentsreceptionist:read · R0 · cursor
POST/receptionist/agentsreceptionist:write · R1 · Idempotency-Key
GET/receptionist/agents/{id}receptionist:read · R0
PATCH/receptionist/agents/{id}receptionist:write · R1 · If-Match · Idempotency-Key
POST/receptionist/agents/{id}/activatereceptionist:write · R2 · If-Match
POST/receptionist/agents/{id}/deactivatereceptionist:write · R2 · If-Match
GET/receptionist/agents/{id}/config-versionsreceptionist:read · R0
GET/receptionist/routesreceptionist:read · R0 · cursor
PUT/receptionist/routes/{phone_number_id}receptionist:write · R2 · If-Match · Idempotency-Key
GET/receptionist/knowledge-sourcesreceptionist:read · R0 · cursor
POST/receptionist/knowledge-sourcesreceptionist:write · R1 · Idempotency-Key
GET/receptionist/knowledge-sources/{id}receptionist:read · R0
PATCH/receptionist/knowledge-sources/{id}receptionist:write · R1 · If-Match · Idempotency-Key
POST/receptionist/knowledge-sources/{id}/approvereceptionist:write · R2 · If-Match · Idempotency-Key
PUT/receptionist/agents/{id}/knowledgereceptionist:write · R1 · If-Match · Idempotency-Key
GET/receptionist/sessionsreceptionist:read · R0 · cursor
GET/receptionist/sessions/{id}receptionist:read · R0
GET/receptionist/sessions/{id}/transcriptrecordings:read · R0
POST/receptionist/sessions/{id}/handoffreceptionist:write · R2 · policy/usage gate
GET/receptionist/analyticsanalytics:read · R0
GET/formsforms:read · R0 · cursor
POST/formsforms:write · R1 · Idempotency-Key
GET/forms/{brand}forms:read
PATCH/forms/{brand}forms:write · R1 · If-Match · Idempotency-Key
POST/forms/{brand}/publishforms:write · R1 · If-Match · Idempotency-Key
POST/forms/{brand}/unpublishforms:write · R1 · If-Match · Idempotency-Key
POST/forms/{brand}/archiveforms:write · R1 · If-Match · Idempotency-Key
POST/forms/{brand}/cloneforms:write · R1 · Idempotency-Key
GET/forms/{brand}/revisionsforms:read · R0 · cursor
GET/forms/{brand}/revisions/{revision_id}forms:read · R0
GET/forms/{brand}/submissionsforms:submissions:read · R0 · cursor
GET/forms/{brand}/submissions/{id}forms:submissions:read · R0
GET/forms/{brand}/analyticsanalytics:read · R0
POST/forms/{brand}/eventsforms:submit · R1 · 204 · Idempotency-Key
POST/forms/{brand}/submissionsforms:submit
GET/public-linksforms:read · R0 · cursor
PATCH/public-links/{id}forms:write · R1 · If-Match · Idempotency-Key
GET/analytics/application-funnelanalytics:read
GET/analytics/dashboardanalytics:read · R0
GET/analytics/funnelanalytics:read · R0
GET/analytics/sourcesanalytics:read · R0 · cursor
GET/analytics/velocityanalytics:read · R0 · cursor
GET/analytics/attributionanalytics:read · R0 · cursor
GET/analytics/cohortsanalytics:read · R0 · cursor
GET/analytics/paid-performancemarketing:read · R0 · cursor
GET/analytics/creativesmarketing:read · R0 · cursor
GET/analytics/unit-economicsmarketing:read · R0 · cursor
GET/analytics/data-qualityanalytics:read · R0 · cursor
GET/analytics/attendanceanalytics:read · R0 · cursor
GET/analytics/leaderboardanalytics:read · R0 · cursor
POST/analytics/exportsanalytics:export · R1 · 202 · Idempotency-Key
POST/tracking/eventsmarketing:configure · R1 · 200/201 · Idempotency-Key
POST/tracking/conversion-eventsmarketing:configure · R1 · 200/201 · Idempotency-Key
POST/commerce/eventsmarketing:configure · R1 · 200/201 · Idempotency-Key
GET/tracking/events/{event_id}marketing:read · R0
GET/marketing/connectionsintegrations:read · R0 · cursor
POST/marketing/connections/{provider}/authorizeintegrations:write · R1 · hosted OAuth · Idempotency-Key
GET/marketing/connections/{provider}/callbackintegrations:write · R1 · state/PKCE/nonce-bound callback
GET/marketing/authorizations/{id}integrations:read · R0 · redacted status
GET/marketing/connections/{id}integrations:read · R0 · redacted
POST/marketing/connections/{id}/syncmarketing:configure · R2 · queued/simulated · Idempotency-Key
POST/marketing/connections/{id}/disconnect/planintegrations:write · R3 · exact plan · Idempotency-Key
POST/marketing/connections/{id}/disconnectintegrations:write · R3 · approved/simulated · Idempotency-Key
GET/marketing/goal-mappingsmarketing:read · R0 · cursor
PUT/marketing/goal-mappings/{provider}marketing:configure · R1 · Idempotency-Key
GET/marketing/consent-policiesmarketing:read · R0 · cursor
PUT/marketing/consent-policies/{brand_id}marketing:configure · R2 · Idempotency-Key
GET/marketing/recommendationsmarketing:read · R0 · cursor
GET/marketing/recommendations/{id}marketing:read · R0
POST/marketing/recommendations/{id}/reviewmarketing:configure · R1 · Idempotency-Key
POST/marketing/recommendations/{id}/execute/planmarketing:execute · R2 · quality/plan gate
POST/marketing/recommendations/{id}/executemarketing:execute · R2 · queued/simulated · Idempotency-Key
POST/marketing/actions/{id}/rollback/planmarketing:execute · R3 · prior-state plan
POST/marketing/actions/{id}/rollbackmarketing:execute · R3 · approved/simulated · Idempotency-Key
GET/marketing/actionsmarketing:read · R0 · cursor
GET/marketing/forecastsmarketing:read · R0 · freshness warnings · cursor
POST/marketing/forecastsmarketing:configure · R2 · queued/simulated · Idempotency-Key
GET/marketing/identity/unresolvedmarketing:read · R0 · cursor
POST/marketing/identity/correctionsmarketing:configure · R1 · redacted · Idempotency-Key
GET/growth/stategrowth:read · R0 · entitlement
GET/growth/brandsgrowth:read · R0 · cursor
POST/growth/brandsgrowth:write · R1 · Idempotency-Key
GET/growth/brands/{id}growth:read · R0
PATCH/growth/brands/{id}growth:write · R1 · If-Match
POST/growth/brands/{id}/assetsgrowth:write · R1 · bounded upload
DELETE/growth/brands/{id}/assets/{role}growth:write · R1 · If-Match
GET/growth/brands/{id}/topicsgrowth:read · R0 · cursor
POST/growth/brands/{id}/topicsgrowth:write · R1 · Idempotency-Key
POST/growth/brands/{id}/topics/suggestgrowth:generate · R2 · queued/simulated
GET/growth/postsgrowth:read · R0 · cursor
POST/growth/posts/generategrowth:generate · R2 · queued/simulated
GET/growth/posts/{id}growth:read · R0
PATCH/growth/posts/{id}growth:write · R1 · If-Match
POST/growth/posts/{id}/enhancegrowth:generate · R2 · queued/simulated
POST/growth/posts/{id}/approvegrowth:write · R1 · editorial only
POST/growth/posts/{id}/rejectgrowth:write · R1 · editorial only
POST/growth/posts/{id}/publish/plangrowth:publish · R3 · exact plan
POST/growth/posts/{id}/publishgrowth:publish · R3 · approved/simulated
POST/growth/posts/{id}/unpublish/plangrowth:publish · R2 · exact plan
POST/growth/posts/{id}/unpublishgrowth:publish · R2 · approved/simulated
GET/growth/metricsgrowth:read · R0
GET/growth/brands/{id}/pipeline-healthgrowth:read · R0
GET/growth/brands/{id}/index-healthseo:read · R0
GET/growth/brands/{id}/niche-coverageseo:read · R0
GET/growth/brands/{id}/cta-experimentsgrowth:read · R0
GET/growth/brands/{id}/ai-visibilityseo:read · R0 · versioned evidence
GET/growth/brands/{id}/backlinksseo:read · R0 · cursor
POST/growth/brands/{id}/backlinks/{backlinkId}/reviewgrowth:write · R1 · If-Match
GET/seo/connectionsseo:read · R0 · cursor
POST/seo/connections/google/authorizeseo:configure · R1 · hosted OAuth
GET/seo/connections/google/callbackseo:configure · R1 · state/PKCE/nonce-bound callback
GET/seo/authorizations/{id}seo:read · R0 · redacted status
POST/seo/connections/{id}/syncseo:configure · R2 · queued/simulated
GET/seo/opportunitiesseo:read · R0 · cursor
GET/seo/recommendationsseo:read · R0 · cursor
GET/seo/google-updatesseo:read · R0
POST/seo/recommendations/{id}/reviewseo:configure · R1 · If-Match
GET/signalssignals:read · R0 · cursor
GET/signals/{id}signals:read · R0
POST/signals/{id}/convert-to-leadleads:write · R1 · idempotent conversion
GET/prospect-packsleads:read · R0 · cursor
POST/prospect-packs/requests/planleads:bulk · R3 · exact criteria/cost plan
POST/prospect-packs/requestsleads:bulk · R3 · approved · queued/simulated
GET/prospect-packs/requests/{id}leads:read · R0 · job state
GET/usersusers:read · R0 · cursor
POST/users/invitations/planusers:write · R2 · exact team_ids plan + approval
POST/users/invitationsusers:write · R2 · 202 · Idempotency-Key
GET/users/{id}users:read · R0
PATCH/users/{id}users:write · R1 · If-Match · Idempotency-Key
POST/users/{id}/disable/planusers:write · R3 · exact ownership/workload plan
POST/users/{id}/disableusers:write · R3 · approved plan
POST/users/{id}/enableusers:write · R1 · If-Match · Idempotency-Key
GET/teamsteams:read · R0 · cursor
POST/teamsteams:write · R1 · Idempotency-Key
GET/teams/{id}teams:read · R0
PATCH/teams/{id}teams:write · R1 · If-Match · Idempotency-Key
PUT/teams/{id}/membersteams:write · R1 · tenant membership
POST/teams/{id}/archive/planteams:write · R2 · workload plan + approval
POST/teams/{id}/archiveteams:write · R2 · workload/If-Match
GET/workspaceworkspace:read · R0
PATCH/workspaceworkspace:write · R1 · If-Match · Idempotency-Key
GET/workspace/brandingworkspace:read · R0
PATCH/workspace/brandingworkspace:write · R1 · allowlisted HTTPS logo
GET/workspace/notification-policiesworkspace:read · R0 · typed
PUT/workspace/notification-policiesworkspace:write · R1 · typed destinations · If-Match or version · Idempotency-Key
GET/workspace/usageworkspace:read · R0
GET/workspace/entitlementsworkspace:read · R0
GET/workspacesworkspace:read · agency-owned cursor
POST/workspaces/planworkspace:write · R3 · exact plan
POST/workspacesworkspace:write · R3 · approved/simulated
GET/workspaces/{id}workspace:read · R0 · owned relationship
PATCH/workspaces/{id}workspace:write · R1 · If-Match
POST/workspaces/{id}/suspend/planworkspace:write · R3 · exact plan
POST/workspaces/{id}/suspendworkspace:write · R3 · approved/simulated
GET/domainsdomains:read · R0 · cursor
POST/domainsdomains:write · R1 · Idempotency-Key
GET/domains/{id}domains:read · R0
POST/domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key
POST/domains/{id}/remove/plandomains:write · R3 · exact plan
POST/domains/{id}/removedomains:write · R3 · approved plan · 202
GET/integrationsintegrations:read · R0 · opaque cursor · max 100
GET/integrations/{provider}integrations:read · R0
POST/integrations/{provider}/authorizeintegrations:write · R1 · server-bound OAuth state
POST/integrations/{provider}/authorize/completeintegrations:write · R1 · bounded/redacted completion
GET/integrations/{provider}/authorize/statusintegrations:read · R0 · redacted status
POST/integrations/{provider}/syncintegrations:write · R2 · 202 · Idempotency-Key
POST/integrations/{provider}/disconnect/planintegrations:write · R3 · exact plan
POST/integrations/{provider}/disconnectintegrations:write · R3 · approved plan · 202
GET/onboarding/stateworkspace:read · R0 · independent email_domains_cursor/integrations_cursor · max 100
PATCH/onboarding/business-profileworkspace:write · R1 · If-Match
POST/onboarding/texting-registrationworkspace:write · R3 · carrier plan/job
GET/onboarding/texting-registrationworkspace:read · R0
POST/onboarding/email-domainsdomains:write · R1 · Idempotency-Key
POST/onboarding/email-domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key
GET/settingsworkspace:read · R0 · typed/redacted
PATCH/settingsworkspace:write · R1 · If-Match
GET/billing/statebilling:read · R0
GET/billing/usagebilling:read · R0 · minor units
GET/billing/plansbilling:read · R0 · server catalog
POST/billing/plan-changes/previewbilling:write · R3 · exact plan · Idempotency-Key
POST/billing/plan-changesbilling:write · R3 · approved provider/simulation · 200 · Idempotency-Key
POST/billing/topups/previewbilling:write · R3 · exact plan · Idempotency-Key
POST/billing/topupsbilling:write · R3 · approved provider/simulation · 200 · Idempotency-Key
POST/billing/portal-sessionsbilling:write · R1 · provider-hosted URL · Idempotency-Key
GET/webhook-endpointsdeveloper:webhooks:read
POST/webhook-endpointsdeveloper:webhooks:write
GET/webhook-endpoints/{endpoint_id}developer:webhooks:read
PATCH/webhook-endpoints/{endpoint_id}developer:webhooks:write
DELETE/webhook-endpoints/{endpoint_id}developer:webhooks:write · R3 · policy · Idempotency-Key + If-Match
POST/webhook-endpoints/{endpoint_id}/rotate-secretdeveloper:webhooks:write
GET/webhook-endpoints/{endpoint_id}/deliveriesdeveloper:webhooks:read
GET/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}developer:webhooks:read
POST/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retrydeveloper:webhooks:write
POST/workflows/{workflowId}/triggerworkflows:trigger
GET/jobsdomain read scope
GET/jobs/{job_id}domain read scope
POST/jobs/{job_id}/canceloriginating execute scope
GET/approval-requestsapprovals:read
POST/approval-requestsapprovals:request
GET/approval-requests/{approval_request_id}approvals:read
POST/approval-requests/{approval_request_id}/cancelapprovals:request
GET/audit-eventsaudit:read
GET/audit-events/{audit_event_id}audit:read
GET/developer/scopesdeveloper:credentials:admin
GET/service-accountsdeveloper:credentials:admin
POST/service-accountsdeveloper:credentials:admin
GET/service-accounts/{service_account_id}developer:credentials:admin
PATCH/service-accounts/{service_account_id}developer:credentials:admin
POST/service-accounts/{service_account_id}/rotatedeveloper:credentials:admin
POST/service-accounts/{service_account_id}/disabledeveloper:credentials:admin
POST/service-accounts/{service_account_id}/enabledeveloper:credentials:admin
GET/service-accounts/{service_account_id}/credentialsdeveloper:credentials:admin
POST/service-accounts/{service_account_id}/credentialsdeveloper:credentials:admin
DELETE/service-accounts/{service_account_id}/credentials/{credential_id}developer:credentials:admin
GET/tagstags:read
POST/tagstags:write · R1 · Idempotency-Key
GET/tags/{tag_id}tags:read
PATCH/tags/{tag_id}tags:write · R1 · If-Match
POST/tags/{tag_id}/archivetags:write · R1 · If-Match
GET/leads/{lead_id}/tagstags:read
PUT/leads/{lead_id}/tagstags:write · R1 · Idempotency-Key
GET/deals/{deal_id}/tagstags:read
PUT/deals/{deal_id}/tagstags:write · R1 · Idempotency-Key
GET/custom-fieldscustom_fields:read
POST/custom-fieldscustom_fields:write · R1 · Idempotency-Key
GET/custom-fields/{field_id}custom_fields:read
PATCH/custom-fields/{field_id}custom_fields:write · R1 · If-Match
POST/custom-fields/{field_id}/archivecustom_fields:write · R1 · If-Match
GET/leads/{lead_id}/custom-fieldscustom_fields:read
PUT/leads/{lead_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key
GET/deals/{deal_id}/custom-fieldscustom_fields:read
PUT/deals/{deal_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key
GET/smart-lists/filter-schemasmart_lists:read
GET/smart-listssmart_lists:read · cursor
POST/smart-listssmart_lists:write · R1 · Idempotency-Key
POST/smart-lists/previewsmart_lists:write · R0 · Idempotency-Key
GET/smart-lists/{id}smart_lists:read
PATCH/smart-lists/{id}smart_lists:write · R1 · If-Match
DELETE/smart-lists/{id}smart_lists:write · R1 · If-Match
GET/smart-lists/{id}/leadsleads:read · cursor
GET/pipelinespipelines:read
POST/pipelinespipelines:write · R1 · Idempotency-Key
GET/pipelines/{id}pipelines:read
PATCH/pipelines/{id}pipelines:write · R1 · If-Match
POST/pipelines/{id}/archivepipelines:write · R1 · If-Match
POST/pipelines/{id}/stagespipelines:write · R1 · Idempotency-Key
PATCH/pipelines/{id}/stages/{stage_id}pipelines:write · R1 · If-Match
POST/pipelines/{id}/stages/{stage_id}/archivepipelines:write · R1 · If-Match
POST/pipelines/{id}/stages/reorderpipelines:write · R1 · If-Match
GET/dealsdeals:read · R0 · cursor
POST/dealsdeals:write · R1 · Idempotency-Key
GET/deals/{id}deals:read · R0
PATCH/deals/{id}deals:write · R1 · If-Match
POST/deals/{id}/movedeals:write · R1 · If-Match
POST/deals/{id}/wondeals:write · R1 · If-Match
POST/deals/{id}/lostdeals:write · R1 · If-Match
POST/deals/{id}/reopendeals:write · R1 · If-Match
POST/deals/{id}/archivedeals:archive · R1 · If-Match
POST/deals/{id}/restoredeals:archive · R1 · If-Match
GET/deals/{id}/activitiesdeals:read · R0 · cursor
POST/deals/{id}/activitiesdeals:write · R1 · Idempotency-Key
GET/pipelines/{id}/boarddeals:read · R0 · cursor
GET/pipelines/{id}/forecastanalytics:read · R0
GET/taskstasks:read · R0 · cursor
POST/taskstasks:write · R1 · Idempotency-Key
GET/tasks/{id}tasks:read · R0
PATCH/tasks/{id}tasks:write · R1 · If-Match
POST/tasks/{id}/completetasks:write · R1 · If-Match
POST/tasks/{id}/reopentasks:write · R1 · If-Match
POST/tasks/{id}/archivetasks:write · R1 · If-Match
DELETE/tasks/{id}tasks:write · R1 · If-Match
GET/task-summarytasks:read · R0
GET/calendar/entriestasks:read · R0 · cursor
GET/calendar/entries/{id}tasks:read · R0
POST/calendar/entriestasks:write · R1 · Idempotency-Key
PATCH/calendar/entries/{id}tasks:write · R1 · If-Match
DELETE/calendar/entries/{id}tasks:write · R1 · If-Match

Calls and voice assets

Calls are workspace-scoped durable intents. A start request persists its operation and job before any Telnyx request, then applies DNC, international, caller-ID, usage, and human/policy gates. When external effects are disabled, the same request returns a deterministic simulation and never contacts a provider.

i
Protected artifacts

Recording, transcript, and summary reads require their dedicated scopes. Recordings are exposed only through resource-bound signed access with a bounded expiry; raw provider URLs and storage keys are never returned. Expired or mismatched grants fail closed.

Scopes: call lifecycle uses calls:read, calls:start, and calls:control; artifacts use recordings:read; script and voicemail assets use their matching scripts:* and voicemails:* scopes. Mutations require replay-safe Idempotency-Key headers.

Call queues and supervisor floor

Call queues persist ordered lead work in the workspace and use the same call policy gates as direct dialing. Queue start creates durable operation/job intent before a provider request; external-effects-disabled environments return deterministic simulations.

i
Concurrency and live-floor controls

Queue pause/resume requires the current If-Match version. Supervisor presence and monitor sessions are owner/admin-only; monitoring requires explicit consent, a short-lived resource-bound token, and replay-safe start/end mutations.

Scopes and retries: queues use calls:read, calls:start, and calls:control; supervisor reads and monitor controls use coaching:read/coaching:write. Every mutation requires Idempotency-Key; no raw provider URL, storage key, or monitor credential is returned.

Phone numbers and AI receptionist

Phone inventory and receptionist configuration are workspace-owned resources. Phone purchases, replacements, and retirement are two-step R3 operations: create a server-side plan, then execute only the exact approved plan. Health checks, DNC/plan/usage gates, and disabled-effects simulation are enforced by the same service boundary used by the app.

i
Tenant-safe routing

Receptionist routes accept only phone numbers, calendars, event types, and knowledge sources owned by the authenticated workspace. Transcript reads require recordings:read; handoffs require paid-plan and AI-minute allowance checks and are simulated when external effects are disabled.

Scopes: use phone_numbers:read/phone_numbers:manage for inventory and lifecycle; receptionist:read/receptionist:write for agents, routes, knowledge, and sessions; recordings:read for receptionist transcripts. Every write is replay-safe and returns only public resource/job references.

Campaigns

Campaign definitions use the same typed steps, merge-field validation, suppression rules, audience compliance checks, usage gates, and trusted worker path as the application. Create a launch plan before execution: the server binds the exact audience, resource versions, projected usage/spend, and plan hash to an expiring operation.

i
Audience-bound execution

Launch accepts only the server-issued operation reference and exact plan context. Thresholds create an approval request; modified campaign steps, versions, audience, or spend invalidate the plan. The API queues a durable job and disabled-effects mode deterministically simulates worker effects without contacting a provider.

Scopes: use campaigns:read for definitions, steps, and enrollments; analytics:read for campaign analytics; campaigns:write for definition changes; and campaigns:execute for activation, audience enrollment, pause/resume, and launch. Every mutation requires Idempotency-Key; versioned changes also require If-Match.

Meetings, coaching, and roleplay

Meetings are workspace-owned resources with explicit host/participant visibility. Create and control them through meetings:write; read scoped recording, transcript, summary, and action-item projections through meeting_artifacts:read. Join grants are one-way, audience-bound, hashed at rest, and expire within the server's short TTL.

i
Durable and simulation-safe

Meeting endings, note delivery, AI coaching insights, and synthetic roleplay create durable job/event intent before any provider work. With external effects disabled, jobs and responses are deterministic simulations and no provider or raw storage URL is exposed.

Scopes: meetings use meetings:read/meetings:write; artifacts use meeting_artifacts:read; performance uses analytics:read; coaching uses coaching:read/coaching:write; and synthetic practice uses roleplay:read/roleplay:execute. Every mutation is replay-safe; If-Match is required for versioned state transitions.

Projects and private files

Projects expose tenant-owned boards, columns, tasks, checklists, comments, and membership. A held workspace scope is necessary but not sufficient: reads require project membership, while project writes and membership changes additionally require project-admin role checks.

i
Private storage by construction

File upload intents validate plain names, allowlisted MIME types, a 10 MiB maximum, checksums, and project/task ownership. File responses contain public metadata only; storage keys and provider credentials never cross the API boundary.

Scopes: use projects:read/projects:write for boards and tasks, and files:read/files:write for file metadata and lifecycle. Mutations require Idempotency-Key; versioned writes require If-Match. Download grants expire and cannot be replayed across workspaces, file versions, or actors.

Team chat

Team chat exposes workspace channels, direct messages, reactions, and read markers through the same credential and live-workspace gates as the rest of the Developer API. Room membership and message authorship remain additional authorization checks after workspace scope.

i
Actor identity is explicit

Human messages identify the authenticated workspace user. Service-account messages identify the credential actor and display name; request bodies cannot supply a human sender or impersonate another actor.

Scopes and retries: use chat:read for users, rooms, members, and message reads; use chat:write for channel, DM, message, reaction, and read-marker mutations. Every write requires Idempotency-Key; channel/message edits and deletes also require If-Match. Message sends require a caller-stable client_message_id, and attachment references must be actor-owned uploaded references with an allowlisted MIME type and size.

Finance core

Finance core exposes tenant-owned invoices, payments, customer subscriptions, and document lifecycles. Amounts are always integer minor units paired with an exact ISO-4217 currency; floating-point money is never accepted.

i
Token-safe provider flows

Raw card and bank-account details are rejected before policy or persistence. Payment recording accepts only an existing tokenized method or opaque provider/hosted reference, and public responses omit hashes, tokens, provider metadata, and storage keys.

Scopes and plans: reads use finance:read; drafts use invoices:write or documents:write; payment records and refunds use payments:write. Every mutation requires Idempotency-Key. Issue, void, refund, and send executions require the exact server-generated plan, approval/policy context, and current If-Match version. When external effects are disabled, provider work is a deterministic simulation and no provider URL or raw storage key is returned.

Commissions

Commission entries are tenant-owned calculations represented in integer minor units and exact ISO-4217 currencies. Corrections and payout controls never accept raw card or bank data.

i
Exact R3 payout controls

Corrections are owner/admin-only and require If-Match. Approval and mark-paid plans bind the workspace, entry IDs, versions, calculation hashes, total, and currency. Execution requires a separate approver; stale plans and approval mismatches fail closed.

Scopes and retries: use commissions:read for reads, commissions:write for corrections, and commissions:approve for R3 plans/execution. Every mutation requires Idempotency-Key. Disabled effects return deterministic simulated jobs/events and never expose provider URLs, storage keys, card data, or bank data.

Tasks and personal/team calendars

CRM tasks remain backed by lead_tasks; project work is a separate resource. Assignments are checked against active human workspace membership, while service accounts remain creator identities only.

i
Replay-safe concurrency

Send Idempotency-Key on every mutation and the current ETag as If-Match on updates, state changes, and deletes. Task collections and calendar entry lists return opaque cursors.

Bounded CRM imports and exports

Move CRM data through bounded, tenant-safe jobs. Imports accept only CSV or TSV files with explicit allowlisted mappings; exports select an explicit public lead projection and produce an expiring artifact.

i
Preview first, commit deliberately

Import validation returns a five-row preview and field-level errors in a 202 job response. Commit is a separate replay-safe job and resolves ownership from the authenticated actor or active workspace owner/admin; callers cannot supply a user ID.

POST/leads/importsleads:bulk · R1 · 202

Send multipart/form-data with a required file and optional JSON mappings object. Files are limited to 10 MiB, 64 columns, and 1000 data rows. Unknown headers, destinations, duplicate headers, and duplicate mappings fail closed.

FieldTypeContract
file requiredCSV/TSVUTF-8 upload; raw bytes are parsed and not retained by the public response.
mappingsJSON objectSource header to an allowlisted CRM field such as contact_email or contact_name.
Idempotency-Key requiredheader8–200 URL-safe characters; replay returns the original 202 response.
Request
curl https://leadtrackerai.com/api/v1/leads/imports \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY" \
  -H "Idempotency-Key: crm-import-20260815-01" \
  -F "file=@leads.csv;type=text/csv" \
  -F 'mappings={"email":"contact_email","name":"contact_name"}'
202 response
{
  "data": {
    "job_id": "job_01JIMPORT",
    "status": "succeeded",
    "resource_type": "lead_import",
    "resource_id": "imp_01JIMPORT",
    "simulated": true,
    "import": { "counts": { "rows": 1, "valid": 1 } }
  }
}
Preview errors: invalid_file, unsupported_media_type, unknown_field, duplicate_header, duplicate_mapping, missing_name, missing_identity, invalid_email, invalid_phone, invalid_stage, and bounded row/file limit errors are returned with safe details.
POST/leads/imports/{import_id}/commitleads:bulk · R1 · 202

Send an empty JSON object with a new Idempotency-Key to queue the commit. The worker uses workspace-qualified email/phone duplicate checks, tenant RLS, and actor-derived ownership. A second request with the same key replays the original job envelope; a different payload with that key returns 409 idempotency_key_reused.

POST/leads/exportsanalytics:export · R1 · 202

Provide 1–1000 explicit lead IDs and 1–32 fields from the public projection. The query is always workspace-qualified. Only bounded CSV is supported; generated files are capped at 8 MiB and stored as expiring artifact metadata.

Request
curl https://leadtrackerai.com/api/v1/leads/exports \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY" \
  -H "Idempotency-Key: crm-export-20260815-01" \
  -H "Content-Type: application/json" \
  -d '{"lead_ids":[2194],"fields":["id","name","email","company"],"format":"csv"}'
202 response
{
  "data": {
    "job_id": "job_01JEXPORT",
    "status": "queued",
    "resource_id": "art_01JEXPORT",
    "artifact": { "status": "pending", "download_url": null }
  }
}
Explicit projection: the response and artifact metadata never expose workspace_id, credential data, internal provider columns, storage keys, raw URLs, or an unbounded Excel buffer.
GET/leads/exports/{artifact_id}analytics:export · R0

Inspect status, projection, row and byte counts, checksum, simulated mode, download count, and expiry. The artifact is workspace-scoped and returns 410 artifact_expired after expiry.

GET/leads/exports/{artifact_id}/downloadanalytics:export · R0 · audited

The download request is authenticated, workspace-qualified, expiry-checked, and audit-recorded. It returns explicit artifact metadata while the bounded artifact worker handles storage delivery; pending artifacts return 409 resource_not_ready.

Booking brands

Choose the brand before reading availability or creating a booking. Each workspace exposes its own tenant-configured brands and routes person-less bookings through that brand's Calendar Round Robin; the API does not use a fixed list of product brands.

1
Always send the returned numeric brand_id

Call GET /scheduling/brands, select the intended brand, then use its id as brand_id with one of that brand's event_type_ids. Send the same pair and one stable routing_key to availability and booking creation.

GET/scheduling/brandsscheduling:read

Returns only active booking brands owned by the API key's workspace. identifier is the human-readable slug shown in the app; id is the numeric value to send as brand_id.

Request
curl https://leadtrackerai.com/api/v1/scheduling/brands \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY"
200 response
{
  "data": [{
    "id": 17,
    "identifier": "acme-consulting",
    "name": "Acme Consulting",
    "event_type_ids": [42],
    "routing_mode": "round_robin",
    "active_calendar_count": 2
  }]
}
Validated as one pair: a brand from another workspace, an unknown ID, or an event type assigned to another brand is rejected before a lead, room, calendar event, or email is created. Brand names are never hard-coded by the API.

Event types

Fetch the booking types available in the authenticated workspace. Every event type includes its allowed brand records; use a matching brand.id and event type ID when retrieving availability or creating a booking.

GET/scheduling/event-typesscheduling:read

Returns active event types and their scheduling constraints.

Request
curl https://leadtrackerai.com/api/v1/scheduling/event-types \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY"
200 response
{
  "data": [{
    "id": 42,
    "title": "Discovery Call",
    "duration_minutes": 30,
    "timezone": "America/New_York",
    "booking_window_days": 14,
    "brands": [{
      "id": 17,
      "identifier": "acme-consulting",
      "name": "Acme Consulting"
    }]
  }]
}

Availability

Slots are returned as UTC ISO 8601 timestamps. Convert them to the caller's local time in your voice experience, then pass the selected UTC start time when booking.

GET/scheduling/availabilityscheduling:read
Query parameterTypeDescription
brand_id requiredintegerThe intended brand's id from /scheduling/brands. It must allow the selected event type.
event_type_id requiredintegerAn ID returned by the event types endpoint.
start_date requiredYYYY-MM-DDFirst calendar date to inspect.
end_date requiredYYYY-MM-DDLast calendar date to inspect. Ranges may be up to 31 days.
routing_keystringA stable call/conversation ID (8-200 URL-safe characters). Reuse it when creating the booking so availability and booking stay on the same round-robin calendar. If omitted, the response generates one that you must reuse.
closer_user_idintegerOptional known LeadTracker user. If that active closer belongs to the brand pool, they remain pinned instead of consuming a round-robin turn.
Request
curl "https://leadtrackerai.com/api/v1/scheduling/availability?brand_id=17&event_type_id=42&start_date=2026-08-17&end_date=2026-08-21&routing_key=vapi-call-6d9f08b2" \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY"
200 response
{
  "data": {
    "event_type_id": 42,
    "routed_event_type_id": 81,
    "brand_id": 17,
    "brand": { "id": 17, "identifier": "acme-consulting", "name": "Acme Consulting" },
    "routing_mode": "round_robin",
    "routing_key": "vapi-call-6d9f08b2",
    "timezone": "America/New_York",
    "slots": [{
      "start": "2026-08-17T14:00:00.000Z",
      "end": "2026-08-17T14:30:00.000Z"
    }]
  }
}

Create a booking

LeadTracker AI validates the brand/event-type pair, creates a CRM lead or links an exact existing identity, performs a final conflict check, creates the correctly branded native meeting room, writes the connected calendar event, starts reminder delivery, and sends the normal Telegram booking notification. Create-style booking intake never edits an existing lead’s contact, location, or timezone; conflicting identity details return 409 lead_identity_conflict.

POST/scheduling/bookingsscheduling:write
Body fieldTypeDescription
brand_id requiredintegerThe intended brand's id from /scheduling/brands. Reuse the value sent to availability.
event_type_id requiredintegerThe active LeadTracker AI event type.
routing_keystringThe exact key used for availability. When booking directly without an availability lookup, omit it and the Idempotency-Key becomes the round-robin key.
closer_user_idintegerOptional known closer override. Otherwise an existing active lead closer is preserved, then the brand round robin is used.
start requiredISO 8601 UTCThe exact slot start returned by availability.
attendee.name requiredstringProspect name.
attendee.email or attendee.phone requiredstringAt least one contact method. Phone is recommended for SMS reminders.
attendee.timezone requiredCanonical IANA timezoneFor example America/Chicago or Asia/Dubai. Fixed aliases such as EST and numeric offsets are rejected.
sourcestringYour integration label, such as vapi or retell.
external_referencestringYour call, conversation, or booking identifier for reconciliation.
metadataobjectOptional integration context, stored with the booking. Maximum 16 KB.
Request
curl -X POST https://leadtrackerai.com/api/v1/scheduling/bookings \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY" \
  -H "Idempotency-Key: vapi-call-6d9f08b2" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": 17,
    "event_type_id": 42,
    "routing_key": "vapi-call-6d9f08b2",
    "start": "2026-08-17T14:00:00.000Z",
    "attendee": {
      "name": "Avery Chen",
      "email": "avery@northstar.example",
      "phone": "+15125550123",
      "timezone": "America/Chicago",
      "company": "Northstar Health",
      "location": "Austin, TX"
    },
    "source": "vapi",
    "external_reference": "call_01J123",
    "metadata": { "agent": "inbound-sales" }
  }'
201 Created
Response
{
  "data": {
    "id": "ltbk_9c7bd1...",
    "status": "scheduled",
    "brand_id": 17,
    "brand": { "id": 17, "identifier": "acme-consulting", "name": "Acme Consulting" },
    "routing_mode": "round_robin",
    "routing_key": "vapi-call-6d9f08b2",
    "start": "2026-08-17T14:00:00.000Z",
    "end": "2026-08-17T14:30:00.000Z",
    "meeting_url": "https://leadtrackerai.com/meet/...",
    "lead_id": 2194
  },
  "duplicate": false,
  "lead_created": true
}
i
Two different emails are sent

The customer confirmation is sent to attendee.email. A separate internal message labelled “Organizer notification” is sent to the exact connected calendar account (falling back to the host's login email only when needed). Seeing prospect details in the organizer message does not mean the customer confirmation was sent to the organizer.

Routing and retries: use one call/conversation ID as both routing_key and Idempotency-Key. Availability and booking then stay pinned to one native calendar, and a replay returns 200 with duplicate: true instead of advancing the pool or creating another appointment.

List bookings

Use the collection endpoint to reconcile bookings created by the API or the LeadTracker AI app. Results are always limited to the authenticated API key’s workspace and can be narrowed by attendee email, status, or the legacy from/to date filters.

GET/scheduling/bookingsscheduling:read
Query fieldTypeDescription
emailemailExact attendee email filter.
statusstringBooking status filter, such as scheduled or cancelled.
fromstringLower date/time bound in the existing scheduler filter format.
tostringUpper date/time bound in the existing scheduler filter format.
Request
curl "https://leadtrackerai.com/api/v1/scheduling/bookings?status=scheduled" \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY"
200 response
{
  "data": [{
    "id": "ltbk_9c7bd1...",
    "status": "scheduled",
    "brand_id": 17,
    "event_type_id": 42,
    "start": "2026-08-17T14:00:00.000Z",
    "end": "2026-08-17T14:30:00.000Z",
    "attendee": { "name": "Avery Chen", "email": "avery@example.com" }
  }]
}
Legacy collection: this endpoint uses bounded filters rather than cursor pagination for compatibility. Use the single-booking endpoint when reconciling a known booking UID.

Read a booking

GET/scheduling/bookings/{booking_id}scheduling:read

Use the LeadTracker AI booking ID returned when an appointment is created. The record is only accessible within the API key's workspace.

Request
curl https://leadtrackerai.com/api/v1/scheduling/bookings/ltbk_9c7bd1... \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY"

Reschedule a booking

POST/scheduling/bookings/{booking_id}/reschedulescheduling:write

LeadTracker AI validates the requested slot again, updates the connected calendar event and native meeting, and re-evaluates reminder delivery.

Request body
{
  "start": "2026-07-16T16:00:00.000Z",
  "reason": "Caller requested a later time"
}

Cancel a booking

POST/scheduling/bookings/{booking_id}/cancelscheduling:write

Cancelling removes the provider event when connected, stops pending reminders, clears the active appointment from the CRM lead, and retains the booking history.

Request body
{
  "reason": "Prospect cancelled during the call"
}

Leads

Use the CRM endpoints to identify a caller, create or update a contact, and add durable notes or activities. They expose a deliberately small CRM-safe field set: no deletion, assignment, campaign enrollment, billing, or bulk export operations are available.

GET/leadsList up to 50 recent leads
GET/leads/search?q=... | email=... | phone=...Find a specific lead
GET/leads/{lead_id}Read one lead
POST/leads | /leads/upsertCreate or match a lead
PATCH/leads/{lead_id}Update CRM-safe fields
POST/leads/{lead_id}/notes | /activitiesAdd CRM history
POST/leads/upsertleads:write

Provide an email or phone to match an existing record. Every lead mutation requires Idempotency-Key.

Request
curl -X POST https://leadtrackerai.com/api/v1/leads/upsert \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY" \
  -H "Idempotency-Key: voice-call-01JABC" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Avery Chen",
    "email": "avery@northstar.example",
    "phone": "+15125550123",
    "company": "Northstar Health",
    "timezone": "America/Chicago",
    "source": "retell",
    "attribution": { "utm_source": "partner" }
  }'

Tags and custom fields

CRM taxonomy is workspace-scoped and uses the same API-key or delegated OAuth boundary as leads. Reads require a tags:read or custom_fields:read scope; mutations require the matching write scope, an Idempotency-Key, and If-Match on versioned definition updates and archives.

GET/tagstags:read · R0 · cursor
POST/tagstags:write · R1 · Idempotency-Key
GET/tags/{tag_id}tags:read · R0
PATCH/tags/{tag_id}tags:write · R1 · Idempotency-Key + If-Match
POST/tags/{tag_id}/archivetags:write · R1 · Idempotency-Key + If-Match
GET/leads/{lead_id}/tagstags:read · R0
PUT/leads/{lead_id}/tagstags:write · R1 · Idempotency-Key
GET/deals/{deal_id}/tagstags:read · R0
PUT/deals/{deal_id}/tagstags:write · R1 · Idempotency-Key
GET/custom-fieldscustom_fields:read · R0 · cursor
POST/custom-fieldscustom_fields:write · R1 · Idempotency-Key
GET/custom-fields/{field_id}custom_fields:read · R0
PATCH/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key + If-Match
POST/custom-fields/{field_id}/archivecustom_fields:write · R1 · Idempotency-Key + If-Match
GET/leads/{lead_id}/custom-fieldscustom_fields:read · R0
PUT/leads/{lead_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key
GET/deals/{deal_id}/custom-fieldscustom_fields:read · R0
PUT/deals/{deal_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key
ContractExact behaviorError taxonomy
ReadsR0, no idempotency header; list endpoints use opaque cursor pagination.invalid_api_key, invalid_access_token, insufficient_scope, resource_access_denied, invalid_request, invalid_cursor, resource_not_found, rate_limited
MutationsR1, required Idempotency-Key; create replays return 201 and updates return 200. Versioned writes require current If-Match.invalid_request, unknown_field, idempotency_key_required, invalid_idempotency_key, idempotency_key_reused, approval_pending, resource_archived, resource_in_use, precondition_required, version_conflict, idempotency_unavailable
Tenant safetyLead and deal IDs are checked against the credential workspace before reads or writes; foreign records are concealed as not found.resource_not_found is never a cross-workspace disclosure.
Replace lead tags
curl -X PUT https://leadtrackerai.com/api/v1/leads/2194/tags \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: lead-tags-01JABC" \
  -H "Content-Type: application/json" \
  -d '{"tag_ids":[12,19]}'
Create a custom field
curl -X POST https://leadtrackerai.com/api/v1/custom-fields \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: field-01JABC" \
  -H "Content-Type: application/json" \
  -d '{"scope":"contact","key":"plan","label":"Plan","type":"select","options":["starter","team"]}'

Smart lists

Smart lists are saved, bounded lead filters. The filter schema is read-only metadata; creation, preview, update, and archive use smart_lists:write, R1/R0 as shown, and replay-safe idempotency. The lead projection requires leads:read.

GET/smart-lists/filter-schemasmart_lists:read · R0
GET/smart-listssmart_lists:read · R0 · cursor
POST/smart-listssmart_lists:write · R1 · Idempotency-Key
POST/smart-lists/previewsmart_lists:write · R0 · Idempotency-Key
GET/smart-lists/{id}smart_lists:read · R0
PATCH/smart-lists/{id}smart_lists:write · R1 · Idempotency-Key + If-Match
DELETE/smart-lists/{id}smart_lists:write · R1 · Idempotency-Key + If-Match
GET/smart-lists/{id}/leadsleads:read · R0 · cursor
Exact errors: reads may return invalid_filter, invalid_cursor, resource_not_found, or smart_list_not_found; mutations additionally return duplicate_smart_list, role_denied, precondition_required, version_conflict, idempotency_key_reused, or idempotency_unavailable. All routes also use the shared authentication, scope, tenant, and rate-limit taxonomy.
Preview a smart list
curl -X POST https://leadtrackerai.com/api/v1/smart-lists/preview \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: preview-01JABC" \
  -H "Content-Type: application/json" \
  -d '{"filters":{"match":"all","rules":[{"field":"stage","operator":"eq","value":"setter"}]}}'

Pipelines and stages

Pipeline configuration is workspace-scoped and admin-role guarded in addition to the pipelines:read/pipelines:write scope. Every mutation is R1, requires Idempotency-Key, and stage/pipeline updates, archives, and reorders require If-Match.

GET/pipelinespipelines:read · R0
POST/pipelinespipelines:write · R1 · Idempotency-Key
GET/pipelines/{id}pipelines:read · R0
PATCH/pipelines/{id}pipelines:write · R1 · Idempotency-Key + If-Match
POST/pipelines/{id}/archivepipelines:write · R1 · Idempotency-Key + If-Match
POST/pipelines/{id}/stagespipelines:write · R1 · Idempotency-Key
PATCH/pipelines/{id}/stages/{stage_id}pipelines:write · R1 · Idempotency-Key + If-Match
POST/pipelines/{id}/stages/{stage_id}/archivepipelines:write · R1 · Idempotency-Key + If-Match
POST/pipelines/{id}/stages/reorderpipelines:write · R1 · Idempotency-Key + If-Match
Exact errors: route-specific failures include pipeline_not_found, stage_not_found, insufficient_role, resource_archived, resource_in_use, precondition_required, version_conflict, idempotency_key_reused, and idempotency_unavailable, plus shared authentication, scope, request, and rate-limit errors.
Create a pipeline stage
curl -X POST https://leadtrackerai.com/api/v1/pipelines/7/stages \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: stage-01JABC" \
  -H "Content-Type: application/json" \
  -d '{"name":"Qualified","position":2,"color":"#22d3ee"}'

Deals and forecast

Deals are workspace-scoped pipeline records linked to a lead. Read operations require deals:read (or analytics:read for forecast); create, update, transition, and activity writes require deals:write; archive and restore additionally require deals:archive. All deal mutations are R1, require a stable Idempotency-Key, and versioned writes require the current If-Match value.

GET/dealsdeals:read · R0 · cursor
POST/dealsdeals:write · R1 · Idempotency-Key
GET/deals/{id}deals:read · R0
PATCH/deals/{id}deals:write · R1 · If-Match
POST/deals/{id}/movedeals:write · R1 · If-Match
POST/deals/{id}/wondeals:write · R1 · If-Match
POST/deals/{id}/lostdeals:write · R1 · If-Match
POST/deals/{id}/reopendeals:write · R1 · If-Match
POST/deals/{id}/archivedeals:archive · R1 · If-Match
POST/deals/{id}/restoredeals:archive · R1 · If-Match
GET/deals/{id}/activitiesdeals:read · R0 · cursor
POST/deals/{id}/activitiesdeals:write · R1 · Idempotency-Key
GET/pipelines/{id}/boarddeals:read · R0 · cursor
GET/pipelines/{id}/forecastanalytics:read · R0
Exact money contract: responses expose value.amount_minor as a non-negative integer and value.currency as an uppercase three-letter ISO-4217 code. Inputs may use value.amount_minor or a decimal string in amount, never a floating-point value. Decimal precision follows the currency: USD uses two places, JPY uses zero, and currencies such as BHD, JOD, and KWD use three. Forecast totals remain integer minor units and are never calculated through binary floating point.
ContractExact behaviorErrors
TransitionsOnly open deals can move, become won, or become lost. Only won or lost deals can reopen, and reopen requires an active open destination stage. Archive and restore are separate admin-role guarded actions.invalid_state_transition, resource_archived, resource_not_archived, stage_not_found, insufficient_role
ConcurrencySend the ETag returned by a deal read in If-Match for every versioned mutation. A stale or missing version is rejected before the write.precondition_required, version_conflict
OutcomesMarking a deal won records the authoritative deal_won marketing event once per deal version. It does not charge a card, create an invoice, or imply payment.deal_not_found, lead_not_found, pipeline_not_found
Replay safetyReuse of an idempotency key replays the original response only when the canonical request hash matches; in-progress and unavailable reservations fail closed.idempotency_key_required, invalid_idempotency_key, idempotency_key_reused, idempotency_in_progress, idempotency_unavailable
Events: successful mutations can emit deal.created, deal.updated, deal.stage_changed, deal.won, deal.lost, deal.archived, deal.restored, and deal.activity.created. Events retain the credential's unified actor context and remain workspace-scoped.
Create a deal with exact money
curl -X POST https://leadtrackerai.com/api/v1/deals \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: deal-01JABC" \
  -H "Content-Type: application/json" \
  -d '{
    "lead_id": 2194,
    "pipeline_id": 7,
    "stage_id": 31,
    "name": "Northstar annual plan",
    "amount": "12500.00",
    "currency": "USD"
  }'
Move with the current version
curl -X POST https://leadtrackerai.com/api/v1/deals/884/move \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: deal-move-01JABC" \
  -H "If-Match: \"deal-884-v3\"" \
  -H "Content-Type: application/json" \
  -d '{"stage_id":32,"position":0}'

Conversations and compliant messaging

Read tenant-owned conversations and messages, explain send eligibility, and queue outbound SMS, WhatsApp, and email messages from a conversation. Recipient addresses are resolved only from the conversation lead; arbitrary recipients, sender IDs, provider IDs, and provider credentials are not accepted.

GET/conversationsList workspace conversations (cursor)
GET/conversations/{id}Read one safe conversation projection
GET/conversations/{id}/messagesList messages and delivery state (cursor)
GET/conversations/{id}/send-eligibilityExplain DNC, opt-out, quiet-hours, entitlement, and usage checks
POST/conversations/{id}/messagesQueue an outbound message — Idempotency-Key
POST/conversations/{id}/messages/scheduleSchedule an outbound message — Idempotency-Key
POST/conversations/{id}/messages/{message_id}/replyReply to an inbound message — Idempotency-Key
GET/suppression/statusRead masked suppression state
POST/suppression/requestsRecord a workspace suppression request — Idempotency-Key
POST/conversations/inboundStore an inbound channel message
POST/conversations/inbound-callsStore an inbound call transcript or outcome
POST/conversations/{id}/messagesconversations:send · R2 · 202

Send only body and, when needed, a conversation-matching channel, subject, or scheduled_at. The API atomically records the message intent, audit/event record, idempotency result, generic job, and tenant-owned outbox item. With external effects disabled, the response is a deterministic simulated queue and no provider call occurs.

Request
curl -X POST https://leadtrackerai.com/api/v1/conversations/300/messages \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: conversation-message-01JABC" \
  -H "Content-Type: application/json" \
  -d '{"channel":"sms","body":"Confirmed for Tuesday at 10:00."}'
Queued response
{
  "data": {
    "status": "queued",
    "simulated": true,
    "outbox_id": "mout_01JABC"
  },
  "request_id": "req_01JABC"
}
Compliance is fail-closed: DNC, lead DNC, channel opt-outs, and quiet hours produce a durable suppressed message with no provider job or outbox row. Duplicate idempotency keys replay the original result without charging usage twice.
POST/conversations/inbound-callsconversations:write

Supply lead_id, lead_email, or lead_phone, plus an external call ID and at least one of transcript, summary, disposition, or outcome. STOP requests are routed through LeadTracker AI's normal suppression handling.

Required idempotency: use a stable key from the upstream call provider. The API records a workspace-scoped external call ID and does not send a reply.

User Journey forms

Manage tenant-owned User Journey definitions through draft, immutable revision, publish, unpublish, clone, and archive lifecycle operations. Public links are updated with the same workspace and event-type ownership checks, while archived forms and submissions remain retained.

Submission reads are explicitly PII-safe: request only the projections your integration needs, use cursor pagination for exports, and keep the API key on a trusted server.

{brand} is your workspace's own brand slug — one per public booking/application page you've set up (find yours on the Applications dashboard's User Journey Forms page, or in each page's live URL). Any brand slug your workspace owns works here; it isn't limited to any fixed list.

GET/formsList owned forms (cursor)
POST/formsCreate a draft form — forms:write
GET/forms/{brand}Fetch the saved form definition
PATCH/forms/{brand}Save a versioned draft — If-Match
POST/forms/{brand}/publishPublish a draft — If-Match
POST/forms/{brand}/unpublishUnpublish without deleting submissions
POST/forms/{brand}/archiveArchive while retaining history
POST/forms/{brand}/cloneClone into a new tenant-owned brand
GET/forms/{brand}/revisionsList immutable revisions (cursor)
GET/forms/{brand}/revisions/{revision_id}Read one immutable revision
GET/forms/{brand}/submissionsList explicit PII-safe submissions (cursor)
GET/forms/{brand}/submissions/{id}Read one explicit PII-safe submission
GET/forms/{brand}/analyticsRead aggregate funnel analytics
POST/forms/{brand}/eventsAppend a funnel event · Idempotency-Key · 204 replay
POST/forms/{brand}/submissionsValidate and submit a completed form
GET/public-linksList owned public links (cursor)
PATCH/public-links/{id}Update link routing — If-Match
POST/forms/acme/submissionsforms:submit

The submission is checked against the saved form definition. Send contact data, answers, a canonical IANA timezone, attribution, and a stable session ID. location remains accepted only for legacy compatibility; when timezone is absent, a recognized legacy location or North-American phone area code may be inferred into the canonical timezone field. New integrations should send timezone and omit location. New leads follow the existing Telegram notification route; retries replay safely. If email or phone already belongs to a different lead identity, the submission is rejected with 409 lead_identity_conflict and the existing CRM record remains unchanged.

Server-side only: do not expose an lt_live_ key in a browser embed. Use LeadTracker AI's public hosted journey for client-side pages.

Analytics, attribution, and tracking

Read aggregate funnel, source, velocity, cohort, paid-media, creative, unit-economics, attendance, leaderboard, and data-quality metrics without exposing contact details, answers, session identifiers, provider payloads, or raw query strings. The same surface preserves the existing application funnel contract while adding attribution and event ingestion.

GET/analytics/application-funnel?days=30&brand=acmeanalytics:read

days accepts 7 through 90. brand is optional and, when given, must be one of your workspace's own registered brand slugs (omit it to aggregate across all of them). The response contains totals, daily trend data, attribution rows, and abandonment points only.

GET/analytics/dashboardanalytics:read · aggregate summary
GET/analytics/funnelanalytics:read · aggregate stages
GET/analytics/sourcesanalytics:read · cursor
GET/analytics/velocityanalytics:read · cursor
GET/analytics/attributionanalytics:read · model + currency basis · cursor
GET/analytics/cohortsanalytics:read · model + currency basis · cursor
GET/analytics/paid-performancemarketing:read · cursor
GET/analytics/creativesmarketing:read · cursor
GET/analytics/unit-economicsmarketing:read · cursor
GET/analytics/data-qualityanalytics:read · freshness/coverage · cursor
GET/analytics/attendanceanalytics:read · cursor
GET/analytics/leaderboardanalytics:read · cursor
POST/analytics/exportsanalytics:export · queued/202 · Idempotency-Key
POST/tracking/eventsmarketing:configure · deduplicated · Idempotency-Key
POST/tracking/conversion-eventsmarketing:configure · authoritative outcomes stay server-side
POST/commerce/eventsmarketing:configure · minor-unit currency · Idempotency-Key
GET/tracking/events/{event_id}marketing:read · workspace-scoped projection
Privacy and quality: event IDs are caller-stable and deduplicated per workspace; attribution and event attributes are sanitized before storage, and PII is never projected. Monetary values use integer amount_minor plus uppercase ISO-4217 currency. Mixed currencies require an explicit workspace-rate basis and may return currency_basis_required. Data-quality responses surface freshness and coverage warnings rather than silently presenting stale or incomplete inputs.
Exports and effects: exports create durable queued jobs and require analytics:export plus Idempotency-Key. With external effects disabled, export and tracking operations remain deterministic local intents; no provider URL, storage key, or raw credential is returned.

Marketing connections and governed actions

The marketing surface connects workspace-owned provider integrations, goal mappings, consent policy, recommendations, forecasts, and identity resolution. Every operation is workspace-scoped, audited, idempotent, and protected by its exact integrations or marketing scope.

i
Stored credentials stay server-side

Authorization uses provider-hosted OAuth where supported. Request bodies reject access tokens, refresh tokens, client secrets, passwords, and credential objects; connection projections and audit summaries redact provider secrets and storage keys.

Data-quality and plans: recommendation planning and execution fail closed when freshness, reconciliation, or attribution coverage evidence is missing or stale. Plans carry exact request and resource-version hashes; execution requires the matching operation and approval context. Rollback plans bind the prior action state/version and cannot run after that state changes.
Simulation and jobs: with external effects disabled, provider reads and writes are deterministic simulations. Syncs and forecasts still create durable queued job intents, and action execution records simulated effects without calling a provider. Every mutation requires Idempotency-Key; retrying a completed request replays its original response.

Growth Engine and SEO/GEO

Growth Engine brands, topics, posts, editorial decisions, quality gates, and SEO/GEO reporting are tenant-scoped and entitlement-gated. The surface contains 38 operations and never projects provider credentials, raw OAuth tokens, storage keys, or provider URLs.

i
Editorial approval is not publishing

POST /growth/posts/{id}/approve changes editorial state only. Publishing and unpublishing require growth:publish, a fresh exact plan, matching operation and plan hashes, approval context, and If-Match; quality, evidence, build, index, and semantic gates still run at execution.

Entitlements fail closed: Growth operations require the workspace Growth add-on; SEO operations require seo:configure only for approved configuration actions and eligible subscription verification. An unavailable billing or provider configuration check cannot enable an external action.
Credential and job boundary: Google authorization persists server-owned state bound to the actor, workspace, PKCE challenge, redirect URI, nonce, and expiry. Generation, enhancement, topic suggestions, publishing, and SEO sync use durable jobs; disabled external effects return deterministic simulation records and no raw provider data.

High-intent Signals and Prospect Packs

Signals and Prospect Packs add seven workspace-scoped operations for reading high-intent signals, converting a signal into a CRM lead exactly once, and requesting bounded prospect data through typed criteria.

i
Exact plan and tenancy boundary

Signal reads and conversion always bind the authenticated workspace; foreign signals are concealed. Conversion is replay-safe and derives the lead only from the server-owned signal identity. Prospect-pack plans bind the exact criteria, count, pricing version, usage allowance, entitlement snapshot, and plan hash before any provider work.

Fail-closed provider boundary: Prospect criteria accept only typed geography, company size, role, count, and allowlisted enrichment fields. Provider queries, credentials, and arbitrary recipients are rejected. The plan and request routes require leads:bulk; paid entitlement and usage checks fail closed when unavailable; external effects disabled returns deterministic simulation state without provider URLs or raw payloads.

Users, teams, workspace, and agency subaccounts

The Phase 9 control plane adds 30 tenant-safe operations for workspace membership, team tenancy, profile and branding settings, typed notification policies, usage and entitlements, and an agency parent’s explicitly owned subaccounts.

i
One credential, one tenant

Ordinary workspace credentials cannot select a workspace or team outside their authenticated tenant. Every user, team, policy, and workspace lookup is tenant-bound; cross-workspace identifiers are concealed as not found and membership replacement verifies every user belongs to the same workspace.

GET/usersCursor-paginated tenant users POST/users/invitations/planExact role/team invitation plan · R2 approval POST/users/invitationsDurable invitation job or deterministic simulation GET/users/{id}Safe user projection PATCH/users/{id}Owner/admin role and profile update POST/users/{id}/disable/planExact ownership/workload preview POST/users/{id}/disableApproved disablement plan POST/users/{id}/enableVersioned membership enable GET/teamsCursor-paginated tenant teams POST/teamsTyped team creation GET/teams/{id}Team and safe member projection PATCH/teams/{id}Versioned team update PUT/teams/{id}/membersTenant-checked membership replacement POST/teams/{id}/archive/planExact workload archive plan · R2 approval POST/teams/{id}/archiveWorkload-aware team archive GET/workspaceWorkspace profile and settings PATCH/workspaceVersioned workspace profile update GET/workspace/brandingSafe branding projection PATCH/workspace/brandingAllowlisted branding update GET/workspace/notification-policiesTyped event policies PUT/workspace/notification-policiesReplace typed policies with If-Match or version GET/workspace/usageUsage counters GET/workspace/entitlementsEntitlement status GET/workspacesAgency-owned subaccounts only POST/workspaces/planExact R3 creation and rebilling plan POST/workspacesApproved subaccount creation job or simulation GET/workspaces/{id}Owned relationship projection PATCH/workspaces/{id}Versioned owned-subaccount update POST/workspaces/{id}/suspend/planExact R3 suspension plan POST/workspaces/{id}/suspendApproved suspension job or simulation GET/domainsdomains:read · R0 · cursor POST/domainsdomains:write · R1 · Idempotency-Key GET/domains/{id}domains:read · R0 POST/domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key POST/domains/{id}/remove/plandomains:write · R3 · exact plan POST/domains/{id}/removedomains:write · R3 · approved plan · 202 GET/integrationsintegrations:read · R0 · opaque cursor · max 100 GET/integrations/{provider}integrations:read · R0 POST/integrations/{provider}/authorizeintegrations:write · R1 · server-bound OAuth state POST/integrations/{provider}/syncintegrations:write · R2 · 202 · Idempotency-Key POST/integrations/{provider}/disconnect/planintegrations:write · R3 · exact plan POST/integrations/{provider}/disconnectintegrations:write · R3 · approved plan · 202 GET/onboarding/stateworkspace:read · R0 · independent nested cursors · max 100 PATCH/onboarding/business-profileworkspace:write · R1 · If-Match POST/onboarding/texting-registrationworkspace:write · R3 · carrier plan/job GET/onboarding/texting-registrationworkspace:read · R0 POST/onboarding/email-domainsdomains:write · R1 · Idempotency-Key POST/onboarding/email-domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key GET/settingsworkspace:read · R0 · typed/redacted PATCH/settingsworkspace:write · R1 · If-Match
Role, plan, and secrecy gates: owner/admin or manager checks are enforced in addition to scopes; the final active owner cannot be disabled or demoted. Agency operations require the separate agency control-plane audience and stored ownership relationship. Invitation and team-archive plans bind exact request and resource versions, team memberships/workload, approval context, entitlement state, and expiry; execution requires the matching one-time approval. Invitations, agency provisioning, and suspension create durable jobs; external-effects-disabled mode returns deterministic simulations and never accepts or returns provider credentials, tokens, or arbitrary destinations.
Typed policies: notification policies are typed event, channel, and destination policies that accept only allowlisted channels and destinations (user, team, role, workspace admin, or workspace owner), with bounded settings and recursive secret rejection.

Domains, integrations, onboarding, and settings

The Domains/Integrations/Onboarding/Settings surface adds 22 tenant-bound operations for customer domains, provider connections, carrier registration, email sending domains, and typed workspace settings.

i
Provider state stays server-bound

Integration authorization accepts only an allowlisted provider, exact HTTPS redirect URI, PKCE S256 challenge, and OIDC nonce/scopes. OAuth state is generated and stored server-side bound to the credential, actor, workspace, redirect, challenge, nonce hash, and expiry; callbacks accept the standard provider state/code redirect and validate nonce only from a cryptographically verified ID token. Callbacks never accept client-supplied provider secrets. Status projections redact access tokens, refresh tokens, provider IDs, raw URLs, and storage keys.

Exact R3 and durable jobs: domain removal and integration disconnect create dependency-aware plans that bind the current resource version, request hash, policy decision, approval, and expiry. Execution requires the exact plan and one-time approval; stale or changed dependencies fail closed. Texting registration follows the same plan-first carrier boundary, while verification and synchronization are durable jobs with deterministic simulations when external effects are disabled.
Typed settings and tenant isolation: domains, integrations, onboarding records, and settings are always scoped to the authenticated workspace. Settings accept only allowlisted timezone, locale, date format, channel, notification, branding, website, and quiet-hour fields; unsafe keys, nested secrets, provider credentials, raw URLs, and storage references are rejected or redacted.
Typed policies and bounded traversal: notification policies are typed event, channel, and destination policies that accept only allowlisted channels and destinations (user, team, role, workspace admin, or workspace owner), with bounded settings and recursive secret rejection. Replacements require If-Match or the numeric version from the read response. Integration lists accept workspace-bound opaque cursors up to 100 items; onboarding state exposes independent email_domains_cursor and integrations_cursor inputs and returns a cursor for each nested collection.

Billing and plan management

Billing adds 8 tenant-scoped operations for safe subscription state, usage, server-owned plans, exact plan changes, usage-credit top-ups, and provider-hosted portal sessions. Reads use billing:read; owner/admin mutations use billing:write.

i
Provider-hosted and tokenized only

Raw card, bank, provider credential, token, storage-key, and secret fields are rejected. Use the provider-hosted portal or tokenized provider flow; the API never stores or returns raw payment data.

Exact approval and currency gates: previews resolve prices, add-ons, currency, entitlement deltas, and server resource versions. Plan and top-up execution requires the exact operation_id, approval_id, request hash, resolved-resource-versions hash, one-time approval, and unexpired plan; stale or changed catalog/subscription state must fail closed. Amounts are integer minor units and the catalog currency is USD.
Usage and effects: owner/admin role and paid-entitlement checks run in addition to scopes. Every mutation requires Idempotency-Key. With external effects disabled, previews, executions, jobs, and events are deterministic simulations with no provider call; live mode returns only safe provider-hosted or tokenized projections.

Native workflows and triggers

Build tenant-owned workflows from the validated node catalog, inspect durable runs, and trigger or simulate them through the same scope, plan, idempotency, audit, and disabled-effects gates as the rest of the API. HTTP and webhook nodes accept only prevalidated workspace destinations; provider URLs, storage keys, and raw credentials never enter the public contract.

POST/workflows/{workflow_id}/triggerworkflows:trigger

The compatibility webhook trigger accepts { "event": "voice.call.completed", "payload": { ... } } with an Idempotency-Key. Native workflow runs additionally accept an exact operation plan where policy requires it, persist retry lineage, and simulate all effects while external effects are disabled.

Destination and billing gates are server-side: workflow execution resolves only workspace-owned prevalidated destinations, enforces usage/paid-plan checks for live effects, and never calls a provider directly from the request handler.

Jobs, approvals, and audit

Phase 1 operation resources are workspace-scoped and available through the same API-key or delegated OAuth credential boundary. Job reads require a held domain read scope; cancellation requires the execute scope that originated the job.

!
Approval separation is enforced

POST /approval-requests creates a request from a server-generated operation plan. There is intentionally no public /approve endpoint. Owner decisions happen through the existing authenticated approval channel, then execution must present the exact request hash, workspace, resource versions, expiry, and one-time approval state.

GET/jobsR0 · domain read scope · cursor
GET/jobs/{job_id}R0 · domain read scope
POST/jobs/{job_id}/cancelR1 · originating execute scope · Idempotency-Key
GET/approval-requestsR0 · approvals:read · cursor
POST/approval-requestsR1 · approvals:request · Idempotency-Key
GET/approval-requests/{approval_request_id}R0 · approvals:read
POST/approval-requests/{approval_request_id}/cancelR1 · approvals:request · Idempotency-Key
GET/audit-eventsR0 · audit:read · cursor
GET/audit-events/{audit_event_id}R0 · audit:read
OperationScope / riskIdempotency and approvalStable errors
GET /jobsdomain_read
R0
Signed cursor bound to workspace, route, and filtersinvalid_api_key, invalid_access_token, insufficient_scope, invalid_request, invalid_filter, invalid_cursor, rate_limited
GET /jobs/{job_id}domain_read
R0
Noneinvalid_api_key, invalid_access_token, insufficient_scope, resource_not_found
POST /jobs/{job_id}/canceloriginating_execute
R1
Required Idempotency-Key; cancellation is only allowed for cancellable jobsidempotency_key_required, idempotency_key_reused, resource_not_found, job_not_cancellable, invalid_state_transition
GET /approval-requestsapprovals:read
R0
Signed cursor; callback evidence is omittedinvalid_filter, invalid_cursor, rate_limited
POST /approval-requestsapprovals:request
R1
Required Idempotency-Key; server-generated operation plan onlyunknown_field, idempotency_key_reused, resource_not_found, approval_mismatch, approval_expired
GET /approval-requests/{approval_request_id}approvals:read
R0
Cross-workspace IDs return resource_not_foundresource_not_found, insufficient_scope
POST /approval-requests/{approval_request_id}/cancelapprovals:request
R1
Required Idempotency-Key; initiator or owner may cancelidempotency_key_reused, resource_not_found, insufficient_role, invalid_state_transition
GET /audit-eventsaudit:read
R0
Signed cursor and bounded filtersinvalid_filter, invalid_cursor, rate_limited
GET /audit-events/{audit_event_id}audit:read
R0
Redacts authorization, OAuth, API-key, callback, and provider secretsresource_not_found, insufficient_scope
List jobs
curl https://leadtrackerai.com/api/v1/jobs?limit=50 \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN"
Request approval
curl -X POST https://leadtrackerai.com/api/v1/approval-requests \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: campaign-approval-2026-08-14" \
  -H "Content-Type: application/json" \
  -d '{"operation_id":"op_01JABCDEF1234567","reason":"recipient threshold"}'

Service-account control plane

Service-account administration is a human owner/admin control plane. It uses the same workspace-bound API-key or delegated OAuth chain, requires developer:credentials:admin, and never treats a legacy API key as a human administrator.

!
Secrets are one-time values

Credential creation and rotation return client_secret once with Cache-Control: no-store. List, get, revoke, idempotent replay, and /whoami responses contain metadata only. Store the secret immediately; it cannot be recovered.

GET/developer/scopesR0 · developer:credentials:admin
GET/service-accountsR0 · cursor
POST/service-accountsR1 · Idempotency-Key
GET/service-accounts/{service_account_id}R0 · metadata only
PATCH/service-accounts/{service_account_id}R1 · Idempotency-Key + If-Match
POST/service-accounts/{service_account_id}/rotateR3 · Idempotency-Key + If-Match
POST/service-accounts/{service_account_id}/disableR3 · Idempotency-Key + If-Match
POST/service-accounts/{service_account_id}/enableR1 · Idempotency-Key + If-Match
GET/service-accounts/{service_account_id}/credentialsR0 · cursor · metadata only
POST/service-accounts/{service_account_id}/credentialsR3 · one-time client_secret
DELETE/service-accounts/{service_account_id}/credentials/{credential_id}R3 · Idempotency-Key + If-Match
OperationGrantabilitySafety contractStable errors
GET /developer/scopesOwner/admin onlyReturns exact server-owned scope definitions and grantable subsetinsufficient_role, insufficient_scope, resource_access_denied
POST /service-accountsRequested scopes must be grantableRequired Idempotency-Key; no secret is created or returnedinvalid_request, unknown_field, idempotency_key_reused
PATCH /service-accounts/{service_account_id}Owner/admin grant setRequired Idempotency-Key and current If-Matchprecondition_required, version_conflict, insufficient_scope
POST /service-accounts/{service_account_id}/rotateOwner/admin grant setR3; exact ETag and idempotency; bounded overlap; one-time secret revealinvalid_state_transition, version_conflict, resource_not_found
POST /service-accounts/{service_account_id}/disableOwner/admin onlyR3; revokes issued access tokens; final owner account is protectedresource_in_use, precondition_required, version_conflict
POST /service-accounts/{service_account_id}/credentialsSubset of account grantR3; secret appears once and replay never re-reveals itinvalid_request, invalid_state_transition, idempotency_key_reused
DELETE /service-accounts/{service_account_id}/credentials/{credential_id}Owner/admin onlyR3; revokes tokens; the final recovery credential and final owner automation credential are protectedresource_in_use, precondition_required, version_conflict
Create a service account
curl -X POST https://leadtrackerai.com/api/v1/service-accounts \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: create-sa-2026-08-14" \
  -H "Content-Type: application/json" \
  -d '{"name":"Sales automation","purpose":"automation","scopes":["leads:read"]}'
Create one-time credential
curl -X POST https://leadtrackerai.com/api/v1/service-accounts/sa_01JABCDEF1234567/credentials \
  -H "Authorization: Bearer $LEADTRACKER_API_TOKEN" \
  -H "Idempotency-Key: create-credential-2026-08-14" \
  -H "Content-Type: application/json" \
  -d '{"purpose":"automation","scopes":["leads:read"]}'

Generic event webhooks

Manage workspace-scoped endpoints for the generic event stream with an API key. These routes are separate from the legacy booking webhook settings below and never accept booking lifecycle event names.

!
Signing secrets are one-time values

POST /webhook-endpoints and POST /webhook-endpoints/{endpoint_id}/rotate-secret return signing_secret once. Replay responses, list responses, and delivery responses never contain a secret. Store it immediately and use it to verify the signed event envelope.

GET/webhook-endpointsR0 · developer:webhooks:read · no key
POST/webhook-endpointsR1 · developer:webhooks:write · Idempotency-Key
GET/webhook-endpoints/{endpoint_id}R0 · developer:webhooks:read · no key
PATCH/webhook-endpoints/{endpoint_id}R1 · developer:webhooks:write · Idempotency-Key + If-Match
DELETE/webhook-endpoints/{endpoint_id}R3 · developer:webhooks:write · policy · Idempotency-Key + If-Match
POST/webhook-endpoints/{endpoint_id}/rotate-secretR3 · developer:webhooks:write · Idempotency-Key + If-Match
GET/webhook-endpoints/{endpoint_id}/deliveriesR0 · developer:webhooks:read · cursor
GET/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}R0 · developer:webhooks:read · no key
POST/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retryR1 · developer:webhooks:write · Idempotency-Key
OperationScope / riskIdempotency and preconditionErrors
GET /webhook-endpointsdeveloper:webhooks:read
R0
Noneinvalid_api_key, insufficient_scope, invalid_endpoint_id, resource_not_found, rate_limited
POST /webhook-endpointsdeveloper:webhooks:write
R1
Required Idempotency-Key; replay returns the original projection without a secretinvalid_api_key, insufficient_scope, invalid_request, unknown_field, invalid_webhook_name, invalid_webhook_url, unsafe_webhook_destination, destination_unresolvable, invalid_webhook_events, legacy_booking_webhook_event, invalid_idempotency_key, idempotency_key_reused, quota_exceeded, rate_limited, idempotency_unavailable, webhook_encryption_unavailable
GET /webhook-endpoints/{endpoint_id}developer:webhooks:read
R0
Noneinvalid_api_key, insufficient_scope, invalid_endpoint_id, resource_not_found, rate_limited
PATCH /webhook-endpoints/{endpoint_id}developer:webhooks:write
R1
Required Idempotency-Key and current If-Matchinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_request, unknown_field, invalid_webhook_name, invalid_webhook_url, unsafe_webhook_destination, destination_unresolvable, invalid_webhook_events, legacy_booking_webhook_event, invalid_idempotency_key, idempotency_key_reused, resource_not_found, precondition_required, version_conflict, rate_limited, idempotency_unavailable
DELETE /webhook-endpoints/{endpoint_id}developer:webhooks:write
R3 · policy
Policy evaluation, required Idempotency-Key and current If-Matchinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_request, invalid_idempotency_key, idempotency_key_reused, resource_not_found, precondition_required, version_conflict, rate_limited, idempotency_unavailable
POST /webhook-endpoints/{endpoint_id}/rotate-secretdeveloper:webhooks:write
R3
Required Idempotency-Key and current If-Matchinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_request, invalid_idempotency_key, idempotency_key_reused, resource_not_found, precondition_required, version_conflict, rate_limited, idempotency_unavailable, webhook_encryption_unavailable
GET /webhook-endpoints/{endpoint_id}/deliveriesdeveloper:webhooks:read
R0
Opaque cursor pagination; no keyinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_filter, invalid_cursor, resource_not_found, rate_limited
GET /webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}developer:webhooks:read
R0
Noneinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_delivery_id, resource_not_found, rate_limited
POST /webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retrydeveloper:webhooks:write
R1
Required Idempotency-Keyinvalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_delivery_id, invalid_request, invalid_idempotency_key, idempotency_key_reused, resource_not_found, resource_in_use, invalid_state_transition, rate_limited, idempotency_unavailable
Create and reveal once
curl -X POST https://leadtrackerai.com/api/v1/webhook-endpoints \
  -H "Authorization: Bearer $LEADTRACKER_API_KEY" \
  -H "Idempotency-Key: crm-events-2026-08-14" \
  -H "Content-Type: application/json" \
  -d '{"name":"CRM events","url":"https://hooks.example.com/leadtracker","events":["deal.updated","lead.created"]}'
201 response
{
  "data": { "id": "wep_01JABCDEF1234567", "version": 1 },
  "signing_secret": "whsec_one_time_value"
}
// Replay and GET/list responses omit signing_secret.
Delivery response
{
  "data": {
    "id": "whd_01JABCDEF1234567",
    "event_type": "deal.updated",
    "status": "delivered",
    "event": { "api_version": "2026-08-14", "data": { "object": { "id": 91 } } }
  }
}
PATCHIf-Match: "wep_...:1"versioned writes

Configuration updates, deletion, and secret rotation require the current ETag. A stale or missing tag returns 428 precondition_required or 412 version_conflict. Destination changes, subscription changes, and deletion discard queued generic deliveries.

Booking webhooks

Create endpoints from LeadTracker AI app → Developer API. Endpoint configuration is owner/admin session-only; API keys cannot add a destination or reveal a signing secret.

EVENTbooking.createdNative booking was confirmed
EVENTbooking.rescheduledNative booking time changed
EVENTbooking.cancelledNative booking was cancelled
EVENTbooking.no_showAttendance was marked no-show
POSTYour configured HTTPS endpointHMAC SHA-256

LeadTracker AI sends JSON over DNS-pinned public HTTPS, never follows redirects, and retries at least once with a stable event ID. De-duplicate deliveries with X-LeadTracker-Event-Id. Every booking payload includes brand_id so downstream systems can retain the same tenant identity.

HeaderDescription
X-LeadTracker-EventThe booking event name.
X-LeadTracker-Event-IdStable event identifier for receiver de-duplication.
X-LeadTracker-TimestampUnix timestamp in seconds.
X-LeadTracker-Signaturev1= + HMAC SHA-256 of timestamp + "." + raw_body.

Errors and limits

All errors include a stable machine-readable code and a request_id for support and diagnostics.

400invalid_brand_idbrand_id is not a positive integer.
400brand_event_type_mismatchThe selected event type is not configured for this booking brand.
400brand_id_requiredThe event type is shared by multiple brands, so the brand must be selected explicitly.
400brand_not_configuredThe event type has no active booking-brand association; configure one before using it through the Developer API.
400invalid_attendeeRequired contact information or timezone is missing or invalid.
401invalid_api_keyThe key is unknown, expired, revoked, or belongs to an inactive workspace.
402subscription_requiredA paid automation action was requested from a workspace without an active subscription, or its trial has ended.
402quota_exceededA plan count limit (seats, phone numbers, active forms, form submissions/mo, API keys) is at its cap. Upgrade to raise it.
402trial_limit_reachedA free-trial cap (seats, event types, forms, submissions, or API keys) is at its limit. Pick a plan to raise it.
402trial_expiredThe workspace's 14-day trial window has passed; mutations are blocked (reads still work) until a plan is chosen.
403insufficient_scopeThe credential does not include the required capability scope.
404brand_not_foundThe brand does not exist in the API key's workspace or is not booking-enabled.
404booking_not_foundThe booking does not exist in this workspace.
409slot_takenThe slot changed after availability was fetched. Fetch availability again and offer a new time.
409idempotency_key_reusedThe same write key was sent with a different request body.
429rate_limitedAuthenticated keys are limited to 120 requests per minute. Respect the standard rate-limit response headers.
503subscription_verification_unavailablePaid external actions fail closed while entitlement verification is unavailable.
Error response
{
  "error": {
    "code": "slot_taken",
    "message": "That slot is no longer available."
  },
  "request_id": "4c0725d0-..."
}

Security practices

Use separate keys for every provider and environment. Give each key a recognizable name, set a practical expiration, and replace it before sharing changes hands.

!
Keep keys server-side

Never put a LeadTracker AI API key in a frontend bundle, publicly accessible webhook URL, or transcript. For a suspected exposure, create a replacement key and revoke the existing one immediately.

Payment and compliance gates cannot be delegated: an API key grants only a capability scope. It never grants a plan, usage allowance, phone number, billing role, or exemption from consent, quiet-hours, opt-out, and provider checks.