API overview¶
Every Trilocore API call is an HTTPS request to https://api.trilocore.ai, carrying one
Authorization: Bearer header. There is no separate API host, no per-service hostname, and
no SDK requirement — the API is plain HTTP and JSON.
See Authentication for how to obtain a token.
Base URL and versioning¶
| Base URL | https://api.trilocore.ai |
| Product surface | /api/v1/<group>/… |
| Transport | HTTPS only, HTTP/1.1 and HTTP/2 |
| Request and response bodies | application/json (errors use application/problem+json) |
The version lives in the path, not in a header. v1 is the only version currently served, and
it is additive: new endpoints, new optional request fields and new response fields may appear at
any time. Treat unknown response fields as forgiving — do not fail a parse on a field you have
not seen before.
A single front door serves the whole product. It authenticates the caller once, applies rate limits, quota and idempotency, and forwards the request to the service that owns the resource. Which service that is shows up in the reference as the endpoint's upstream; it is an implementation detail, not something you address directly.
The resource model¶
The API is a resource API, not an RPC API. Three consequences are worth internalising before you write a client:
Identifiers live in the path. A call names the thing it acts on — POST
/api/v1/workspaces/{workspace_id}/attestations — rather than passing an operation name and an id
in a body. On the auditing surface the front door additionally validates each path parameter's
shape before forwarding, so a malformed address or transaction hash is rejected with
400 validation_failed instead of reaching a service.
Most creates answer 201; exactly one adds a Location. Many POSTs answer
201 Created, and the per-endpoint tables in the endpoint reference state
which. Only POST /api/v1/bevm/scans is promoted by the front door to 201 with a
Location header and an X-Resource-Id, because that is the one route where the gateway itself
derives the identifier. Everywhere else, read the id out of the response body — do not write a
client that depends on Location, because it will be absent.
Some operations are custom methods. Where an action does not map onto a noun, the path ends
in :verb — POST /api/v1/bevm/snapshots:restore, POST /api/v1/bevm/storage-slots:write,
POST /api/v1/public/attestations/verify. The colon may be sent raw or percent-encoded as
%3A; both resolve identically.
Beyond that:
- Pagination is not uniform, so check per endpoint. The auditing surface
(
/api/v1/bevm/*) emits an RFC 8288Linkheader — followrel="next"rather than constructing offsets — and spells its cursorpage_token, withpage_sizealongside it. The workspace and Contract IDE surfaces do not emitLink; the workspace collections take a plainlimit. Treat "noLinkheader" as "this collection does not paginate that way", never as "there are no more results". - Conditional requests work end to end.
If-None-MatchandIf-Matchare forwarded to the owning service, andETag,Cache-ControlandVarycome back. Use them for polling: a304still counts as a request, but it saves you transferring and re-parsing an unchanged body. - Some auditing singletons accept
current. Several/api/v1/bevm/*resources are singletons keyed by the caller, and there the literalcurrentmay stand in for the id to mean "mine" — which is how a first-time caller addresses a resource that has no id yet. This is a property of the auditing surface only: on/api/v1/workspaces/*and the other prefixes an id must be a real UUID, andcurrentfails the matcher. - Unknown resources answer
404, never403. An identifier that exists but is not yours is indistinguishable from one that does not exist. This is deliberate: it stops the API confirming that another tenant's resource exists.
The machine-readable specification¶
An OpenAPI 3.1.0 document is served publicly and needs no authentication:
It is generated from the same routing table that serves traffic, so it cannot drift from the
endpoints it covers. It is cacheable (Cache-Control: public, max-age=300) and CORS-open, so a
browser tool can fetch it directly.
The served specification is partial — do not treat it as the whole API
The document expands one product group only: the auditing endpoints under
/api/v1/bevm/sessions and its siblings. That is 137 paths and 153 operations out of the 363
the API actually serves.
Architecture, Contract IDE, workspaces, projects, activity, contracts, audits, invitations,
notes and the public verification endpoints are not in its paths object — several appear
only as one-line prefix annotations, and the rest are absent entirely.
Generating a client from this file therefore gives you a client for less than half the API. The endpoint reference covers all of it, and is the source to work from if you need the full surface.
What this API does not serve¶
Documenting an endpoint that does not answer is worse than omitting it, so two absences are stated plainly rather than left for you to discover:
- The model plane at
/v1/is mounted but not in service. Unlike the surfaces below, this prefix is routed — an unauthenticated request to it answers401rather than404, which can easily read as "this exists and my token is wrong". It does not currently serve traffic: an authenticated request fails at the upstream. Do not build against it. - The fork platform, billing and webhook-receiver surfaces are not mounted at all. They
return
404because no route exists. They are built but not deployed, and there is no behaviour to integrate with today.
Where to go next¶
| Authentication | Bearer keys, browser sessions, CSRF, and the headers the front door strips |
| Idempotency | The 13 endpoints that require Idempotency-Key, and replay semantics |
| Errors | RFC 9457 problem documents and the full code catalogue |
| Rate limits and quota | x-ratelimit-* headers, 429 handling, daily quota |
| Endpoint reference | Every live endpoint, by group |