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

# Error codes

> Every error code the Kynva API returns — with cause and fix.

This page is the authoritative list. Every code below appears in
[`src/api/facade/errors/index.ts`](https://github.com/fredadun/renderforge/blob/main/src/api/facade/errors/index.ts)
in the backend.

<Info>
  Codes are stable across non-breaking versions. New codes may appear in new
  [API versions](/concepts/api-versioning); existing codes never change meaning.
</Info>

## 400 — Request errors

### `INVALID_REQUEST`

**Cause** — the request body, query, or headers don't match the schema (missing required field, wrong type, malformed JSON).

**Fix** — inspect `error.details[]` for the path and rule. Correct the field and retry.

### `VALIDATION_FAILED`

**Cause** — the request parses but fails a business validation rule (e.g., `size.width` exceeds the max for this format).

**Fix** — `error.details[]` has the rule that failed in `context.rule`. Many validation errors include a `fix_patch` you can apply.

### `STYLE_LOCK_VIOLATION`

**Cause** — your brief requested a value (color, font, layout) that conflicts with a BrandKit lock.

**Fix** — either use the locked value (often surfaced in `context.expected`) or relax the lock in your BrandKit. See [render with brand](/guides/render-with-brand).

### `POLICY_VIOLATION`

**Cause** — request was syntactically valid but violates a content-safety or commercial-use policy (e.g., trademarked text, restricted asset).

**Fix** — the policy reason is in `details[0].context.rule`. Change the offending content. If you believe this is a false positive, email support with the `request_id`.

### `INVALID_IDEMPOTENCY_KEY`

**Cause** — the `Idempotency-Key` header is present but isn't a valid UUID v4.

**Fix** — generate one: `crypto.randomUUID()` in Node, `uuid.uuid4()` in Python, `uuidgen` on Unix. See [idempotency](/concepts/idempotency).

### `API_VERSION_UNSUPPORTED`

**Cause** — `X-API-Version` is set to a version we don't support (typo, retired version, future date).

**Fix** — call `GET /api/v1/facade/api-versions` to discover supported values. See [versioning](/concepts/api-versioning).

### `SELF_ACTION_NOT_ALLOWED`

**Cause** — you tried to perform an action on yourself that's only valid against other users (e.g., approving your own draft for collaborative review).

**Fix** — route the action through another user with the appropriate permission.

## 401 — Authentication

### `UNAUTHORIZED`

**Cause** — missing, malformed, expired, or revoked bearer token.

**Fix**:

* Check the `Authorization` header is present and formatted as `Bearer <token>`.
* For API keys: confirm the key hasn't been rotated/revoked in the dashboard.
* For JWTs: confirm `iss`, `aud`, `sub`, `exp` claims are valid (see [authentication](/concepts/authentication)).

## 402 — Payment

### `INSUFFICIENT_CREDITS`

**Cause** — the request would consume credits you don't have.

**Fix** — top up at [Billing](https://www.kynva.ai/billing), or use a `kyn_test_` key for development (free, watermarked).

## 403 — Authorization

### `FORBIDDEN`

**Cause** — your token is valid but lacks the required scope (e.g., a `brands:read` key calling a render endpoint).

**Fix** — issue a key with the right scopes, or have a workspace owner grant your user the matching permission.

## 404 — Resource not found

All codes below return 404. The body indicates which kind of resource was missing.

| Code                         | What it means                                                 |
| ---------------------------- | ------------------------------------------------------------- |
| `NOT_FOUND`                  | Generic — no more specific code fits.                         |
| `BRAND_NOT_FOUND`            | `brand_id` doesn't exist or you can't see it.                 |
| `BRANDKIT_NOT_FOUND`         | `brand_id@version` combination doesn't exist.                 |
| `ASSET_NOT_FOUND`            | `asset_id` doesn't exist or was deleted.                      |
| `TEMPLATE_NOT_FOUND`         | `template_id` doesn't exist.                                  |
| `WEBHOOK_NOT_FOUND`          | `webhook_id` doesn't exist.                                   |
| `JOB_NOT_FOUND`              | `job_id` doesn't exist or is older than the retention window. |
| `DECISION_NOT_FOUND`         | A `decision_id` referenced in a draft wasn't found.           |
| `DESIGN_PRESET_NOT_FOUND`    | Preset doesn't exist or isn't published.                      |
| `COMPONENT_PRESET_NOT_FOUND` | Component preset doesn't exist.                               |
| `COLLECTION_NOT_FOUND`       | Collection doesn't exist.                                     |
| `DESIGN_VERSION_NOT_FOUND`   | The specific version of a design doesn't exist.               |
| `PREVIEW_JOB_NOT_FOUND`      | The async preview job has expired or doesn't exist.           |

**Fix** — confirm the ID. If it's a recent resource, check for a typo or whether it was created in a different workspace.

## 409 — Conflict

### `CONFLICT`

**Cause** — request conflicts with current state (e.g., creating a webhook with a URL that's already registered).

**Fix** — check `error.message` for the specific conflict, then either reuse the existing resource or delete it and recreate.

### `IDEMPOTENCY_CONFLICT`

**Cause** — you reused an `Idempotency-Key` with a different request body, URL, or method.

**Fix** — generate a fresh UUID v4 for new requests. Only reuse a key when retrying the same request. See [idempotency](/concepts/idempotency).

### `APPROVAL_REQUIRED`

**Cause** — your workspace requires human approval for this action and approval is still pending.

**Fix** — the response includes `error.approval` with `review_url` and `required_approvers`. Direct the approver there. Once approved, retry the original request.

## 429 — Rate limiting

### `RATE_LIMIT_EXCEEDED`

**Cause** — you hit the per-category rate limit.

**Fix** — wait `Retry-After` seconds, then retry. Use exponential backoff if you hit it repeatedly. See [rate limits](/concepts/rate-limits).

## 500 — Server errors

### `RENDER_FAILED`

**Cause** — the renderer hit an internal error producing pixels (font resolution failure, layout collapse, codec error for video).

**Fix** — retry once. If it persists, email support with the `request_id` and the original request body — it's likely a bug we need to see.

### `INTERNAL_ERROR`

**Cause** — an unexpected server error. We were paged.

**Fix** — exponential backoff up to 5 retries. Use the same `Idempotency-Key`.

## 501 — Not implemented

### `NOT_IMPLEMENTED`

**Cause** — you called a feature that isn't enabled for your account or version (commonly: video render on a non-video tier).

**Fix** — check your plan at [Billing](https://www.kynva.ai/billing) or talk to sales about enabling the feature.

## 503 — Service degradation

### `SERVICE_UNAVAILABLE`

**Cause** — a backend dependency (font catalog, asset CDN, render farm) is temporarily degraded.

**Fix** — exponential backoff up to 5 retries. Check [status.kynva.ai](https://status.kynva.ai) for ongoing incidents.
