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

# Errors

> Handle Biqli API errors, validation details, partial bulk failures, and request tracing.

Biqli uses HTTP status codes for the broad result and stable error codes for
programmatic handling. Error messages are written for people and may become
more specific over time; integrations should branch on `error.code`.

## Error response

API errors use one JSON envelope:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "The long url field is required.",
    "details": {
      "errors": {
        "long_url": [
          "The long url field is required."
        ]
      }
    }
  },
  "request_id": "ae437f49-30a3-4d55-bca6-dc523f2efcb3"
}
```

| Field           | Type   | Description                                                                 |
| :-------------- | :----- | :-------------------------------------------------------------------------- |
| `error.code`    | string | Stable machine-readable error identifier.                                   |
| `error.message` | string | Human-readable explanation of this failure.                                 |
| `error.details` | object | Optional structured context, such as field errors or a required permission. |
| `request_id`    | string | Identifier for tracing the request with Biqli support.                      |

Do not assume `details` is always present. Ignore unrecognized detail fields so
Biqli can add useful context without breaking your integration.

## Error catalog

### Authentication and access

| Status | Code                 | Meaning                                                               | Action                                                                     |
| :----- | :------------------- | :-------------------------------------------------------------------- | :------------------------------------------------------------------------- |
| `401`  | `invalid_token`      | The API key is missing, malformed, invalid, or revoked.               | Replace or correct the key.                                                |
| `403`  | `insufficient_scope` | The key or its creator lacks a required permission.                   | Grant the permission shown in `details.required_permission`, when present. |
| `403`  | `upgrade_required`   | The workspace plan does not include the requested capability.         | Review the plan information in `details` or remove the restricted feature. |
| `403`  | `quota_exceeded`     | A plan resource quota, such as the number of links, has been reached. | Remove unused resources or increase the workspace allowance.               |

Read [Authentication](/docs/api-reference/authentication) for workspace scope
and permission dependencies.

### Resources and conflicts

| Status | Code                 | Meaning                                                                  |
| :----- | :------------------- | :----------------------------------------------------------------------- |
| `404`  | `resource_not_found` | The resource or pagination cursor is unavailable in the key's workspace. |
| `409`  | `domain_taken`       | The domain is connected to another Biqli account.                        |
| `409`  | `alias_taken`        | The alias is already in use on the selected domain.                      |
| `409`  | `external_id_taken`  | The external ID is already in use in the workspace.                      |
| `409`  | `folder_name_taken`  | A folder already uses that name in the workspace.                        |
| `409`  | `tag_name_taken`     | A tag already uses that name in the workspace.                           |
| `409`  | `pixel_name_taken`   | A tracking pixel already uses that name in the workspace.                |
| `409`  | `biolink_name_taken` | A Biolink already uses that name in the workspace.                       |

Biqli intentionally returns the same `resource_not_found` response for a
missing resource and a resource belonging to another workspace.

### Request and validation failures

| Status | Code                      | Meaning                                                               |
| :----- | :------------------------ | :-------------------------------------------------------------------- |
| `405`  | `method_not_allowed`      | The endpoint does not support the requested HTTP method.              |
| `422`  | `validation_error`        | One or more body, query, or cursor values are invalid or unsupported. |
| `422`  | `url_blocked`             | URL safety rules rejected one or more destination fields.             |
| `422`  | `dns_verification_failed` | The required DNS records are missing or have not propagated.          |

Unknown JSON fields are rejected instead of silently ignored. For a validation
failure, `details.errors` maps each invalid field to one or more explanations:

```json theme={null}
{
  "error": {
    "code": "validation_error",
    "message": "The active field must be true or false.",
    "details": {
      "errors": {
        "active": ["The active field must be true or false."],
        "widget_data": ["The widget_data field is not supported by this endpoint."]
      }
    }
  },
  "request_id": "ae437f49-30a3-4d55-bca6-dc523f2efcb3"
}
```

Correct every reported field before retrying.

### Throttling and server failures

| Status | Code                    | Meaning                                                                | Action                                              |
| :----- | :---------------------- | :--------------------------------------------------------------------- | :-------------------------------------------------- |
| `429`  | `rate_limit_exceeded`   | The workspace exhausted its current request allowance.                 | Honor `Retry-After`, then retry.                    |
| `500`  | `internal_server_error` | Biqli could not complete the request because of an unexpected failure. | Retry with backoff; contact support if it persists. |

Read [Rate limits](/docs/api-reference/rate-limits) before implementing `429`
retries.

## Request tracing

Every API error includes the same identifier in:

```http theme={null}
X-Biq-Request-Id: ae437f49-30a3-4d55-bca6-dc523f2efcb3
```

```json theme={null}
{
  "request_id": "ae437f49-30a3-4d55-bca6-dc523f2efcb3"
}
```

You may send your own non-empty `X-Biq-Request-Id` value of up to 100
characters. Use a unique value per logical request and include it in your logs.
Do not place API keys, passwords, URLs containing secrets, or personal data in
the request identifier.

## Retry decisions

| Result               | Retry?    | Recommended behavior                                                                                     |
| :------------------- | :-------- | :------------------------------------------------------------------------------------------------------- |
| Network interruption | Sometimes | Retry with exponential backoff and jitter. Use `external_id` where supported to avoid duplicate creates. |
| `401`, `403`         | No        | Correct credentials, permissions, plan access, or resource quota first.                                  |
| `404`                | No        | Verify the resource ID, workspace, filters, and cursor.                                                  |
| `405`, `409`, `422`  | No        | Correct the request before retrying.                                                                     |
| `429`                | Yes       | Wait for `Retry-After`; it takes precedence over other timing hints.                                     |
| `500`                | Yes       | Use capped exponential backoff with jitter and a maximum attempt count.                                  |

Never retry indefinitely. Preserve the original `X-Biq-Request-Id` for retries
of the same logical operation, or record both the original and replacement IDs
in your trace.

## Bulk endpoint failures

Bulk create and bulk update can return `207 Multi-Status`. This is a completed
HTTP request, but one or more items failed. Always inspect every ordered
`results` item and the `summary` object:

```json theme={null}
{
  "results": [
    {
      "index": 0,
      "status": "success",
      "link": {
        "id": "biq_lnk_01M14D2M8VFKYQCE7Z3A6HRXWP"
      }
    },
    {
      "index": 1,
      "status": "error",
      "error": {
        "code": "validation_error",
        "message": "The long url field is required.",
        "details": {
          "errors": {
            "long_url": ["The long url field is required."]
          }
        }
      }
    }
  ],
  "summary": {
    "requested_count": 2,
    "created_count": 1,
    "failed_count": 1
  },
  "status": "partial_success"
}
```

Retry only the failed items after correcting their errors. Do not assume that
every `2xx` response means every requested bulk operation succeeded.
