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

# Knouds API error codes and responses

> Every Knouds API error code, its HTTP status, what it means, and how to resolve it.

All non-2xx responses from the Knouds API return a JSON body. At minimum it contains `error` (a human-readable message) and `code` (a machine-readable constant). Some errors include additional context fields to help you diagnose the problem without guessing.

```json theme={null}
{ "error": "<message>", "code": "<CODE>", ...context }
```

## Error reference

| HTTP status | Code                           | Meaning                                                                                                                                                                       |
| ----------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`       | `INVALID_INPUTS`               | The request body is malformed or missing required fields. Check that `inputs` is a non-array object.                                                                          |
| `400`       | `INVALID_SLUG`                 | The workflow slug or model `internalName` in the URL contains invalid characters. Slugs must be lowercase letters, digits, and hyphens only.                                  |
| `400`       | `INVALID_BODY`                 | Request body is not valid JSON or is missing required fields.                                                                                                                 |
| `400`       | `INVALID_CAPABILITY`           | A capability string supplied at key creation is malformed (unknown verb, invalid slug pattern).                                                                               |
| `400`       | `ASYNC_NOT_SUPPORTED`          | `?async=true` was used on an endpoint whose provider doesn't support polling-based async (Fal-backed, Anthropic, HTTP-without-polling). Use sync mode (omit `?async=true`).   |
| `401`       | (no code)                      | The `x-api-key` header is missing, the key has been revoked, or the key is invalid.                                                                                           |
| `401`       | `LEGACY_KEY_RETIRED`           | Pre-Phase-11 key (created before May 2026). Regenerate at the [Developer Dashboard](https://knouds.ai/app/api/keys). See [Migration from scopes](/api/migration-from-scopes). |
| `402`       | `INSUFFICIENT_CREDITS`         | Your account does not have enough credits to complete the request. Top up your credit balance to continue.                                                                    |
| `402`       | `grant_exhausted`              | Your trial grant for this model has been fully used. Topping up credits will not unlock further access — you must upgrade your tier.                                          |
| `403`       | `CAPABILITY_DENIED`            | Your key's capability set does not cover this endpoint. Response includes `required` indicating which capability would have passed.                                           |
| `403`       | `CAPABILITY_ABOVE_CEILING`     | At key-creation time you tried to grant a capability your tier doesn't allow. Response includes `attempted`.                                                                  |
| `403`       | `API_KEY_ACCESS_DENIED`        | Free tier — upgrade to Pro to create API keys.                                                                                                                                |
| `403`       | `MODEL_TIER_REQUIRED`          | The model you are trying to run requires a higher plan tier than your account currently holds.                                                                                |
| `403`       | `WORKFLOW_CAP_REACHED`         | Free user trying to create a workflow above the per-tier cap (`maxWorkflows: 1` for Free). Upgrade to Pro for unlimited.                                                      |
| `404`       | `MODEL_NOT_FOUND`              | The `internalName` in the URL does not match any enabled registry model.                                                                                                      |
| `404`       | `EXECUTION_NOT_FOUND`          | The execution id (UUID) doesn't resolve to a row owned by you.                                                                                                                |
| `404`       | (message)                      | The workflow slug in the URL does not match any workflow you own.                                                                                                             |
| `429`       | `RATE_LIMIT_EXCEEDED`          | You have exceeded the per-minute request limit for your tier. Check the `Retry-After` header.                                                                                 |
| `500`       | `EXECUTION_FAILED`             | A provider call failed. The `error` field describes the cause. Retry with exponential back-off.                                                                               |
| `500`       | `PROVIDER_SUBMIT_FAILED`       | Async submit hit upstream 4xx/5xx — surfaced synchronously so you don't wait on a stuck `processing` row. Body includes `providerStatus` + `providerBody`.                    |
| `500`       | `PROVIDER_RESPONSE_INCOMPLETE` | Polling completed but the provider's response didn't contain the expected output (rare — transient provider issue or a misconfigured model). Credits NOT deducted.            |

## The two distinct 402 responses

Two different situations both return `402`, and they require different responses:

* **`INSUFFICIENT_CREDITS`** — you have a valid plan and the model is accessible, but your credit balance is too low. Go to **Settings → Billing** and top up your credits.
* **`grant_exhausted`** — your plan includes a limited trial grant for this model (for example, 1 free lifetime generation on a Free plan) and you have used it all. Topping up credits will not help here. You need to upgrade to a higher plan tier.

<Warning>
  If you receive `grant_exhausted`, adding credits to your account will not resolve the error. The grant is a tier-level feature, not a credit-level one. Upgrade your plan to regain access.
</Warning>

## CAPABILITY\_DENIED payload

When your key lacks the required capability, the response tells you exactly which one would have passed:

```json theme={null}
{
  "error": "Insufficient capability",
  "code": "CAPABILITY_DENIED",
  "required": "model:run"
}
```

Use `required` to decide whether to regenerate your key with broader capabilities (capped by your tier) or upgrade your tier.

## Handling errors in code

<CodeGroup>
  ```javascript JavaScript theme={null}
  const response = await fetch(url, options);

  if (!response.ok) {
    const err = await response.json();

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '10', 10);
      // Wait and retry
    } else if (err.code === 'INSUFFICIENT_CREDITS') {
      // Prompt user to top up credits
    } else if (err.code === 'grant_exhausted') {
      // Prompt user to upgrade plan — credits won't help
    } else if (err.code === 'CAPABILITY_DENIED') {
      console.error(`Need capability: ${err.required}`);
    } else if (err.code === 'LEGACY_KEY_RETIRED') {
      console.error('Regenerate your key at https://knouds.ai/app/api/keys');
    }
  }
  ```

  ```python Python theme={null}
  response = requests.post(url, ...)

  if not response.ok:
      err = response.json()
      code = err.get('code')

      if response.status_code == 429:
          retry_after = int(response.headers.get('Retry-After', '10'))
          # Wait and retry
      elif code == 'INSUFFICIENT_CREDITS':
          # Prompt user to top up credits
          pass
      elif code == 'grant_exhausted':
          # Prompt user to upgrade plan
          pass
      elif code == 'CAPABILITY_DENIED':
          print(f"Need capability: {err.get('required')}")
      elif code == 'LEGACY_KEY_RETIRED':
          print("Regenerate your key at https://knouds.ai/app/api/keys")
  ```
</CodeGroup>
