ReferenceErrors

Errors

Auth errors, scope errors, and MCP tool error kinds returned by the Zoop API.

When something goes wrong with a Zoop API call, the error comes from one of two places: the auth layer checks your credentials before anything runs, and the tool layer runs your requested action after auth passes. Knowing which layer failed tells you exactly what to fix.


Auth-layer errors

Auth errors happen before Zoop runs your tool — your credentials didn't check out. The response uses a JSON-RPC error envelope (a standard response wrapper with a jsonrpc, id, and error field). Because the request never reached the tool, id is always null.

Error envelope shape

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32001,
    "message": "Unauthorized"
  }
}

When extra context is available — for example, which scopes (permissions) your token is missing — it appears in an error.data field:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32002,
    "message": "Insufficient scope",
    "data": {
      "required": ["write:jobs"]
    }
  }
}

Auth error reference

HTTP statuserror.codeerror value in auth layerWhen it happens
401-32001missing_tokenNo Authorization header, or the value does not start with Bearer .
401-32001invalid_tokenThe token is not a recognized Zoop API key and not a valid JWT, or the JWT failed signature/issuer/audience verification. See reason below.
401-32001revokedReserved — in practice a revoked API key returns invalid_token with reason key_revoked (see the reasons table below).
401-32001expiredThe credential has passed its expiry time.
403-32002insufficient_scopeThe token is valid but does not carry all scopes the endpoint requires. The error.data.required array lists the missing scopes.
403-32002wrong_tenantThe token belongs to a different tenant than the one being addressed.
429-32003rate_limitedToo many requests. A Retry-After header is present with the number of seconds to wait.

All 401 errors share the same JSON-RPC code (-32001). The HTTP response body does not tell you which sub-kind you hit — use the error value column in the table above and match the fix to your situation.

invalid_token reasons

When the error is invalid_token, Zoop records an internal reason code. This code does not appear in the HTTP response — you won't see it in your app. It does appear in server logs and audit events, so it's useful when working with Zoop support to diagnose a persistent failure. Common values:

ReasonWhat it means
unrecognized_prefixThe token value is not a Zoop API key and does not look like a JWT (JSON Web Token, the format used for OAuth access tokens).
key_not_foundThe API key prefix is recognized but no matching record exists in the database.
key_revokedThe key exists but has been revoked.
missing_user_idThe API key references a user but has no user_id — this indicates a corrupted key record. Contact support.
invalid_tenant_idThe JWT tenant_id claim is not a valid UUID.
malformed_jwt_headerThe JWT header could not be decoded — the token may be truncated or corrupted.
unsupported_algThe JWT uses a symmetric algorithm (HS256, etc.). Zoop only accepts asymmetric OAuth tokens (ES256, RS256).
missing_subThe JWT payload has no sub claim — the token is malformed.
missing_tenant_idThe JWT payload has no tenant_id claim — the token is malformed.
no_valid_tenant_membershipThe user tied to this API key is not an active member of the tenant.

401: missing or invalid token

Check that your Authorization header is present and correctly formatted:

Authorization: Bearer zoop_uk_<rest of key>

The full key — including the zoop_uk_ or zoop_tk_ prefix — must be present. If you are using an OAuth access token, make sure the JWT was issued by the correct authorization server and has not been modified in transit.

401: revoked or expired

A revoked key cannot be restored. Go to Settings → API & MCP and create a new API key. For an expired OAuth access token, use your refresh token to get a new access token.

See API keys and OAuth for details.

403: insufficient scope

Your token is valid but is missing a permission (scope) that the tool requires. The error.data.required array lists exactly which scopes you need to add:

{
  "jsonrpc": "2.0",
  "id": null,
  "error": {
    "code": -32002,
    "message": "Insufficient scope",
    "data": {
      "required": ["write:jobs", "read:customers"]
    }
  }
}

You cannot add scopes to an existing API key. Revoke the current key, then create a new one with the required scopes selected. For OAuth tokens, re-authorize the user with the additional scopes. See Scopes for the full scope catalog.

403: wrong tenant

Your API key belongs to a different Zoop account (tenant) than the one you're calling. Double-check that you're using the right key for this account.

429: rate limited

You've sent too many requests too quickly. Wait the number of seconds given in the Retry-After response header, then try again:

# The Retry-After header value is in seconds
Retry-After: 30

See Rate limits for per-credential and per-tenant limits.

WWW-Authenticate header

On 401 responses, Zoop includes a WWW-Authenticate header. OAuth 2.0 clients can follow the URL in that header to auto-discover the authorization server, supported scopes, and token endpoint:

WWW-Authenticate: Bearer realm="zoop", resource_metadata="https://app.zoop.example/.well-known/oauth-protected-resource"

If you're using a simple API key, you can ignore this header.


Tool-layer errors

Once your credentials pass, Zoop runs the tool you called. If the tool itself fails, the HTTP status is still 200 — but the response body signals the failure with isError: true and a plain-English message in content[0].text.

Tool error envelope shape

Tool errors appear inside the normal tools/call result, not as a top-level JSON-RPC error object:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "Resource not found."
      }
    ],
    "isError": true
  }
}

Always check isError in your code — a 200 status does not mean the tool succeeded.

Tool error kinds

KindWhen it happensTypical fix
invalid_inputThe arguments you passed do not match the tool's input schema (wrong type, missing required field, value out of range).Check the tool's parameter definitions and correct your input.
not_foundThe record you referenced (by ID or slug) does not exist in this tenant's data.Confirm the ID is correct and belongs to the current tenant.
conflictThe operation would create a duplicate of something that must be unique (for example, a customer with an email address already in use).The message text describes what already exists.
insufficient_scopeThe token passed auth but the specific tool being called requires a scope the token does not hold.The message names the required scopes. Re-issue the token with those scopes.
internalAn unexpected database or application error occurred.Retry once. If the error persists, contact support with your request ID.

The insufficient_scope tool error is a second scope check that runs inside the tool itself, separate from the auth-layer check. If you already passed auth, this error is rare — it can appear when a tool needs a very specific child scope that a broader umbrella scope doesn't include.

invalid_input detail

The invalid_input response always contains the same fixed message, regardless of which field is wrong:

{
  "type": "text",
  "text": "Invalid input. Check the schema."
}

Zoop does not tell you which field failed. When you see this error, go back to the tool's parameter definitions and check every required field, its type, and any allowed values — the response won't name the offending field for you.

conflict detail

The conflict message is a plain English sentence that describes what already exists. Read it directly:

{
  "type": "text",
  "text": "Already exists"
}

Quick-reference: error layers

LayerWhenHTTP statusResponse shape
AuthBefore any tool runs401, 403, 429JSON-RPC error object at top level, id: null
ToolInside tool execution200JSON-RPC result with isError: true
TransportUnhandled server fault (rare)200JSON-RPC error object, code -32603, id: null