API Reference

The Tonic Desk API is a JSON REST API for reading and writing your CRM data from scripts, integrations, and AI tools.

Machine-readable spec: OpenAPI 3.1 (openapi.json) — also served live at https://app.tonicdesk.com/api/v1/openapi.json. If you're pointing an AI tool at this API, give it that file.

Connecting an AI assistant? See Connect AI to Tonic Desk (MCP) for a copy-paste setup.

Authentication

Create an API key in Settings → API Keys inside Tonic Desk (you need the settings permission on your account; keys are only ever created from inside the logged-in app). The key is shown once — store it in a secrets manager, never in code or a repo.

Send it on every request, either way works:

Authorization: Bearer crm_YOUR_KEY
X-API-Key: crm_YOUR_KEY

Keys are scoped to your organisation: the API can only ever see your own org's data. Keys can be revoked instantly from the same settings screen, and revoking a user's account revokes their keys with it.

Scopes

Every key carries a scope list, chosen at creation:

  • Read-only (recommended, the default) — every read: scope; all GET endpoints work, nothing can be modified.
  • Full access — read plus write:contacts, write:companies, write:deals, write:activities, write:tasks.

A call outside the key's scopes returns 403 with "code": "insufficient_scope" and the scope it needed. Objects added to the API after a key was created aren't in that key's scope list — issue a fresh key to pick them up.

Base URL

https://app.tonicdesk.com/api/v1

Endpoints

ResourceMethodsNotes
/contacts · /contacts/:idGET, POST, PUT/PATCH, DELETE?search= name/email; single GET includes custom_fields
/contacts/:id/timelineGETFull activity history for one contact
/companies · /companies/:idGET, POST, PUT/PATCH, DELETE?search= name; create is dedup-guarded (returns the existing company + already_existed: true instead of a duplicate)
/companies/:id/timelineGET
/deals · /deals/:idGET, POST, PUT/PATCH, DELETE?pipeline_id=; amounts, stages, close dates
/deals/:id/move-stagePOST{"stage_id": …}
/deals/:id/close-won · /close-lostPOSTOptional {"reason": "…"}
/deals/:id/reopenPOST
/deals/:id/timelineGET
/activities · /activities/:idGET, POSTCalls, emails, meetings, notes; ?type=
/notesGET, POSTSugar over activities with type note; filter by contact_id/company_id/deal_id
/tasks · /tasks/:idGET, POST, PUT/PATCH, DELETE?status=
/pipelinesGETPipelines with ordered stages
/tags · /users · /custom-fields · /segmentsGETDirectory objects (read-only)
/segments/:id/contactsGETMembers of a segment
/searchGET?q= across contacts, companies, deals; contacts also match by linked-company name

Full request/response shapes, parameters, and per-endpoint scopes are in the OpenAPI spec.

Pagination

All list endpoints take ?page= and ?per_page= (default 25, max 100) and return:

{
  "data": [ ... ],
  "meta": { "page": 1, "per_page": 25, "total": 142, "pages": 6, "has_next": true, "has_prev": false }
}

Incremental sync

Every list endpoint accepts ?updated_since=<ISO 8601 datetime>. Results are then ordered (updated_at, id) ascending so pages stay stable while you walk them — poll with the timestamp of the last record you processed instead of re-downloading everything.

Updates are partial

PUT and PATCH are equivalent: only the fields you send change.

Errors

{ "error": "Human-readable message", "code": "machine_readable_code" }
StatuscodeMeaning
401missing_api_key / invalid_api_keyNo key, or key invalid/revoked/expired
403insufficient_scopeKey lacks the required scope (included in the response)
400invalid_requestBad parameter (message says which)
400invalid_referenceA contact_id/company_id/deal_id/owner you referenced doesn't exist in your org
404Record not found (or soft-deleted)
429rate_limitedSlow down; the Retry-After header says how long

Rate limits

60 requests per minute per API key. 429 responses carry a Retry-After header (seconds). If you need sustained higher throughput, use updated_since to pull incrementally rather than re-listing.

Quick test

curl -H "Authorization: Bearer crm_YOUR_KEY" \
  "https://app.tonicdesk.com/api/v1/pipelines"