Skip to content
DocsUnitley Docs home
REST API reference

Errors

Every error the Unitley REST API can send, its HTTP status, what it means, and whether to retry the call or fix the request first.

Every failed REST call answers with an HTTP error status and one JSON object, error. The codes are the same for every tool.

Over MCP, a tool that fails returns the same code, message and issues in its result, marked isError. A request the MCP server refuses before any tool runs gets a JSON-RPC error instead. See The MCP server.

The error envelope

FieldWhat it holds
codeWhat went wrong, as one of the codes below. Branch on this.
messageA sentence written to be shown to a person. For bad arguments, it names the first problem.
issuesEvery problem the check against the tool's schema found, each with a path (the field, with nested fields joined by dots) and a message. A few argument problems are found after that check, such as a to before from (to: The end of the range is before its start.) or a page cursor that is not valid. Those name the field in message and leave issues empty, as other errors do. The exception is the game in log_bet: a gameId that is not on the schedule (not_found) or is in another sport (invalid_input) has one issue, on gameId.
retryAfterSecondsHow many seconds to wait. Sent with rate_limited only.

Write your code against code, not the wording of message, and show message to the person using your app.

Every code

CodeStatusMeaning
invalid_input400The arguments or the body are wrong. The message says how, and issues lists what the schema check found.
invalid_tokenREST only401No token, or one that is unknown, revoked or expired. Comes in the error envelope, with a WWW-Authenticate challenge.
invalid_tokenMCP only401The same token problems over MCP. The body is an OAuth error, not the envelope: error is invalid_token and error_description holds the message, which the WWW-Authenticate challenge repeats.
insufficient_scope403A write tool called with a read-only token. WWW-Authenticate names the scope it needs: scope="write".
forbidden403The request reached a host that does not serve the API, or came from another site in a browser.
not_found404The game, bet or pick does not exist or is not yours, or a tool that sizes a stake finds no bankroll set up.
unknown_tool404There is no tool by that name.
payload_too_large413The body is over 256 KB.
unsupported_media_type415The body is not sent as application/json.
limit422A rule refused the request, such as a date range or a page that is too large.
rate_limited429A budget is spent for now. retryAfterSeconds and the Retry-After header say when to try again.
internal500Something failed on Unitley's side. Try again in a moment.
unavailable503Unitley could not serve the call just then, as when its database is out of reach. Try again in a moment.

Examples

A bad argument: calc_implied_probability with odds of 50, which American odds cannot be.

400 · americanOdds of 50
{
  "error": {
    "code": "invalid_input",
    "message": "americanOdds: American odds must be +100 or more, or -100 or less.",
    "issues": [
      {
        "path": "americanOdds",
        "message": "American odds must be +100 or more, or -100 or less."
      }
    ]
  }
}

A tool that saves to your account, called with a read-only token:

403 · log_bet with a read-only token
HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer realm="unitley", error="insufficient_scope", scope="write"
Content-Type: application/json

{
  "error": {
    "code": "insufficient_scope",
    "message": "log_bet saves to your account, and this access token is read-only. Create a token with write access on the Connect page to use it.",
    "issues": []
  }
}

Authentication challenges

A token problem comes with a WWW-Authenticate header that says what is wrong:

WhenStatusWWW-Authenticate
No token, or one not shaped like a Unitley token401 invalid_tokenBearer realm="unitley"
A token that is unknown, revoked or expired401 invalid_tokenBearer realm="unitley", error="invalid_token"
A read-only token calling a tool that saves403 insufficient_scopeBearer realm="unitley", error="insufficient_scope", scope="write"

The MCP server answers a refused token differently. Both 401s carry Bearer error="invalid_token", error_description="…" with the message, and the body is {"error":"invalid_token","error_description":"…"} rather than the envelope. A read-only token calling a tool that saves gets no challenge there: the tool's result is the insufficient_scope error. See The MCP server.

The messages say what to do:

  • No token: "Send a Unitley access token as Authorization: Bearer unt_... (create one on the Connect page)."
  • A dead token: "This access token is unknown, revoked or expired. Create a new one on the Connect page."
  • The wrong scope: the tool's name, then "saves to your account, and this access token is read-only. Create a token with write access on the Connect page to use it."

Create tokens on the Connect page. See Tokens and security.

Retry-After

Every 429 rate_limited answer has a Retry-After header, in seconds, and the same number in retryAfterSeconds. The message ends with the wait in words, such as "Try again in a minute."

  • "Too many requests." means the per-address budget is spent.
  • "Too many tool calls." means your per-token or per-user budget is spent.
  • "jev_classify is limited to" means that tool's own budget is spent.
  • "Jev is busy." means TypeSafe asked Unitley to wait.

Budgets count in fixed windows that reset on the clock. A call made before the wait is over is refused again and still counts, and it does not bring the reset any closer. See Rate limits.

Retry or fix

Some errors go away if you wait. The rest come back until you change the request.

Fix the request first

CodeWhat to do
invalid_inputFix what issues and message name, or the body. Sending the same call again gets the same answer.
unsupported_media_typeSend the arguments as JSON, with Content-Type: application/json.
payload_too_largeSend a smaller body. It must be 256 KB or less.
unknown_toolCheck the name against the tool list. Names are case-sensitive.
not_foundCheck the id. Get game ids from get_week_slate, and bet ids from get_bet_log. With no bankroll set up, calc_kelly_stake and save_recommendation ask you to set one up first.
limitChange the request as the message says, such as a shorter date range, or delete old picks to make room.
insufficient_scopeUse a token with write access.
invalid_tokenCheck the header. If the token was revoked or has expired, create a new one.
forbiddenSend the request to https://console.unitley.com/api/v1/tools from a server or script, not from a browser on another site.

Wait and retry

CodeWhat to do
rate_limitedWait for Retry-After, then send the call again.
unavailableTry again in a moment. If the message asks you to add or replace a key, as jev_classify does when no TypeSafe key is saved, do that first.
internalTry again in a moment. If it keeps failing, wait longer between tries.

21+ · Gambling problem? Call 1-800-GAMBLER or visit ncpgambling.org

Unitley is an analysis tool, not a sportsbook: it takes no bets and holds no money. Nothing in these docs is a guarantee or financial advice. Only bet where it is legal for you. Unitley is not affiliated with the NFL, its teams, or any sportsbook.

©︎ 2026 Unitley · Analysis, not a guarantee.