REST API
Read and write your CRM data from your own systems. Create a key in Settings, then call the JSON API over HTTPS.
- Create keys in Settings under API keys. Choose read-only or read-and-write. The token (csk_…) is shown once and stored hashed; revoke a key at any time and it stops working immediately.
- Authenticate every request with a header:
Authorization: Bearer csk_… - Resources:
/api/v1/companies,/api/v1/contacts,/api/v1/leadsand/api/v1/deals. Each supports GET (list), POST (create), and GET or PATCH on/api/v1/<resource>/<id>. - Product usage: POST to
/api/v1/usagewith a read-and-write key to feed the customer health score shown on each company. Send one object or an array of up to 500, each{"company_id": "…", "metric": "activity", "count": 1, "occurred_at": "…"}. Onlycompany_idis required:metricdefaults toactivity,countto 1, andoccurred_atto the time of the call. A 202 comes back withacceptedand arejectedlist naming any company id the workspace does not hold, so a partial batch tells you which rows landed. - Workspaces with the Contracts module also get
/api/v1/agreementsand/api/v1/obligations. These are read-only: GET a list or GET one by id. A POST or PATCH returns 405, and a workspace without the module gets 403 saying so. The register is evidence about your contracts, so it is not somewhere an integration should be able to write. - The API returns the facts about the paper and keeps the contract text and citation quotes in the app. Fetch a document from the app when you need the paper itself.
- On an obligation,
owed_by(ours,theirs,mutual,unsure) andsurvives_termination(yes,no,unsure) andextraction_confidence(high,medium,low) can all be null, and null means NOTHING HAS ANSWERED: either the row was read before that field existed, or the reading judged the row is not a duty anyone performs. Null is not the same as no. Treating it as a negative is the exact mistake those fields exist to prevent, so branch on the value explicitly. - Lists return newest first with cursor pagination: pass
?limit=50and follownext_cursoruntil it is null. - A cursor is opaque, server-sealed and short-lived: read it as a token to hand straight back, not as a value to parse, store or build. A
422 Malformed cursormeans that one is no longer usable, so start the collection again from the first page. - Bodies are JSON. Field names are snake_case in responses; creates and updates accept the same fields you see in the app, including
customfor your custom fields. Deal amounts are major units ("amount": "12500"); responses carryamount_minor. - Every write made with a key is recorded on the workspace ledger under that key's identity, so API activity audits exactly like a person's.
- Errors are JSON too:
{"error":{"message":"…"}}with conventional status codes (401 bad key, 403 read-only key writing or a module you do not have, 404 not found, 405 writing to a read-only resource, 422 validation). - Prefer no-code? The web-to-lead capture endpoint accepts form submissions without a key, and CSV import and export cover bulk moves.