Overview
One base URL, two credential types, one response envelope.
Everything goes through the gateway — a single authenticated front door. You never address an engine directly; the gateway resolves your project's engine and proxies to it.
Base URL
The public ThinkingRoot gateway is:
https://api.thinkingroot.comEvery SDK, AI tool, and API call uses this host. (In the Console's own
configuration it is the value of NEXT_PUBLIC_GATEWAY_URL / GATEWAY_URL,
which is set to this same URL.)
The gateway exposes a few families of path:
| Prefix | Purpose | Auth |
|---|---|---|
/engine/* | The engine REST API (/api/v1/...) for your project | tr_sk_… key |
/mcp/sse, /mcp | MCP transport | tr_sk_… key |
/v1/projects/{id}/keys | API key management | session JWT |
/v1/projects/{id}/secrets | Secrets vault | session JWT |
/v1/projects/{id}/egress | Egress allowlist | session JWT |
/identity/*, /billing/*, /provisioner/* | Control-plane services (transparent passthrough) | session JWT |
So an engine call is "$GATEWAY" + "/engine" + "/api/v1/...".
The response envelope
Every engine REST response is a uniform envelope:
{ "ok": true, "data": { /* typed payload */ }, "error": null }
{ "ok": false, "data": null, "error": { "code": "…", "message": "…" } }Clients check ok, read data on success, and surface error.code /
error.message on failure. (The Console's engineGetData / enginePostData
helpers do exactly this.)
404 means empty, not broken
Per the honesty contract, a not-found from a downstream service is treated as an
empty list, not a 500. Absence is represented as empty data, never as
fabricated rows.