Errors and limits
What the server says when it refuses, and how to tell the kinds apart.
The shape of a refusal
A non-OK response carries { error } and often more: tier, limit, current_running, hint. The error string is a CODE, not a sentence, and it is what to branch on. The message beside it is in English or, in older refusals, in Italian.
The codes worth handling
tier_forbidden (403): the plan does not include it, with the tier and a hint. tron_limit_reached (409): the plan holds no more trons, with count, limit and plans_url. awake_limit_reached (409): too many of your trons awake at once. machine_full (409): the machine is at its cap of trons awake; try later. concurrent_limit_reached (429), with current_running. daily_uptime_exhausted (429): the Free day is used up. indexing_quota_exhausted (413): the documents quota is full. 429 Too Many Requests, from the rate limiter. A queued job that finds too many of your trons awake waits and retries; it does not fail.
401 is not always expiry
A 401 on /auth/* means the code was wrong or stale. A 401 anywhere else means the session is gone. Treating them the same turns a typo into a sign-out.
What is public
GET /plans, GET /mcp-registry (the catalogue of MCP servers) and everything under /public (the public API and the public MCP server, next chapter) need no token. Everything else does, including every discover route.