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.
https://leadtrackerai.com/api/v1 Download OpenAPI 3.1Use 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.
curl https://leadtrackerai.com/api/v1/scheduling/brands \
-H "Authorization: Bearer lt_live_..."
X-API-Key: lt_live_...
Idempotency-Key header for every mutation. Booking reschedule/cancel and form funnel events now enforce replay-safe idempotency; duplicate keys replay the original result.402 quota_exceeded.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.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.
npm install @leadtracker/developer-api
python -m pip install leadtracker-developer-api
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);
}
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.
{
"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.
/metaauthenticated/whoamiauthenticated/capabilitiesauthenticated/operation-planstarget scope · R1 · immutable MCP plan/scheduling/brandsscheduling:read/scheduling/event-typesscheduling:read/scheduling/availabilityscheduling:read/scheduling/bookingsscheduling:read/scheduling/bookings/{uid}scheduling:read/scheduling/bookingsscheduling:write/scheduling/bookings/{uid}/reschedulescheduling:write · R2 · Idempotency-Key/scheduling/bookings/{uid}/cancelscheduling:write · R2 · Idempotency-Key/scheduling/calendarsscheduling:read · R0 · cursor/scheduling/calendarsscheduling:configure · R1 · Idempotency-Key/scheduling/calendars/{id}scheduling:read · R0/scheduling/calendars/{id}scheduling:configure · R1 · If-Match/scheduling/calendars/{id}/archivescheduling:configure · R1 · If-Match/scheduling/event-typesscheduling:configure · R1 · Idempotency-Key/scheduling/event-types/{id}scheduling:read · R0/scheduling/event-types/{id}scheduling:configure · R1 · If-Match/scheduling/event-types/{id}scheduling:configure · R1 · If-Match/scheduling/event-types/{id}/remindersscheduling:read · R0/scheduling/event-types/{id}/remindersscheduling:configure · R1 · If-Match/scheduling/calendars/{id}/availability-rulesscheduling:read · R0/scheduling/calendars/{id}/availability-rulesscheduling:configure · R1 · If-Match/scheduling/calendars/{id}/exceptionsscheduling:read · R0/scheduling/calendars/{id}/exceptionsscheduling:configure · R1 · Idempotency-Key/scheduling/calendars/{id}/exceptions/{exception_id}scheduling:configure · R1 · If-Match/scheduling/calendars/{id}/exceptions/{exception_id}scheduling:configure · R1 · If-Match/scheduling/time-offscheduling:read · R0/scheduling/time-offscheduling:configure · R1 · Idempotency-Key/scheduling/time-off/{id}scheduling:configure · R1 · If-Match/scheduling/time-off/{id}scheduling:configure · R1 · If-Match/scheduling/routing-poolsscheduling:read · R0 · cursor/scheduling/routing-poolsscheduling:configure · R1 · Idempotency-Key/scheduling/routing-pools/{id}scheduling:read · R0/scheduling/routing-pools/{id}scheduling:configure · R1 · If-Match/scheduling/routing-pools/{id}/membersscheduling:configure · R1 · If-Match/scheduling/connectionsscheduling:connections · R0/scheduling/connections/{provider}/authorizescheduling:connections · R1 · Idempotency-Key/scheduling/connections/{provider}/callbackpublic state/PKCE/OIDC-ID-token callback · MCP hidden/scheduling/authorizations/{id}scheduling:connections · R0 · status only/scheduling/connections/{id}/syncscheduling:connections · R2 · 202 · Idempotency-Key/scheduling/connections/{id}/calendars/{calendar_id}scheduling:connections · R1 · If-Match/scheduling/connections/{id}/disconnect/planscheduling:connections · R2 · Idempotency-Key/scheduling/connections/{id}/disconnectscheduling:connections · R3 · If-Match/scheduling/holdsscheduling:write · R1 · Idempotency-Key/scheduling/bookings/{uid}/attendancescheduling:write · R1 · If-Match/leads/searchleads:read/leadsleads:read/leads/{id}leads:read/leads/{id}/taskstasks:read · R0 · cursor/leads/{id}/researchleads:write · R2 · 202 · Idempotency-Key/leads/{id}/enrichmentleads:write · R2 · 202 · Idempotency-Key/leads/bulkleads:bulk · R1 · 202 · Idempotency-Key/leadsleads:write/leads/upsertleads:write/leads/importsleads:bulk · R1 · 202 · Idempotency-Key/leads/imports/{job_id}leads:bulk · R0/leads/imports/{import_id}/commitleads:bulk · R1 · 202 · Idempotency-Key/leads/exportsanalytics:export · R1 · 202 · Idempotency-Key/leads/exports/{artifact_id}analytics:export · R0 · expires/leads/exports/{artifact_id}/downloadanalytics:export · R0 · audited/leads/{id}leads:write/leads/{id}/archiveleads:archive/leads/{id}/restoreleads:archive/leads/{id}/notesleads:read/leads/{id}/notesleads:write/leads/{id}/notes/{note_id}leads:write/leads/{id}/notes/{note_id}leads:write/leads/{id}/activitiesleads:read/leads/{id}/activitiesleads:write/conversations/inboundconversations:write/conversations/inbound-callsconversations:write/conversationsconversations:read · R0 · cursor/conversations/{id}conversations:read · R0/conversations/{id}/assignconversations:write · R1 · Idempotency-Key/conversations/{id}/closeconversations:write · R1 · Idempotency-Key/conversations/{id}/reopenconversations:write · R1 · Idempotency-Key/conversations/{id}/messagesconversations:read · R0 · cursor/conversations/{id}/send-eligibilityconversations:send · R0/conversations/{id}/messagesconversations:send · R2 · 202 · Idempotency-Key/conversations/{id}/messages/scheduleconversations:send · R2 · 202 · Idempotency-Key/conversations/{id}/messages/{message_id}/replyconversations:send · R2 · 202 · Idempotency-Key/suppression/statusconversations:read · R0/suppression/requestsconversations:write · R1 · Idempotency-Key/callscalls:read · R0 · cursor/callscalls:start · R2 · 201/202 · Idempotency-Key/calls/{id}calls:read · R0/calls/{id}/statuscalls:read · R0/calls/{id}/statuscalls:control · R2 · Idempotency-Key/calls/{id}/dtmfcalls:control · R2 · Idempotency-Key/calls/{id}/hangupcalls:control · R2 · Idempotency-Key/calls/{id}/dispositioncalls:control · R1 · Idempotency-Key/calls/{id}/retrycalls:start · R2 · 201/202 · Idempotency-Key/calls/{id}/recordingrecordings:read · R0 · signed expiry/calls/{id}/transcriptrecordings:read · R0 · signed expiry/calls/{id}/summarycalls:read · R0 · signed expiry/scheduled-callscalls:read · R0 · cursor/scheduled-callscalls:start · R1 · Idempotency-Key/scheduled-calls/{id}calls:start · R1 · If-Match · Idempotency-Key/scheduled-calls/{id}/completecalls:control · R1 · Idempotency-Key/scheduled-calls/{id}/snoozecalls:control · R1 · Idempotency-Key/scheduled-calls/{id}/skipcalls:control · R1 · Idempotency-Key/call-queuescalls:read · R0 · cursor/call-queuescalls:start · R1 · Idempotency-Key/call-queues/{id}calls:read · R0/call-queues/{id}/start-nextcalls:start · R2 · 202 · Idempotency-Key/call-queues/{id}/pausecalls:control · R1 · If-Match · Idempotency-Key/call-queues/{id}/resumecalls:control · R1 · If-Match · Idempotency-Key/scriptsscripts:read · R0 · cursor/scriptsscripts:write · R1 · Idempotency-Key/scripts/{id}scripts:read · R0/scripts/{id}scripts:write · R1 · If-Match · Idempotency-Key/scripts/{id}/publishscripts:write · R1 · Idempotency-Key/scripts/{id}/archivescripts:write · R1 · Idempotency-Key/scripts/{id}/clonescripts:write · R1 · Idempotency-Key/scripts/{id}/versionsscripts:read · R0 · cursor/scripts/{id}/assignmentsscripts:read · R0/scripts/{id}/assignscripts:write · R1 · Idempotency-Key/voicemailsvoicemails:read · R0 · cursor/voicemailsvoicemails:write · R1 · 201/202 · Idempotency-Key/voicemails/{id}voicemails:read · R0/voicemails/{id}voicemails:write · R1 · If-Match · Idempotency-Key/voicemails/previewvoicemails:write · R2 · 200/202 · Idempotency-Key/voicemails/{id}/previewvoicemails:read · R0 · Idempotency-Key/voicemails/{id}/set-defaultvoicemails:write · R1 · Idempotency-Key/voicemails/{id}/archivevoicemails:write · R1 · Idempotency-Key/voicemails/{id}/versionsvoicemails:read · R0 · cursor/campaignscampaigns:read · R0 · cursor/campaignscampaigns:write · R1 · Idempotency-Key/campaigns/{id}campaigns:read · R0/campaigns/{id}campaigns:write · R1 · If-Match · Idempotency-Key/campaigns/{id}/archivecampaigns:write · R1 · If-Match · Idempotency-Key/campaigns/{id}/stepscampaigns:read · R0/campaigns/{id}/stepscampaigns:write · R1 · If-Match · Idempotency-Key/campaigns/{id}/validatecampaigns:write · R1 · Idempotency-Key/campaigns/{id}/activatecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/pausecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/resumecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/launch/plancampaigns:execute · R2 · plan · Idempotency-Key/campaigns/{id}/launchcampaigns:execute · R3 · approved · 202 · Idempotency-Key/campaigns/{id}/enrollmentscampaigns:execute · R2 · 202 · Idempotency-Key/campaigns/{id}/enrollmentscampaigns:read · R0 · cursor/campaigns/{id}/enrollments/{enrollment_id}/pausecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/enrollments/{enrollment_id}/resumecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/enrollments/{enrollment_id}/removecampaigns:execute · R2 · If-Match · Idempotency-Key/campaigns/{id}/analyticsanalytics:read · R0/workflowsworkflows:read · R0 · cursor/workflowsworkflows:write · R1 · Idempotency-Key/workflows/{id}workflows:read · R0/workflows/{id}workflows:write · R1 · If-Match · Idempotency-Key/workflows/{id}/cloneworkflows:write · R1 · Idempotency-Key/workflows/{id}/archiveworkflows:write · R1 · If-Match · Idempotency-Key/workflows/{id}/nodesworkflows:write · R1 · If-Match · Idempotency-Key/workflows/{id}/validateworkflows:write · R0 · Idempotency-Key/workflows/{id}/activate/planworkflows:execute · R2 · plan · Idempotency-Key/workflows/{id}/activateworkflows:execute · R2 · If-Match · Idempotency-Key/workflows/{id}/deactivate/planworkflows:execute · R2 · plan · Idempotency-Key/workflows/{id}/deactivateworkflows:execute · R2 · If-Match · Idempotency-Key/workflows/{id}/trigger/planworkflows:trigger · R2 · plan · Idempotency-Key/workflows/{id}/triggerworkflows:trigger · R2 · 202 · Idempotency-Key/workflows/{id}/test-runworkflows:execute · R2 · simulated · 202 · Idempotency-Key/workflows/{id}/runsworkflows:read · R0 · cursor/workflow-runs/{id}workflows:read · R0/workflow-runs/{id}/stepsworkflows:read · R0 · cursor/workflow-runs/{id}/cancelworkflows:execute · R2 · Idempotency-Key/workflow-runs/{id}/retryworkflows:execute · R2 · lineage · 202 · Idempotency-Key/meetingsmeetings:read · R0 · cursor/meetingsmeetings:write · R1 · 201 · Idempotency-Key/meetings/{id}meetings:read · R0/meetings/{id}meetings:write · R1 · If-Match · Idempotency-Key/meetings/{id}/cancelmeetings:write · R2 · policy · If-Match/meetings/{id}/inviteesmeetings:read · R0 · cursor/meetings/{id}/inviteesmeetings:write · R2 · external timezone required · Idempotency-Key/meetings/{id}/invitees/{invitee_id}meetings:write · R2 · Idempotency-Key/meetings/{id}/join-tokenmeetings:write · R1 · short-lived grant/meetings/{id}/endmeetings:write · R2 · artifacts · If-Match/meetings/{id}/recordingsmeeting_artifacts:read · R0/meetings/{id}/transcriptmeeting_artifacts:read · R0/meetings/{id}/summarymeeting_artifacts:read · R0/meetings/{id}/action-itemsmeeting_artifacts:read · R0/meetings/{id}/send-notes/eligibilitymeetings:write · R0 · policy check/meetings/{id}/send-notes/planmeetings:write · R2 · plan · Idempotency-Key/meetings/{id}/send-notesmeetings:write · R2 · 202 · Idempotency-Key/performance/leaderboardanalytics:read · R0 · cursor/performance/reps/{user_id}analytics:read · R0/coaching/templatescoaching:read · R0/coaching/templatescoaching:write · R1 · Idempotency-Key/coaching/templates/{id}coaching:write · R1 · If-Match · Idempotency-Key/coaching/sessionscoaching:read · R0 · cursor/coaching/sessionscoaching:write · R1 · Idempotency-Key/coaching/sessions/{id}coaching:read · R0/coaching/sessions/{id}/startcoaching:write · R1 · If-Match · Idempotency-Key/coaching/sessions/{id}/completecoaching:write · R1 · If-Match · Idempotency-Key/coaching/sessions/{id}/ai-insightscoaching:write · R2 · 202 · Idempotency-Key/closer-assist/sessionscoaching:read · R0 · cursor/closer-assist/sessions/{id}coaching:read · R0/roleplay/nichesroleplay:read · R0/roleplay/certificationsroleplay:read · R0/roleplay/certifications/{mode}/startroleplay:execute · R1 · If-Match · Idempotency-Key/roleplay/certifications/{mode}/completeroleplay:execute · R1 · If-Match · Idempotency-Key/roleplay/sessionsroleplay:execute · R2 · simulated/202 · Idempotency-Key/roleplay/sessionsroleplay:read · R0 · cursor/roleplay/sessions/{id}roleplay:read · R0/roleplay/sessions/{id}/messagesroleplay:execute · R2 · simulated/202 · Idempotency-Key/roleplay/sessions/{id}/endroleplay:execute · R2 · If-Match · Idempotency-Key/roleplay/sessions/{id}/scoreroleplay:read · R0/roleplay/sessions/{id}/scoreroleplay:execute · R2 · Idempotency-Key/supervisor/presencecoaching:read · R0 · owner/admin/supervisor/agents/{user_id}coaching:read · R0 · owner/admin/supervisor/agents/{user_id}/monitorcoaching:write · R2 · 202 · Idempotency-Key/supervisor/agents/{user_id}/monitor/endcoaching:write · R2 · Idempotency-Key/projectsprojects:read · R0 · offset/projectsprojects:write · R1 · Idempotency-Key/projects/{id}projects:read · R0 · project member/projects/{id}projects:write · R1 · admin · If-Match · Idempotency-Key/projects/{id}/archiveprojects:write · R2 · admin · If-Match · Idempotency-Key/projects/{id}/restoreprojects:write · R2 · admin · If-Match · Idempotency-Key/projects/{id}/membersprojects:read · R0 · member/projects/{id}/membersprojects:write · R2 · admin · If-Match · Idempotency-Key/projects/{id}/columnsprojects:read · R0 · member/projects/{id}/columnsprojects:write · R1 · admin · Idempotency-Key/projects/{id}/columns/{column_id}projects:write · R1 · admin · If-Match · Idempotency-Key/projects/{id}/columns/reorderprojects:write · R1 · admin · If-Match · Idempotency-Key/projects/{id}/tasksprojects:read · R0 · offset/projects/{id}/tasksprojects:write · R1 · Idempotency-Key/projects/{id}/tasks/{task_id}projects:read · R0 · member/projects/{id}/tasks/{task_id}projects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/moveprojects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/archiveprojects:write · R2 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/assigneesprojects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/labelsprojects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/checklistprojects:write · R1 · Idempotency-Key/projects/{id}/tasks/{task_id}/checklist/{item_id}projects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/checklist/{item_id}projects:write · R1 · If-Match · Idempotency-Key/projects/{id}/tasks/{task_id}/commentsprojects:read · R0 · member/projects/{id}/tasks/{task_id}/commentsprojects:write · R1 · Idempotency-Key/files/uploadsfiles:write · R1 · validated private intent · Idempotency-Key/files/{id}files:read · R0 · tenant-owned metadata/files/{id}/downloadfiles:read · R0 · resource-bound expiry/files/{id}/archivefiles:write · R1 · If-Match · Idempotency-Key/chat/userschat:read · R0/chat/roomschat:read · R0/chat/channelschat:write · R1 · admin · Idempotency-Key/chat/channels/{id}chat:read · R0 · room access/chat/channels/{id}chat:write · R1 · admin · If-Match · Idempotency-Key/chat/channels/{id}/archivechat:write · R1 · admin · If-Match · Idempotency-Key/chat/channels/{id}/memberschat:read · R0 · room access/chat/channels/{id}/memberschat:write · R1 · admin · Idempotency-Key/chat/dmschat:write · R1 · human actor · Idempotency-Key/chat/rooms/{id}/messageschat:read · R0 · room access · cursor/chat/rooms/{id}/messageschat:write · R1 · client UUID · Idempotency-Key/chat/messages/{id}chat:write · R1 · authorship · If-Match · Idempotency-Key/chat/messages/{id}chat:write · R1 · authorship/admin · If-Match · Idempotency-Key/chat/messages/{id}/reactionschat:write · R1 · Idempotency-Key/chat/rooms/{id}/readchat:write · R1 · Idempotency-Key/invoicesfinance:read · R0 · cursor/invoicesinvoices:write · R1 · draft · Idempotency-Key/invoices/{id}finance:read · R0/invoices/{id}invoices:write · R1 · If-Match · Idempotency-Key/invoices/{id}/issue/planinvoices:write · R2 · exact plan · Idempotency-Key/invoices/{id}/issueinvoices:write · R2 · approved plan · If-Match · Idempotency-Key/invoices/{id}/void/planinvoices:write · R3 · exact plan · Idempotency-Key/invoices/{id}/voidinvoices:write · R3 · approved plan · If-Match · Idempotency-Key/paymentsfinance:read · R0 · cursor/payments/{id}finance:read · R0/payments/record/planpayments:write · R2 · exact tenant payment plan · Idempotency-Key/paymentspayments:write · R2 · hosted/tokenized · Idempotency-Key/payments/{id}/refund/planpayments:write · R3 · exact plan · Idempotency-Key/payments/{id}/refundpayments:write · R3 · approved plan · If-Match · Idempotency-Key/subscriptionsfinance:read · R0 · cursor/subscriptions/{id}finance:read · R0/documentsfinance:read · R0 · cursor/documentsdocuments:write · R1 · draft · Idempotency-Key/documents/{id}finance:read · R0/documents/{id}/send/plandocuments:write · R2 · exact plan · Idempotency-Key/documents/{id}/senddocuments:write · R2 · approved plan · If-Match · Idempotency-Key/commissionscommissions:read · R0 · cursor/commissions/{id}commissions:read · R0/commissions/{id}commissions:write · R1 · If-Match · Idempotency-Key/commissions/{id}/approve/plancommissions:approve · R3 · exact plan/commissions/{id}/approvecommissions:approve · R3 · separate approver · Idempotency-Key/commissions/{id}/mark-paid/plancommissions:approve · R3 · exact plan/commissions/{id}/mark-paidcommissions:approve · R3 · separate approver · Idempotency-Key/commissions/bulk-mark-paid/plancommissions:approve · R3 · exact set/total plan/commissions/bulk-mark-paidcommissions:approve · R3 · separate approver · Idempotency-Key/phone-numbersphone_numbers:read · R0 · cursor/phone-numbers/{id}phone_numbers:read · R0/phone-numbers/searchphone_numbers:manage · R0 · provider read/phone-numbers/purchases/planphone_numbers:manage · R3 · plan/phone-numbers/purchasesphone_numbers:manage · R3 · approved · Idempotency-Key/phone-numbers/{id}/health-checkphone_numbers:manage · R2 · provider read/phone-numbers/{id}/health-historyphone_numbers:read · R0 · cursor/phone-numbers/local-presence-policyphone_numbers:read · R0/phone-numbers/local-presence-policyphone_numbers:manage · R2 · If-Match · Idempotency-Key/phone-numbers/{id}/replacement/planphone_numbers:manage · R3 · plan/phone-numbers/{id}/replacementphone_numbers:manage · R3 · approved · If-Match/phone-numbers/{id}/retire/planphone_numbers:manage · R3 · plan/phone-numbers/{id}/retirephone_numbers:manage · R3 · approved · If-Match/phone-numbers/{id}/quarantine/planphone_numbers:manage · R2 · plan/phone-numbers/{id}/quarantinephone_numbers:manage · R2 · If-Match · Idempotency-Key/receptionist/agentsreceptionist:read · R0 · cursor/receptionist/agentsreceptionist:write · R1 · Idempotency-Key/receptionist/agents/{id}receptionist:read · R0/receptionist/agents/{id}receptionist:write · R1 · If-Match · Idempotency-Key/receptionist/agents/{id}/activatereceptionist:write · R2 · If-Match/receptionist/agents/{id}/deactivatereceptionist:write · R2 · If-Match/receptionist/agents/{id}/config-versionsreceptionist:read · R0/receptionist/routesreceptionist:read · R0 · cursor/receptionist/routes/{phone_number_id}receptionist:write · R2 · If-Match · Idempotency-Key/receptionist/knowledge-sourcesreceptionist:read · R0 · cursor/receptionist/knowledge-sourcesreceptionist:write · R1 · Idempotency-Key/receptionist/knowledge-sources/{id}receptionist:read · R0/receptionist/knowledge-sources/{id}receptionist:write · R1 · If-Match · Idempotency-Key/receptionist/knowledge-sources/{id}/approvereceptionist:write · R2 · If-Match · Idempotency-Key/receptionist/agents/{id}/knowledgereceptionist:write · R1 · If-Match · Idempotency-Key/receptionist/sessionsreceptionist:read · R0 · cursor/receptionist/sessions/{id}receptionist:read · R0/receptionist/sessions/{id}/transcriptrecordings:read · R0/receptionist/sessions/{id}/handoffreceptionist:write · R2 · policy/usage gate/receptionist/analyticsanalytics:read · R0/formsforms:read · R0 · cursor/formsforms:write · R1 · Idempotency-Key/forms/{brand}forms:read/forms/{brand}forms:write · R1 · If-Match · Idempotency-Key/forms/{brand}/publishforms:write · R1 · If-Match · Idempotency-Key/forms/{brand}/unpublishforms:write · R1 · If-Match · Idempotency-Key/forms/{brand}/archiveforms:write · R1 · If-Match · Idempotency-Key/forms/{brand}/cloneforms:write · R1 · Idempotency-Key/forms/{brand}/revisionsforms:read · R0 · cursor/forms/{brand}/revisions/{revision_id}forms:read · R0/forms/{brand}/submissionsforms:submissions:read · R0 · cursor/forms/{brand}/submissions/{id}forms:submissions:read · R0/forms/{brand}/analyticsanalytics:read · R0/forms/{brand}/eventsforms:submit · R1 · 204 · Idempotency-Key/forms/{brand}/submissionsforms:submit/public-linksforms:read · R0 · cursor/public-links/{id}forms:write · R1 · If-Match · Idempotency-Key/analytics/application-funnelanalytics:read/analytics/dashboardanalytics:read · R0/analytics/funnelanalytics:read · R0/analytics/sourcesanalytics:read · R0 · cursor/analytics/velocityanalytics:read · R0 · cursor/analytics/attributionanalytics:read · R0 · cursor/analytics/cohortsanalytics:read · R0 · cursor/analytics/paid-performancemarketing:read · R0 · cursor/analytics/creativesmarketing:read · R0 · cursor/analytics/unit-economicsmarketing:read · R0 · cursor/analytics/data-qualityanalytics:read · R0 · cursor/analytics/attendanceanalytics:read · R0 · cursor/analytics/leaderboardanalytics:read · R0 · cursor/analytics/exportsanalytics:export · R1 · 202 · Idempotency-Key/tracking/eventsmarketing:configure · R1 · 200/201 · Idempotency-Key/tracking/conversion-eventsmarketing:configure · R1 · 200/201 · Idempotency-Key/commerce/eventsmarketing:configure · R1 · 200/201 · Idempotency-Key/tracking/events/{event_id}marketing:read · R0/marketing/connectionsintegrations:read · R0 · cursor/marketing/connections/{provider}/authorizeintegrations:write · R1 · hosted OAuth · Idempotency-Key/marketing/connections/{provider}/callbackintegrations:write · R1 · state/PKCE/nonce-bound callback/marketing/authorizations/{id}integrations:read · R0 · redacted status/marketing/connections/{id}integrations:read · R0 · redacted/marketing/connections/{id}/syncmarketing:configure · R2 · queued/simulated · Idempotency-Key/marketing/connections/{id}/disconnect/planintegrations:write · R3 · exact plan · Idempotency-Key/marketing/connections/{id}/disconnectintegrations:write · R3 · approved/simulated · Idempotency-Key/marketing/goal-mappingsmarketing:read · R0 · cursor/marketing/goal-mappings/{provider}marketing:configure · R1 · Idempotency-Key/marketing/consent-policiesmarketing:read · R0 · cursor/marketing/consent-policies/{brand_id}marketing:configure · R2 · Idempotency-Key/marketing/recommendationsmarketing:read · R0 · cursor/marketing/recommendations/{id}marketing:read · R0/marketing/recommendations/{id}/reviewmarketing:configure · R1 · Idempotency-Key/marketing/recommendations/{id}/execute/planmarketing:execute · R2 · quality/plan gate/marketing/recommendations/{id}/executemarketing:execute · R2 · queued/simulated · Idempotency-Key/marketing/actions/{id}/rollback/planmarketing:execute · R3 · prior-state plan/marketing/actions/{id}/rollbackmarketing:execute · R3 · approved/simulated · Idempotency-Key/marketing/actionsmarketing:read · R0 · cursor/marketing/forecastsmarketing:read · R0 · freshness warnings · cursor/marketing/forecastsmarketing:configure · R2 · queued/simulated · Idempotency-Key/marketing/identity/unresolvedmarketing:read · R0 · cursor/marketing/identity/correctionsmarketing:configure · R1 · redacted · Idempotency-Key/growth/stategrowth:read · R0 · entitlement/growth/brandsgrowth:read · R0 · cursor/growth/brandsgrowth:write · R1 · Idempotency-Key/growth/brands/{id}growth:read · R0/growth/brands/{id}growth:write · R1 · If-Match/growth/brands/{id}/assetsgrowth:write · R1 · bounded upload/growth/brands/{id}/assets/{role}growth:write · R1 · If-Match/growth/brands/{id}/topicsgrowth:read · R0 · cursor/growth/brands/{id}/topicsgrowth:write · R1 · Idempotency-Key/growth/brands/{id}/topics/suggestgrowth:generate · R2 · queued/simulated/growth/postsgrowth:read · R0 · cursor/growth/posts/generategrowth:generate · R2 · queued/simulated/growth/posts/{id}growth:read · R0/growth/posts/{id}growth:write · R1 · If-Match/growth/posts/{id}/enhancegrowth:generate · R2 · queued/simulated/growth/posts/{id}/approvegrowth:write · R1 · editorial only/growth/posts/{id}/rejectgrowth:write · R1 · editorial only/growth/posts/{id}/publish/plangrowth:publish · R3 · exact plan/growth/posts/{id}/publishgrowth:publish · R3 · approved/simulated/growth/posts/{id}/unpublish/plangrowth:publish · R2 · exact plan/growth/posts/{id}/unpublishgrowth:publish · R2 · approved/simulated/growth/metricsgrowth:read · R0/growth/brands/{id}/pipeline-healthgrowth:read · R0/growth/brands/{id}/index-healthseo:read · R0/growth/brands/{id}/niche-coverageseo:read · R0/growth/brands/{id}/cta-experimentsgrowth:read · R0/growth/brands/{id}/ai-visibilityseo:read · R0 · versioned evidence/growth/brands/{id}/backlinksseo:read · R0 · cursor/growth/brands/{id}/backlinks/{backlinkId}/reviewgrowth:write · R1 · If-Match/seo/connectionsseo:read · R0 · cursor/seo/connections/google/authorizeseo:configure · R1 · hosted OAuth/seo/connections/google/callbackseo:configure · R1 · state/PKCE/nonce-bound callback/seo/authorizations/{id}seo:read · R0 · redacted status/seo/connections/{id}/syncseo:configure · R2 · queued/simulated/seo/opportunitiesseo:read · R0 · cursor/seo/recommendationsseo:read · R0 · cursor/seo/google-updatesseo:read · R0/seo/recommendations/{id}/reviewseo:configure · R1 · If-Match/signalssignals:read · R0 · cursor/signals/{id}signals:read · R0/signals/{id}/convert-to-leadleads:write · R1 · idempotent conversion/prospect-packsleads:read · R0 · cursor/prospect-packs/requests/planleads:bulk · R3 · exact criteria/cost plan/prospect-packs/requestsleads:bulk · R3 · approved · queued/simulated/prospect-packs/requests/{id}leads:read · R0 · job state/usersusers:read · R0 · cursor/users/invitations/planusers:write · R2 · exact team_ids plan + approval/users/invitationsusers:write · R2 · 202 · Idempotency-Key/users/{id}users:read · R0/users/{id}users:write · R1 · If-Match · Idempotency-Key/users/{id}/disable/planusers:write · R3 · exact ownership/workload plan/users/{id}/disableusers:write · R3 · approved plan/users/{id}/enableusers:write · R1 · If-Match · Idempotency-Key/teamsteams:read · R0 · cursor/teamsteams:write · R1 · Idempotency-Key/teams/{id}teams:read · R0/teams/{id}teams:write · R1 · If-Match · Idempotency-Key/teams/{id}/membersteams:write · R1 · tenant membership/teams/{id}/archive/planteams:write · R2 · workload plan + approval/teams/{id}/archiveteams:write · R2 · workload/If-Match/workspaceworkspace:read · R0/workspaceworkspace:write · R1 · If-Match · Idempotency-Key/workspace/brandingworkspace:read · R0/workspace/brandingworkspace:write · R1 · allowlisted HTTPS logo/workspace/notification-policiesworkspace:read · R0 · typed/workspace/notification-policiesworkspace:write · R1 · typed destinations · If-Match or version · Idempotency-Key/workspace/usageworkspace:read · R0/workspace/entitlementsworkspace:read · R0/workspacesworkspace:read · agency-owned cursor/workspaces/planworkspace:write · R3 · exact plan/workspacesworkspace:write · R3 · approved/simulated/workspaces/{id}workspace:read · R0 · owned relationship/workspaces/{id}workspace:write · R1 · If-Match/workspaces/{id}/suspend/planworkspace:write · R3 · exact plan/workspaces/{id}/suspendworkspace:write · R3 · approved/simulated/domainsdomains:read · R0 · cursor/domainsdomains:write · R1 · Idempotency-Key/domains/{id}domains:read · R0/domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key/domains/{id}/remove/plandomains:write · R3 · exact plan/domains/{id}/removedomains:write · R3 · approved plan · 202/integrationsintegrations:read · R0 · opaque cursor · max 100/integrations/{provider}integrations:read · R0/integrations/{provider}/authorizeintegrations:write · R1 · server-bound OAuth state/integrations/{provider}/authorize/completeintegrations:write · R1 · bounded/redacted completion/integrations/{provider}/authorize/statusintegrations:read · R0 · redacted status/integrations/{provider}/syncintegrations:write · R2 · 202 · Idempotency-Key/integrations/{provider}/disconnect/planintegrations:write · R3 · exact plan/integrations/{provider}/disconnectintegrations:write · R3 · approved plan · 202/onboarding/stateworkspace:read · R0 · independent email_domains_cursor/integrations_cursor · max 100/onboarding/business-profileworkspace:write · R1 · If-Match/onboarding/texting-registrationworkspace:write · R3 · carrier plan/job/onboarding/texting-registrationworkspace:read · R0/onboarding/email-domainsdomains:write · R1 · Idempotency-Key/onboarding/email-domains/{id}/verifydomains:write · R2 · 202 · Idempotency-Key/settingsworkspace:read · R0 · typed/redacted/settingsworkspace:write · R1 · If-Match/billing/statebilling:read · R0/billing/usagebilling:read · R0 · minor units/billing/plansbilling:read · R0 · server catalog/billing/plan-changes/previewbilling:write · R3 · exact plan · Idempotency-Key/billing/plan-changesbilling:write · R3 · approved provider/simulation · 200 · Idempotency-Key/billing/topups/previewbilling:write · R3 · exact plan · Idempotency-Key/billing/topupsbilling:write · R3 · approved provider/simulation · 200 · Idempotency-Key/billing/portal-sessionsbilling:write · R1 · provider-hosted URL · Idempotency-Key/webhook-endpointsdeveloper:webhooks:read/webhook-endpointsdeveloper:webhooks:write/webhook-endpoints/{endpoint_id}developer:webhooks:read/webhook-endpoints/{endpoint_id}developer:webhooks:write/webhook-endpoints/{endpoint_id}developer:webhooks:write · R3 · policy · Idempotency-Key + If-Match/webhook-endpoints/{endpoint_id}/rotate-secretdeveloper:webhooks:write/webhook-endpoints/{endpoint_id}/deliveriesdeveloper:webhooks:read/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}developer:webhooks:read/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retrydeveloper:webhooks:write/workflows/{workflowId}/triggerworkflows:trigger/jobsdomain read scope/jobs/{job_id}domain read scope/jobs/{job_id}/canceloriginating execute scope/approval-requestsapprovals:read/approval-requestsapprovals:request/approval-requests/{approval_request_id}approvals:read/approval-requests/{approval_request_id}/cancelapprovals:request/audit-eventsaudit:read/audit-events/{audit_event_id}audit:read/developer/scopesdeveloper:credentials:admin/service-accountsdeveloper:credentials:admin/service-accountsdeveloper:credentials:admin/service-accounts/{service_account_id}developer:credentials:admin/service-accounts/{service_account_id}developer:credentials:admin/service-accounts/{service_account_id}/rotatedeveloper:credentials:admin/service-accounts/{service_account_id}/disabledeveloper:credentials:admin/service-accounts/{service_account_id}/enabledeveloper:credentials:admin/service-accounts/{service_account_id}/credentialsdeveloper:credentials:admin/service-accounts/{service_account_id}/credentialsdeveloper:credentials:admin/service-accounts/{service_account_id}/credentials/{credential_id}developer:credentials:admin/tagstags:read/tagstags:write · R1 · Idempotency-Key/tags/{tag_id}tags:read/tags/{tag_id}tags:write · R1 · If-Match/tags/{tag_id}/archivetags:write · R1 · If-Match/leads/{lead_id}/tagstags:read/leads/{lead_id}/tagstags:write · R1 · Idempotency-Key/deals/{deal_id}/tagstags:read/deals/{deal_id}/tagstags:write · R1 · Idempotency-Key/custom-fieldscustom_fields:read/custom-fieldscustom_fields:write · R1 · Idempotency-Key/custom-fields/{field_id}custom_fields:read/custom-fields/{field_id}custom_fields:write · R1 · If-Match/custom-fields/{field_id}/archivecustom_fields:write · R1 · If-Match/leads/{lead_id}/custom-fieldscustom_fields:read/leads/{lead_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key/deals/{deal_id}/custom-fieldscustom_fields:read/deals/{deal_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key/smart-lists/filter-schemasmart_lists:read/smart-listssmart_lists:read · cursor/smart-listssmart_lists:write · R1 · Idempotency-Key/smart-lists/previewsmart_lists:write · R0 · Idempotency-Key/smart-lists/{id}smart_lists:read/smart-lists/{id}smart_lists:write · R1 · If-Match/smart-lists/{id}smart_lists:write · R1 · If-Match/smart-lists/{id}/leadsleads:read · cursor/pipelinespipelines:read/pipelinespipelines:write · R1 · Idempotency-Key/pipelines/{id}pipelines:read/pipelines/{id}pipelines:write · R1 · If-Match/pipelines/{id}/archivepipelines:write · R1 · If-Match/pipelines/{id}/stagespipelines:write · R1 · Idempotency-Key/pipelines/{id}/stages/{stage_id}pipelines:write · R1 · If-Match/pipelines/{id}/stages/{stage_id}/archivepipelines:write · R1 · If-Match/pipelines/{id}/stages/reorderpipelines:write · R1 · If-Match/dealsdeals:read · R0 · cursor/dealsdeals:write · R1 · Idempotency-Key/deals/{id}deals:read · R0/deals/{id}deals:write · R1 · If-Match/deals/{id}/movedeals:write · R1 · If-Match/deals/{id}/wondeals:write · R1 · If-Match/deals/{id}/lostdeals:write · R1 · If-Match/deals/{id}/reopendeals:write · R1 · If-Match/deals/{id}/archivedeals:archive · R1 · If-Match/deals/{id}/restoredeals:archive · R1 · If-Match/deals/{id}/activitiesdeals:read · R0 · cursor/deals/{id}/activitiesdeals:write · R1 · Idempotency-Key/pipelines/{id}/boarddeals:read · R0 · cursor/pipelines/{id}/forecastanalytics:read · R0/taskstasks:read · R0 · cursor/taskstasks:write · R1 · Idempotency-Key/tasks/{id}tasks:read · R0/tasks/{id}tasks:write · R1 · If-Match/tasks/{id}/completetasks:write · R1 · If-Match/tasks/{id}/reopentasks:write · R1 · If-Match/tasks/{id}/archivetasks:write · R1 · If-Match/tasks/{id}tasks:write · R1 · If-Match/task-summarytasks:read · R0/calendar/entriestasks:read · R0 · cursor/calendar/entries/{id}tasks:read · R0/calendar/entriestasks:write · R1 · Idempotency-Key/calendar/entries/{id}tasks:write · R1 · If-Match/calendar/entries/{id}tasks:write · R1 · If-MatchCalls 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.
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.
/callsHuman or exactly approved policy context
GET/calls/{id}/recordingSigned, resource-bound recording access
POST/scripts/{id}/publishImmutable script version lifecycle
POST/voicemails/previewQueued or deterministic TTS preview
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.
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.
/call-queuesCursor-paginated queue list
POST/call-queues/{id}/start-nextPolicy-bound next-call job or simulation
POST/call-queues/{id}/pauseVersion-checked queue pause
GET/supervisor/presenceOwner/admin live-floor presence
POST/supervisor/agents/{user_id}/monitorConsent-bound monitor session
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.
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.
/phone-numbersPhone inventory and health
POST/phone-numbers/purchases/planPlan before provider mutation
POST/receptionist/agents/{id}/activateValidate and activate an agent
PUT/receptionist/routes/{phone_number_id}Assign a tenant-owned inbound route
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.
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.
/campaignsList tenant-owned definitions
POST/campaigns/{id}/launch/planPreview suppressions, usage, spend, and exact hashes
POST/campaigns/{id}/launchQueue the exact approved plan
GET/campaigns/{id}/analyticsRead aggregate delivery and outcome metrics
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.
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.
/meetingsHost/participant-safe meeting intent
POST/meetings/{id}/join-tokenShort-lived host/participant grant
GET/meetings/{id}/summaryArtifact-scope redacted summary
POST/meetings/{id}/send-notes/planEligibility, usage, and recipient-bound plan
POST/coaching/sessions/{id}/ai-insightsPaid-plan and usage-gated AI job
POST/roleplay/sessionsParticipant-bound synthetic simulation
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.
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.
/projectsOffset-paginated workspace boards
PUT/projects/{id}/membersProject-admin membership replacement
POST/projects/{id}/tasksTask/checklist/comment lifecycle
POST/files/uploadsValidated private upload intent
GET/files/{id}/downloadShort-lived actor/resource-bound URL
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.
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.
/chat/roomsList visible channels and DMs
POST/chat/channelsAdmin-only channel creation
POST/chat/rooms/{id}/messagesRetry-safe message send
PATCH/chat/messages/{id}Authorship-bound edit
POST/chat/messages/{id}/reactionsToggle an allowed reaction
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.
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.
/invoicesSigned-cursor minor-unit invoices
POST/invoices/{id}/issue/planExact recipient/amount/version plan
POST/invoices/{id}/voidApproved R3 plan with If-Match
POST/paymentsHosted/tokenized authoritative record
POST/documents/{id}/sendApproved send plan and simulated provider job
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.
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.
/commissionsCursor-paginated commission entries
PATCH/commissions/{id}Owner/admin correction with If-Match
POST/commissions/{id}/approve/planExact R3 approval plan
POST/commissions/bulk-mark-paid/planExact set/total mark-paid plan
POST/commissions/bulk-mark-paidSeparate-approver simulated execution
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.
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.
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.
/leads/importsUpload, validate, and preview
GET/leads/imports/{job_id}Read validation state
POST/leads/imports/{import_id}/commitQueue the validated commit
POST/leads/exportsQueue a CSV export
GET/leads/exports/{artifact_id}Inspect artifact metadata
GET/leads/exports/{artifact_id}/downloadAudit an artifact download
/leads/importsleads:bulk · R1 · 202Send 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.
| Field | Type | Contract |
|---|---|---|
| file required | CSV/TSV | UTF-8 upload; raw bytes are parsed and not retained by the public response. |
| mappings | JSON object | Source header to an allowlisted CRM field such as contact_email or contact_name. |
| Idempotency-Key required | header | 8–200 URL-safe characters; replay returns the original 202 response. |
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"}'
{
"data": {
"job_id": "job_01JIMPORT",
"status": "succeeded",
"resource_type": "lead_import",
"resource_id": "imp_01JIMPORT",
"simulated": true,
"import": { "counts": { "rows": 1, "valid": 1 } }
}
}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./leads/imports/{import_id}/commitleads:bulk · R1 · 202Send 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.
/leads/exportsanalytics:export · R1 · 202Provide 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.
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"}'
{
"data": {
"job_id": "job_01JEXPORT",
"status": "queued",
"resource_id": "art_01JEXPORT",
"artifact": { "status": "pending", "download_url": null }
}
}workspace_id, credential data, internal provider columns, storage keys, raw URLs, or an unbounded Excel buffer./leads/exports/{artifact_id}analytics:export · R0Inspect 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.
/leads/exports/{artifact_id}/downloadanalytics:export · R0 · auditedThe 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.
brand_idCall 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.
/scheduling/brandsList booking brand IDs and allowed event types
GET/scheduling/event-typesInspect event types and their brands
GET/scheduling/availabilityCheck the chosen brand and event type
POST/scheduling/bookingsCreate under that exact brand
/scheduling/brandsscheduling:readReturns 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.
curl https://leadtrackerai.com/api/v1/scheduling/brands \
-H "Authorization: Bearer $LEADTRACKER_API_KEY"{
"data": [{
"id": 17,
"identifier": "acme-consulting",
"name": "Acme Consulting",
"event_type_ids": [42],
"routing_mode": "round_robin",
"active_calendar_count": 2
}]
}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.
/scheduling/brandsChoose a booking brand first
GET/scheduling/event-typesList active event types
GET/scheduling/availabilityRead live availability
POST/scheduling/bookingsCreate a booking
/scheduling/event-typesscheduling:readReturns active event types and their scheduling constraints.
curl https://leadtrackerai.com/api/v1/scheduling/event-types \
-H "Authorization: Bearer $LEADTRACKER_API_KEY"{
"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.
/scheduling/availabilityscheduling:read| Query parameter | Type | Description |
|---|---|---|
| brand_id required | integer | The intended brand's id from /scheduling/brands. It must allow the selected event type. |
| event_type_id required | integer | An ID returned by the event types endpoint. |
| start_date required | YYYY-MM-DD | First calendar date to inspect. |
| end_date required | YYYY-MM-DD | Last calendar date to inspect. Ranges may be up to 31 days. |
| routing_key | string | A 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_id | integer | Optional known LeadTracker user. If that active closer belongs to the brand pool, they remain pinned instead of consuming a round-robin turn. |
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"
{
"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.
/scheduling/bookingsscheduling:write| Body field | Type | Description |
|---|---|---|
| brand_id required | integer | The intended brand's id from /scheduling/brands. Reuse the value sent to availability. |
| event_type_id required | integer | The active LeadTracker AI event type. |
| routing_key | string | The 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_id | integer | Optional known closer override. Otherwise an existing active lead closer is preserved, then the brand round robin is used. |
| start required | ISO 8601 UTC | The exact slot start returned by availability. |
| attendee.name required | string | Prospect name. |
| attendee.email or attendee.phone required | string | At least one contact method. Phone is recommended for SMS reminders. |
| attendee.timezone required | Canonical IANA timezone | For example America/Chicago or Asia/Dubai. Fixed aliases such as EST and numeric offsets are rejected. |
| source | string | Your integration label, such as vapi or retell. |
| external_reference | string | Your call, conversation, or booking identifier for reconciliation. |
| metadata | object | Optional integration context, stored with the booking. Maximum 16 KB. |
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" } }'
{
"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
}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_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.
/scheduling/bookingsscheduling:read| Query field | Type | Description |
|---|---|---|
| Exact attendee email filter. | ||
| status | string | Booking status filter, such as scheduled or cancelled. |
| from | string | Lower date/time bound in the existing scheduler filter format. |
| to | string | Upper date/time bound in the existing scheduler filter format. |
curl "https://leadtrackerai.com/api/v1/scheduling/bookings?status=scheduled" \
-H "Authorization: Bearer $LEADTRACKER_API_KEY"{
"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" }
}]
}Read a booking
/scheduling/bookings/{booking_id}scheduling:readUse the LeadTracker AI booking ID returned when an appointment is created. The record is only accessible within the API key's workspace.
curl https://leadtrackerai.com/api/v1/scheduling/bookings/ltbk_9c7bd1... \
-H "Authorization: Bearer $LEADTRACKER_API_KEY"Reschedule a booking
/scheduling/bookings/{booking_id}/reschedulescheduling:writeLeadTracker AI validates the requested slot again, updates the connected calendar event and native meeting, and re-evaluates reminder delivery.
{
"start": "2026-07-16T16:00:00.000Z",
"reason": "Caller requested a later time"
}Cancel a booking
/scheduling/bookings/{booking_id}/cancelscheduling:writeCancelling removes the provider event when connected, stops pending reminders, clears the active appointment from the CRM lead, and retains the booking history.
{
"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.
/leadsList up to 50 recent leads/leads/search?q=... | email=... | phone=...Find a specific lead/leads/{lead_id}Read one lead/leads | /leads/upsertCreate or match a lead/leads/{lead_id}Update CRM-safe fields/leads/{lead_id}/notes | /activitiesAdd CRM history/leads/upsertleads:writeProvide an email or phone to match an existing record. Every lead mutation requires Idempotency-Key.
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.
/tagstags:read · R0 · cursor/tagstags:write · R1 · Idempotency-Key/tags/{tag_id}tags:read · R0/tags/{tag_id}tags:write · R1 · Idempotency-Key + If-Match/tags/{tag_id}/archivetags:write · R1 · Idempotency-Key + If-Match/leads/{lead_id}/tagstags:read · R0/leads/{lead_id}/tagstags:write · R1 · Idempotency-Key/deals/{deal_id}/tagstags:read · R0/deals/{deal_id}/tagstags:write · R1 · Idempotency-Key/custom-fieldscustom_fields:read · R0 · cursor/custom-fieldscustom_fields:write · R1 · Idempotency-Key/custom-fields/{field_id}custom_fields:read · R0/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key + If-Match/custom-fields/{field_id}/archivecustom_fields:write · R1 · Idempotency-Key + If-Match/leads/{lead_id}/custom-fieldscustom_fields:read · R0/leads/{lead_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key/deals/{deal_id}/custom-fieldscustom_fields:read · R0/deals/{deal_id}/custom-fields/{field_id}custom_fields:write · R1 · Idempotency-Key| Contract | Exact behavior | Error taxonomy |
|---|---|---|
| Reads | R0, 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 |
| Mutations | R1, 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 safety | Lead 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. |
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]}'
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.
/smart-lists/filter-schemasmart_lists:read · R0/smart-listssmart_lists:read · R0 · cursor/smart-listssmart_lists:write · R1 · Idempotency-Key/smart-lists/previewsmart_lists:write · R0 · Idempotency-Key/smart-lists/{id}smart_lists:read · R0/smart-lists/{id}smart_lists:write · R1 · Idempotency-Key + If-Match/smart-lists/{id}smart_lists:write · R1 · Idempotency-Key + If-Match/smart-lists/{id}/leadsleads:read · R0 · cursorinvalid_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.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.
/pipelinespipelines:read · R0/pipelinespipelines:write · R1 · Idempotency-Key/pipelines/{id}pipelines:read · R0/pipelines/{id}pipelines:write · R1 · Idempotency-Key + If-Match/pipelines/{id}/archivepipelines:write · R1 · Idempotency-Key + If-Match/pipelines/{id}/stagespipelines:write · R1 · Idempotency-Key/pipelines/{id}/stages/{stage_id}pipelines:write · R1 · Idempotency-Key + If-Match/pipelines/{id}/stages/{stage_id}/archivepipelines:write · R1 · Idempotency-Key + If-Match/pipelines/{id}/stages/reorderpipelines:write · R1 · Idempotency-Key + If-Matchpipeline_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.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.
/dealsdeals:read · R0 · cursor/dealsdeals:write · R1 · Idempotency-Key/deals/{id}deals:read · R0/deals/{id}deals:write · R1 · If-Match/deals/{id}/movedeals:write · R1 · If-Match/deals/{id}/wondeals:write · R1 · If-Match/deals/{id}/lostdeals:write · R1 · If-Match/deals/{id}/reopendeals:write · R1 · If-Match/deals/{id}/archivedeals:archive · R1 · If-Match/deals/{id}/restoredeals:archive · R1 · If-Match/deals/{id}/activitiesdeals:read · R0 · cursor/deals/{id}/activitiesdeals:write · R1 · Idempotency-Key/pipelines/{id}/boarddeals:read · R0 · cursor/pipelines/{id}/forecastanalytics:read · R0value.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.| Contract | Exact behavior | Errors |
|---|---|---|
| Transitions | Only 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 |
| Concurrency | Send 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 |
| Outcomes | Marking 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 safety | Reuse 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 |
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.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" }'
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.
/conversationsList workspace conversations (cursor)/conversations/{id}Read one safe conversation projection/conversations/{id}/messagesList messages and delivery state (cursor)/conversations/{id}/send-eligibilityExplain DNC, opt-out, quiet-hours, entitlement, and usage checks/conversations/{id}/messagesQueue an outbound message — Idempotency-Key/conversations/{id}/messages/scheduleSchedule an outbound message — Idempotency-Key/conversations/{id}/messages/{message_id}/replyReply to an inbound message — Idempotency-Key/suppression/statusRead masked suppression state/suppression/requestsRecord a workspace suppression request — Idempotency-Key/conversations/inboundStore an inbound channel message/conversations/inbound-callsStore an inbound call transcript or outcome/conversations/{id}/messagesconversations:send · R2 · 202Send 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.
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."}'
{
"data": {
"status": "queued",
"simulated": true,
"outbox_id": "mout_01JABC"
},
"request_id": "req_01JABC"
}suppressed message with no provider job or outbox row. Duplicate idempotency keys replay the original result without charging usage twice./conversations/inbound-callsconversations:writeSupply 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.
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.
/formsList owned forms (cursor)/formsCreate a draft form — forms:write/forms/{brand}Fetch the saved form definition/forms/{brand}Save a versioned draft — If-Match/forms/{brand}/publishPublish a draft — If-Match/forms/{brand}/unpublishUnpublish without deleting submissions/forms/{brand}/archiveArchive while retaining history/forms/{brand}/cloneClone into a new tenant-owned brand/forms/{brand}/revisionsList immutable revisions (cursor)/forms/{brand}/revisions/{revision_id}Read one immutable revision/forms/{brand}/submissionsList explicit PII-safe submissions (cursor)/forms/{brand}/submissions/{id}Read one explicit PII-safe submission/forms/{brand}/analyticsRead aggregate funnel analytics/forms/{brand}/eventsAppend a funnel event · Idempotency-Key · 204 replay/forms/{brand}/submissionsValidate and submit a completed form/public-linksList owned public links (cursor)/public-links/{id}Update link routing — If-Match/forms/acme/submissionsforms:submitThe 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.
lt_live_ key in a browser embed. Use LeadTracker AI's public hosted journey for client-side pages.Hosted links and custom domains
Every workspace gets stable hosted URLs for its public journey, and a workspace with an active custom link domain serves all of them on its own hostname — the API shapes below tell you which URL to publish.
/r/{slug}Stable CTA redirect — normalizes attribution, then lands on the journey. Safe to hardcode behind a website button./formVanity entry on a custom link domain only — serves the domain’s journey in place; the visitor’s address bar stays on /form. Append ?demo=1 for test mode./schedule/{slug}The rendered journey itself. Append ?demo=1 for the zero-write test mode.serialized CTA payloadsreferenceWherever the platform serializes a public CTA (the wizard state, journey form responses), it returns liveUrl ({base}/r/{slug}), testUrl (demo mode), and formUrl — the vanity {base}/form link, present only when the workspace has an active custom link domain. Publish formUrl when it exists, else liveUrl.
app.yourdomain.com). Once active, application forms, booking pages, video rooms, and recording links are all generated on that hostname. Attribution query parameters (utm_*, seo_source, landing_page) are read by the journey on whichever entry path is used — /form and /r/{slug} both carry them through. The REST API base URL is unaffected — always call https://leadtrackerai.com/api/v1.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.
/analytics/application-funnel?days=30&brand=acmeanalytics:readdays 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.
/analytics/dashboardanalytics:read · aggregate summary/analytics/funnelanalytics:read · aggregate stages/analytics/sourcesanalytics:read · cursor/analytics/velocityanalytics:read · cursor/analytics/attributionanalytics:read · model + currency basis · cursor/analytics/cohortsanalytics:read · model + currency basis · cursor/analytics/paid-performancemarketing:read · cursor/analytics/creativesmarketing:read · cursor/analytics/unit-economicsmarketing:read · cursor/analytics/data-qualityanalytics:read · freshness/coverage · cursor/analytics/attendanceanalytics:read · cursor/analytics/leaderboardanalytics:read · cursor/analytics/exportsanalytics:export · queued/202 · Idempotency-Key/tracking/eventsmarketing:configure · deduplicated · Idempotency-Key/tracking/conversion-eventsmarketing:configure · authoritative outcomes stay server-side/commerce/eventsmarketing:configure · minor-unit currency · Idempotency-Key/tracking/events/{event_id}marketing:read · workspace-scoped projectionamount_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.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.
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.
/marketing/connectionsList redacted provider connections
POST/marketing/connections/{provider}/authorizeStart hosted OAuth authorization
GET/marketing/connections/{provider}/callbackComplete state/PKCE/nonce-bound OAuth
GET/marketing/authorizations/{id}Read redacted authorization status
POST/marketing/connections/{id}/syncQueue a sync job or disabled-effects simulation
POST/marketing/connections/{id}/disconnect/planBind exact connection state before disconnect
POST/marketing/recommendations/{id}/execute/planRecheck freshness, coverage, and policy
POST/marketing/recommendations/{id}/executeExecute exact approved plan
POST/marketing/actions/{id}/rollback/planBind exact prior provider state
POST/marketing/actions/{id}/rollbackExecute exact rollback or simulation
GET/marketing/forecastsRead forecast projections and warnings
POST/marketing/forecastsQueue a forecast job
POST/marketing/identity/correctionsRecord a redacted identity correction
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.
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.
/growth/brandsList entitled tenant brands
POST/growth/posts/generateQueue metered generation or deterministic simulation
POST/growth/posts/{id}/approveEditorial transition without publish side effects
POST/growth/posts/{id}/publish/planBuild exact quality-gated publish plan
POST/growth/posts/{id}/publishExecute approved plan or disabled-effects simulation
GET/growth/brands/{id}/index-healthRead freshness and index health
GET/growth/brands/{id}/ai-visibilityRead complete panels with consulted-versus-cited source lineage and no false zeros
POST/seo/connections/google/authorizeStart server-owned OAuth with PKCE
GET/seo/connections/google/callbackComplete state/PKCE/nonce-bound OAuth
GET/seo/authorizations/{id}Read redacted authorization status
POST/seo/connections/{id}/syncQueue an SEO sync job or simulation
GET/seo/opportunitiesRead bounded opportunities with cursor pagination
GET/seo/recommendationsRead bounded recommendations
seo:configure only for approved configuration actions and eligible subscription verification. An unavailable billing or provider configuration check cannot enable an external action.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.
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.
/signalsCursor-paginated high-intent signals
POST/signals/{id}/convert-to-leadIdempotent signal-to-lead conversion
POST/prospect-packs/requests/planExact R3 criteria and cost plan
POST/prospect-packs/requestsApproved durable request or deterministic simulation
GET/prospect-packs/requests/{id}Request, pack, and job state
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.
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.
/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
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.
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.
/domainsCursor-paginated custom domains
POST/domainsProvider-backed domain job or simulation
POST/domains/{id}/verifyDNS verification job or simulation
POST/domains/{id}/remove/planExact dependency-aware R3 plan
POST/domains/{id}/removeApproved removal job or simulation
GET/integrationsSafe provider status list
POST/integrations/{provider}/authorizeServer-bound PKCE authorization
POST/integrations/{provider}/authorize/completeBounded authorization completion
GET/integrations/{provider}/authorize/statusRedacted authorization status
POST/integrations/{provider}/syncDurable sync job or simulation
POST/integrations/{provider}/disconnect/planExact dependency-aware R3 plan
POST/integrations/{provider}/disconnectApproved disconnect job or simulation
GET/onboarding/stateBusiness, carrier, email-domain, and integration state
PATCH/onboarding/business-profileTyped profile with If-Match
POST/onboarding/texting-registrationExact carrier plan or registration job
GET/onboarding/texting-registrationSafe carrier registration state
POST/onboarding/email-domainsEmail sending domain job or simulation
POST/onboarding/email-domains/{id}/verifyEmail DNS verification job
GET/settingsAllowlisted typed settings
PATCH/settingsTyped settings with If-Match
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.
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.
/billing/stateSafe subscription and billable state
GET/billing/usageUsage and quotas in minor units
GET/billing/plansCurrent server-owned catalog
POST/billing/plan-changes/previewExact R3 catalog/proration plan
POST/billing/plan-changesApproved plan execution or simulation
POST/billing/topups/previewExact R3 usage-credit plan
POST/billing/topupsApproved top-up execution or simulation
POST/billing/portal-sessionsProvider-hosted portal URL
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.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.
/workflowsList definitions and statuses
PUT/workflows/{id}/nodesReplace a typed, validated graph
POST/workflows/{id}/trigger/planBind the exact graph and version
POST/workflows/{id}/test-runQueue a deterministic simulation
GET/workflow-runs/{id}/stepsInspect redacted run steps
POST/workflow-runs/{id}/retryRetry with original effect lineage
/workflows/{workflow_id}/triggerworkflows:triggerThe 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.
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.
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.
/jobsR0 · domain read scope · cursor/jobs/{job_id}R0 · domain read scope/jobs/{job_id}/cancelR1 · originating execute scope · Idempotency-Key/approval-requestsR0 · approvals:read · cursor/approval-requestsR1 · approvals:request · Idempotency-Key/approval-requests/{approval_request_id}R0 · approvals:read/approval-requests/{approval_request_id}/cancelR1 · approvals:request · Idempotency-Key/audit-eventsR0 · audit:read · cursor/audit-events/{audit_event_id}R0 · audit:read| Operation | Scope / risk | Idempotency and approval | Stable errors |
|---|---|---|---|
GET /jobs | domain_readR0 | Signed cursor bound to workspace, route, and filters | invalid_api_key, invalid_access_token, insufficient_scope, invalid_request, invalid_filter, invalid_cursor, rate_limited |
GET /jobs/{job_id} | domain_readR0 | None | invalid_api_key, invalid_access_token, insufficient_scope, resource_not_found |
POST /jobs/{job_id}/cancel | originating_executeR1 | Required Idempotency-Key; cancellation is only allowed for cancellable jobs | idempotency_key_required, idempotency_key_reused, resource_not_found, job_not_cancellable, invalid_state_transition |
GET /approval-requests | approvals:readR0 | Signed cursor; callback evidence is omitted | invalid_filter, invalid_cursor, rate_limited |
POST /approval-requests | approvals:requestR1 | Required Idempotency-Key; server-generated operation plan only | unknown_field, idempotency_key_reused, resource_not_found, approval_mismatch, approval_expired |
GET /approval-requests/{approval_request_id} | approvals:readR0 | Cross-workspace IDs return resource_not_found | resource_not_found, insufficient_scope |
POST /approval-requests/{approval_request_id}/cancel | approvals:requestR1 | Required Idempotency-Key; initiator or owner may cancel | idempotency_key_reused, resource_not_found, insufficient_role, invalid_state_transition |
GET /audit-events | audit:readR0 | Signed cursor and bounded filters | invalid_filter, invalid_cursor, rate_limited |
GET /audit-events/{audit_event_id} | audit:readR0 | Redacts authorization, OAuth, API-key, callback, and provider secrets | resource_not_found, insufficient_scope |
curl https://leadtrackerai.com/api/v1/jobs?limit=50 \
-H "Authorization: Bearer $LEADTRACKER_API_TOKEN"
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.
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.
/developer/scopesR0 · developer:credentials:admin/service-accountsR0 · cursor/service-accountsR1 · Idempotency-Key/service-accounts/{service_account_id}R0 · metadata only/service-accounts/{service_account_id}R1 · Idempotency-Key + If-Match/service-accounts/{service_account_id}/rotateR3 · Idempotency-Key + If-Match/service-accounts/{service_account_id}/disableR3 · Idempotency-Key + If-Match/service-accounts/{service_account_id}/enableR1 · Idempotency-Key + If-Match/service-accounts/{service_account_id}/credentialsR0 · cursor · metadata only/service-accounts/{service_account_id}/credentialsR3 · one-time client_secret/service-accounts/{service_account_id}/credentials/{credential_id}R3 · Idempotency-Key + If-Match| Operation | Grantability | Safety contract | Stable errors |
|---|---|---|---|
GET /developer/scopes | Owner/admin only | Returns exact server-owned scope definitions and grantable subset | insufficient_role, insufficient_scope, resource_access_denied |
POST /service-accounts | Requested scopes must be grantable | Required Idempotency-Key; no secret is created or returned | invalid_request, unknown_field, idempotency_key_reused |
PATCH /service-accounts/{service_account_id} | Owner/admin grant set | Required Idempotency-Key and current If-Match | precondition_required, version_conflict, insufficient_scope |
POST /service-accounts/{service_account_id}/rotate | Owner/admin grant set | R3; exact ETag and idempotency; bounded overlap; one-time secret reveal | invalid_state_transition, version_conflict, resource_not_found |
POST /service-accounts/{service_account_id}/disable | Owner/admin only | R3; revokes issued access tokens; final owner account is protected | resource_in_use, precondition_required, version_conflict |
POST /service-accounts/{service_account_id}/credentials | Subset of account grant | R3; secret appears once and replay never re-reveals it | invalid_request, invalid_state_transition, idempotency_key_reused |
DELETE /service-accounts/{service_account_id}/credentials/{credential_id} | Owner/admin only | R3; revokes tokens; the final recovery credential and final owner automation credential are protected | resource_in_use, precondition_required, version_conflict |
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"]}'
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.
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.
/webhook-endpointsR0 · developer:webhooks:read · no key/webhook-endpointsR1 · developer:webhooks:write · Idempotency-Key/webhook-endpoints/{endpoint_id}R0 · developer:webhooks:read · no key/webhook-endpoints/{endpoint_id}R1 · developer:webhooks:write · Idempotency-Key + If-Match/webhook-endpoints/{endpoint_id}R3 · developer:webhooks:write · policy · Idempotency-Key + If-Match/webhook-endpoints/{endpoint_id}/rotate-secretR3 · developer:webhooks:write · Idempotency-Key + If-Match/webhook-endpoints/{endpoint_id}/deliveriesR0 · developer:webhooks:read · cursor/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}R0 · developer:webhooks:read · no key/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retryR1 · developer:webhooks:write · Idempotency-Key| Operation | Scope / risk | Idempotency and precondition | Errors |
|---|---|---|---|
GET /webhook-endpoints | developer:webhooks:readR0 | None | invalid_api_key, insufficient_scope, invalid_endpoint_id, resource_not_found, rate_limited |
POST /webhook-endpoints | developer:webhooks:writeR1 | Required Idempotency-Key; replay returns the original projection without a secret | invalid_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:readR0 | None | invalid_api_key, insufficient_scope, invalid_endpoint_id, resource_not_found, rate_limited |
PATCH /webhook-endpoints/{endpoint_id} | developer:webhooks:writeR1 | Required Idempotency-Key and current If-Match | invalid_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:writeR3 · policy | Policy evaluation, required Idempotency-Key and current If-Match | invalid_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-secret | developer:webhooks:writeR3 | Required Idempotency-Key and current If-Match | invalid_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}/deliveries | developer:webhooks:readR0 | Opaque cursor pagination; no key | invalid_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:readR0 | None | invalid_api_key, insufficient_scope, invalid_endpoint_id, invalid_delivery_id, resource_not_found, rate_limited |
POST /webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/retry | developer:webhooks:writeR1 | Required Idempotency-Key | invalid_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 |
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"]}'
{
"data": { "id": "wep_01JABCDEF1234567", "version": 1 },
"signing_secret": "whsec_one_time_value"
}
// Replay and GET/list responses omit signing_secret.
{
"data": {
"id": "whd_01JABCDEF1234567",
"event_type": "deal.updated",
"status": "delivered",
"event": { "api_version": "2026-08-14", "data": { "object": { "id": 91 } } }
}
}
If-Match: "wep_...:1"versioned writesConfiguration 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.
booking.createdNative booking was confirmedbooking.rescheduledNative booking time changedbooking.cancelledNative booking was cancelledbooking.no_showAttendance was marked no-showYour configured HTTPS endpointHMAC SHA-256LeadTracker 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.
| Header | Description |
|---|---|
| X-LeadTracker-Event | The booking event name. |
| X-LeadTracker-Event-Id | Stable event identifier for receiver de-duplication. |
| X-LeadTracker-Timestamp | Unix timestamp in seconds. |
| X-LeadTracker-Signature | v1= + 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.
brand_id is not a positive integer.{
"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.
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.