Skip to content

Help

Markdown

Errors and rate limits

Errors come as JSON with a stable error code and a message written for a person:

{ "error": "auth_required", "message": "This tool needs a TerraLab account. Connect TerraLab in your assistant's settings; see https://terra-lab.ai/mcp." }

Branch on error, never on message: the wording can change.

HTTP errors

StatuserrorMeaningWhat to do
400invalid_inputThe body is not a JSON object of the tool arguments.Fix the request body.
400bad_requestThe request could not be read.Check the JSON and the headers.
401auth_requiredNo key or token was sent.Send Authorization: Bearer <key>.
401invalid_tokenThe key or token is invalid, revoked or expired.Create a new key, or let the agent sign in again.
401access_revokedThe app was disconnected from the dashboard.Reconnect the agent.
402balance_requiredThe free calls of the month are used, or the operation is paid, and the balance is empty.Add funds; the answer carries hint and account_url.
404not_foundThere is no such API path.Check the URL.
404unknown_toolNo tool has that name.List tools with GET /v1/tools.
405method_not_allowedTools are called with POST.Use POST.
413too_largeThe request body is too large.Send a smaller file or fewer features.
429rate_limitedToo many requests in the last minute.Wait for Retry-After seconds, then retry.
429daily_limitThe account reached its daily safety ceiling.Retry the next day (UTC) or write to support.
503unavailableThe account service did not answer.Retry after Retry-After seconds.

Tool errors

A tool that runs but cannot answer returns 200 with isError: true. Its structuredContent then carries code, message and, most of the time, a hint saying what to change: a place it could not find, an area too large, a country it does not cover.

{
  "structuredContent": { "code": "...", "message": "...", "hint": "..." },
  "content": [{ "type": "text", "text": "..." }],
  "isError": true
}

What is counted

A call that fails or finds nothing is not counted: the free call or the amount taken from the balance is given back. Only answers with a result count.

Rate limits

Every account can make 60 calls a minute. Past it, the API answers 429 with Retry-After: 60. Spread batch jobs over time, and retry with a growing delay:

import time
import requests

def call(url, headers, body, attempts=5):
    for attempt in range(attempts):
        response = requests.post(url, headers=headers, json=body, timeout=120)
        if response.status_code not in (429, 503):
            return response
        time.sleep(int(response.headers.get("Retry-After", 2 ** attempt)))
    return response

Retry only 429 and 503. A 401 or 402 will not pass on a second try.

Updated 2026-10-27