Base URL
The envelope
Every response is wrapped:error.code, never on error.message. See Errors.
Objects
Authentication
Bearer token on every request.
The credential’s form selects the Loom mode: a JWT is direct, anything else is relay. See Authentication.
Headers
Versioning
Public endpoints live under/v1. Breaking changes get a new prefix; additive fields may appear on existing objects without one.
Agent ids pin one exact version, so a published agent’s behaviour does not change under you.
Pagination
Every collection is paginated the same way. Passlimit and cursor; read pagination beside data.
Walk a collection by following
next_cursor until has_more is false, at which point next_cursor is null. Cursors are stable under writes: new rows arriving mid-walk will not shift a page and cause you to skip or repeat a row, which is why there is no page or offset, and no total count.
Messages are ordered oldest-to-newest within the page, while the pages themselves walk backwards from the most recent — so opening a thread costs one request, and following the cursor loads older history.
Idempotency
Send anIdempotency-Key on any POST and the call becomes safe to retry. The key is yours to choose; a UUID per logical operation is the usual shape. Our SDKs generate one for every POST automatically.
The first request with a given key does the work and its response is stored. A retry with the same key returns that stored response, carrying Idempotency-Replayed: true — it does not run again, and it does not charge again.
A replay is still a request, so it appears in your activity log with
Idempotency-Replayed. It is left out of the Identify dashboard’s counts, which report lookups performed and therefore match what you were charged.
Keys are scoped to your workspace and expire after 24 hours. Without a key, a POST behaves as it always has: repeating it repeats the work, so POST /v1/identify re-resolves and charges again, and a second POST …/messages starts a second turn.
Rate limits and credits
Requests are metered per workspace — all API keys share one allowance. Every response carriesRateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset; a rejection is 429 with Retry-After.
Credits are prepaid and spent per run. An empty balance returns 402. See Rate limits and credits.