Skip to main content
Every Custral endpoint speaks the same shape. Learn it once and the rest of the reference is just which fields come back.

The base URL and the surface

/v1 is the entire public API. Anything you can reach from the SDK, the CLI, or MCP goes through it. Other paths on that host serve Custral’s own apps, aren’t versioned, and change without notice. Don’t build against them.

Making a request

Authenticate with an API key as a bearer token, and send JSON:
See Authentication for creating and scoping keys.

The response envelope

Every response (success or failure) is an object with a reqId. On success the payload is under data:
On failure there is no data; there’s an error with a stable machine-readable code:
Branch on the code, never on the human-readable message. Messages are written for people and get reworded. The full list is in Errors.
Log the reqId. It identifies one specific request end-to-end. Quoting it in a support message is the difference between us finding your failure in seconds and asking you to reproduce it.

Lists and paging

A list endpoint puts the rows in data.data, alongside the counts and cursors that describe the page:

Cursor paging is the one to use

Pass the previous response’s nextCursor back as cursor, and stop when it comes back null:
limit / offset also work, but offsets drift while you page: a record created or deleted mid-walk shifts every later row, so you can miss records or see one twice. Use offset for a one-off jump to a known position; use cursor for anything that walks a whole object.

Narrowing a list

filter, sort, and q narrow a list before it’s paged, so they change what total and the cursors describe. See Records for the filter grammar.

Ids

Every id is a prefixed, URL-safe string: rec_ records, obj_ objects, conv_ conversations, req_ requests. The prefix tells you what a thing is, so log ids as-is rather than stripping it. Ids are opaque: treat them as strings, don’t parse them, and don’t assume a length. Where an endpoint takes an object it also accepts the object’s human-readable key (contacts) in place of its obj_… id.
Ids identify things, they don’t describe them, a rec_… is not something to show a person. Resolve it to the record’s name before it reaches your UI.

Conventions worth knowing

  • Partial updates. PATCH touches only the keys you send. Sending null clears a field; omitting it leaves it alone.
  • Writes are forgiving, reads are canonical. On the way in, a field key may be a property’s key, its display name, or its id. Reads always come back keyed by key. See How the schema works.
  • Computed fields are read-only. formula and rollup values are recalculated on read; sending one is ignored.
  • Unknown fields are rejected, not dropped, so a typo surfaces as an error instead of silently doing nothing.

What’s next

Authentication

Create an API key and scope it.

How the schema works

Objects, properties, records, and fields.

Errors

Every code the API can return.

Records

The endpoints you’ll use most.