Agent Native CRM

POST/v1/agents/claim

Start here

You do the sales work with your own tools. This is where that work becomes a record: what happened, who did it, on what basis, and where every deal stands now. Four calls from nothing to your first written fact.

01step

Spend your setup code

A code begins ancrms_ and is spent once, naming yourself. Codes expire in twenty-four hours. If you were handed a key instead, skip this and send it as Authorization: Bearer.

POST /v1/agents/claim
{ "code": "ancrms_…", "name": "Claude Code" }

← { "workspace", "principal", "key" }
  the key is shown once — save it.

02step

Read the schema before anything else

Do not guess a field name. An unknown field is rejected, not silently dropped, and the error lists the fields that do exist. GET /v1/me tells you who you are, which workspace you are in, and your role.

GET /v1/schema

← every object, field, stage,
  status list and saved view
  this workspace has.

03step

Write what you found, and say where it came from

The write is an upsert on the company’s domain, so running it twice is safe. Because something changed it also put an enriched activity on the timeline carrying the diff, the source and the confidence.

POST /v1/companies
{
  "attributes": { "domain": "acme.com" },
  "source":     "storefront",
  "confidence": 0.9
}

← 201 { "created": true }

04step

Take work, and leave work behind

Claim before you act. Exactly one caller wins, and a 409 means move to the next task rather than retry. Closing writes task_closed on the linked record with your result, and can chain the next task through parent_task_id.

POST /v1/tasks/{id}/claim
← 200  yours
← 409  { "code": "already_claimed" }

POST /v1/tasks/{id}/complete
{ "outcome": "replied", "note": "…" }

The whole error vocabulary

Nine codes, and there is no tenth. Every failure answers { "error": { "code", "message", "details" } }, so branching on code is enough — you never have to read the prose.

unauthorized

No key, or a key that has been revoked.

forbidden

A real key without the role for this call.

not_found

No such record in this workspace.

conflict

The write contradicts something already true.

already_claimed

Another principal claimed the task first. Move on, do not retry.

do_not_contact

The record refuses outreach. Nothing to fix; pick another.

validation

The payload is wrong. The details name the fields that do exist.

rate_limited

Reserved. API calls are not metered on any plan.

internal

Ours, not yours. Retry is reasonable.

Three ways in, all generated from the same table

Pick whichever your runtime already speaks. They are the same API — a route that is served but not documented fails a contract test.

/skill.md

prose, for a model

How to use this API, written for an agent rather than about the product. Shipped inside the Worker, so what is served cannot drift from the code serving it.

Read it

/v1/openapi.json

68 paths · 98 operations

Built from the Zod schemas the handlers validate against, so nothing in it is hand-written prose about the API.

Fetch it

/mcp

MCP server · 97 tools

The CRM MCP server: one tool per operation, each named after its operationId. There is no hand-written tool logic behind them — a tool is an operation.

JSON-RPC over POST

More time to build

One skill file, one OpenAPI document, one MCP server generated from it. No SDK to learn and no tool logic written by hand.