> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goosybear.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and refusals

> Every refusal a caller can meet, what each one means, and which ones are about you rather than about us.

Refusals come from **two different places**, and telling them apart is the whole
trick to debugging quickly.

* **The door.** A request that never reached an action — no key, access switched
  off, too fast, no such action — answers a `4xx` with an `error` object.
* **The answer.** A request that got through the door and reached the action
  answers `200`, and the `ok` field says how it went. A declined action is still
  a `200` with `"ok": false` and a reason.

**So branch on `ok`, not on the status code.** If you would rather not read the
body, the `x-goosy-tool-error` header carries `true` or `false` on every
dispatched call.

## Refused at the door

```json theme={null}
{ "error": { "code": "tenant_api.unauthenticated", "message": "…" } }
```

| Status | Code                           | What it means                                                                                                                                               | Who fixes it                                                         |
| ------ | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `401`  | `tenant_api.unauthenticated`   | No usable key. Missing, mistyped, revoked and expired all answer **identically** — on purpose, so the endpoint cannot be used to find out which keys exist. | You — check the key, or create a new one                             |
| `403`  | `api_access.platform_disabled` | Programmatic access is off across the whole platform. Nothing about your account or your key.                                                               | Us — contact support                                                 |
| `403`  | `api_access.account_disabled`  | Programmatic access is switched off for your account. Every key stops at once.                                                                              | An account Owner or Admin                                            |
| `403`  | `api_access.capability_denied` | Your key is fine, but you do not hold **Use the API and MCP**.                                                                                              | An Owner or Admin, under Settings → Members & invites                |
| `403`  | `tenant_mcp.surface_disabled`  | The API and MCP surface is not open for your account yet. Not your key, not your permissions.                                                               | Us                                                                   |
| `400`  | `tenant_api.malformed_body`    | The body was not a JSON object. Send `{}` when an action takes no arguments.                                                                                | You                                                                  |
| `400`  | `tenant_mcp.batch_too_large`   | An assistant sent too many messages in one request. Send them one at a time.                                                                                | Your client                                                          |
| `404`  | `tenant_api.unknown_tool`      | No action by that name. The answer deliberately names nothing, so it cannot be used to probe for actions.                                                   | You — check the spelling in the [reference](/api-reference/overview) |
| `429`  | `tenant_mcp.rate_limited`      | Over this key's per-minute cap. Wait for `Retry-After`.                                                                                                     | You — see [Rate limits](/api/rate-limits)                            |

<Warning>
  **`401` never tells you which credential problem you had.** A revoked key, an
  expired one, a typo and a key that never existed all answer the same words. If
  you are unsure, look at the key's row under **Settings → API & MCP** — it shows
  the status and when it was last used.
</Warning>

## Refused by the action

These answer `200` with `"ok": false`, a `code`, and a plain-language `message`.

| Code                        | What it means                                                                                                                                                                                  |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `workspace_ambiguous`       | Your key reaches several workspaces and nothing chose one. The reply lists them. See [Choosing a workspace](/api/workspace-context).                                                           |
| `workspace_unreachable`     | The workspace you named is not one this key reaches — or the key is narrowed to a different one.                                                                                               |
| `workspace_set_unsupported` | You asked for a group of workspaces. Pass a single workspace instead.                                                                                                                          |
| `invalid_arguments`         | The arguments did not match what the action takes. The reply lists which fields, so you rarely need the reference to fix it.                                                                   |
| `tool_capability_unbound`   | The action changes something, and the permission that would decide who may do that over the API does not exist yet — so it is closed to every key. **Not about your credential or your role.** |
| *the action's own codes*    | Anything specific to what you asked for — a board that is not there, an item that does not exist. The message says which.                                                                      |

An `invalid_arguments` reply points at the field:

```json theme={null}
{
  "ok": false,
  "code": "invalid_arguments",
  "message": "The arguments for \"library.get\" did not match its schema.",
  "issues": [
    { "path": "kind", "message": "Required" },
    { "path": "id", "message": "Required" }
  ]
}
```

## Which refusals are about us

Four of the answers above are **platform states**. No new key, no permission
change and no code change on your side will clear them, and each says so in its
own message rather than leaving you to guess:

* `tenant_mcp.surface_disabled` — the surface is not open for your account yet.
* `api_access.platform_disabled` — programmatic access is off platform-wide.
* `tool_capability_unbound` — that action is not open to API clients yet.
* Anything a support reply tells you is on our side.

Everything else in this page has a fix you can perform.

## A quick triage

<Steps>
  <Step title="Read the status first">
    A `4xx` means the request never reached the action. A `200` means it did.
  </Step>

  <Step title="On a 4xx, read the code">
    The table above names who can clear each one. Most `403`s are a switch or a
    permission, not the key.
  </Step>

  <Step title="On a 200, read ok">
    `"ok": true` is a real answer. `"ok": false` carries a code and a message
    written to be acted on — including, where it applies, the list of choices
    you could pass instead.
  </Step>

  <Step title="If the message says it is not about your key, believe it">
    Minting another key is the most common wasted step. The refusals that are
    not about your credential say so in those words.
  </Step>
</Steps>


## Related topics

- [Troubleshooting](/help/troubleshooting.md)
- [Actions that spend credits](/api/spending-actions.md)
- [Recipes](/api/recipes.md)
