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

# Errors & Rate Limits

> HTTP error codes, API error response format, task error states, Bridge error codes, and rate limiting behavior

Use the `code` field in the error response body to drive error-handling logic in your integration. The `message` field is human-readable and intended for logging and debugging.

***

## HTTP errors

### Error response format

Most error responses return an `error` object with a machine-readable `code` and a `message`:

```json theme={null}
{
  "error": {
    "code": "incorrect_parameters",
    "message": "Incorrect request parameters",
    "extra": {
      "invalid-params": []
    }
  }
}
```

The `extra` field appears on `400` responses only. It lists the specific fields that failed validation.

<Note>
  `404` responses use a different shape: `{"detail": "Not Found."}` rather than the standard `error` object.
</Note>

### Status codes

| Status                       | `error.code`            | Description                                                                                                                                                                            |
| ---------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400 Bad Request`            | `incorrect_parameters`  | A required field is missing, a field value is invalid, or a combination of fields is not allowed. Check `extra.invalid-params` for specifics.                                          |
| `401 Unauthorized`           | `authentication_failed` | The `X-Access-Client-Id` or `X-Access-Secret` header is missing, malformed, or the credentials do not match any key in the environment.                                                |
| `403 Forbidden`              | `not_authenticated`     | Credentials are valid but do not have permission to access this resource. Common cause: using sandbox credentials against a production resource.                                       |
| `404 Not Found`              | *(see above)*           | The requested resource ID does not exist or belongs to a different client.                                                                                                             |
| `405 Method Not Allowed`     | —                       | The HTTP method is not supported on this endpoint. Check the [API Reference](/api-reference/openapi) for the supported method.                                                         |
| `406 Not Acceptable`         | —                       | The server can't produce a response matching the `Accept` header in your request. Truv responses are always `application/json` — remove restrictive `Accept` headers.                  |
| `410 Gone`                   | `expired_token`         | A token used in the Bridge flow is no longer valid. Most often a `public_token` exchange after expiry or reuse — see the [410 Gone response example](#response-examples) for recovery. |
| `415 Unsupported Media Type` | —                       | The request payload format is unsupported. Set `Content-Type: application/json` and send a valid JSON body.                                                                            |
| `429 Too Many Requests`      | `throttled`             | Request rate limit exceeded. Back off and retry. See [Rate limits](#rate-limits).                                                                                                      |
| `500 / 502 / 503`            | —                       | Truv-side error. Retry with exponential backoff. If errors persist, check status and contact [support@truv.com](mailto:support@truv.com).                                              |

### Response examples

<AccordionGroup>
  <Accordion title="400 Bad Request">
    Each entry in `invalid-params` carries a `field` (the offending parameter name) and a `message` (the validation reason).

    ```json theme={null}
    {
      "error": {
        "code": "incorrect_parameters",
        "message": "Incorrect request parameters",
        "extra": {
          "invalid-params": [
            { "field": "products", "message": "This field is required." },
            { "field": "user.email", "message": "Enter a valid email address." }
          ]
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="401 Unauthorized">
    ```json theme={null}
    {
      "error": {
        "code": "authentication_failed",
        "message": "No such token"
      }
    }
    ```
  </Accordion>

  <Accordion title="403 Forbidden">
    ```json theme={null}
    {
      "error": {
        "code": "not_authenticated",
        "message": "Authentication credentials were not provided."
      }
    }
    ```
  </Accordion>

  <Accordion title="404 Not Found">
    ```json theme={null}
    {
      "detail": "Not Found."
    }
    ```
  </Accordion>

  <Accordion title="410 Gone">
    The most common trigger is calling `POST /v1/link-access-tokens/` with a `public_token` that was already exchanged or has aged out — `public_token` is single-use and short-lived. Less commonly, the upstream `bridge_token` has expired (valid for 6 hours from creation).

    ```json theme={null}
    {
      "error": {
        "code": "expired_token",
        "message": "Public token expired: 48427a36d43c4d5aa6324bc06c692456"
      }
    }
    ```

    **Recovery**

    | Token                            | Action                                                                                                                                  |
    | -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
    | `public_token` expired or reused | Re-run Truv Bridge so `onSuccess` returns a fresh `public_token`, then exchange it immediately at `POST /v1/link-access-tokens/`.       |
    | `bridge_token` expired           | Call [Create Bridge Token](/api-reference/bridge-token/users_tokens) for a new `bridge_token`, then re-initialize Bridge on the client. |

    See the [`bridge_token → public_token → access_token`](/developers/best-practices/bridge-token#understand-the-token-flow) flow for the full token lifecycle.
  </Accordion>

  <Accordion title="429 Too Many Requests">
    ```json theme={null}
    {
      "error": {
        "code": "throttled",
        "message": "Request was throttled."
      }
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Rate limits

Truv applies rate limits to protect platform stability and to keep latency predictable for every customer. Limits apply per access secret key. Sandbox and production have separate keys, so their limits are tracked independently.

### Standard limits

| Surface                               | Limit                                            | Scope                 |
| ------------------------------------- | ------------------------------------------------ | --------------------- |
| All API requests                      | **300 requests / minute**                        | Per access secret key |
| Refresh endpoints, per `access_token` | **1 initial request + 3 refreshes per 24 hours** | Per `access_token`    |

The 300/minute limit covers all API requests authenticated with a given access secret key, across every endpoint. Requests over the limit return a `429 Too Many Requests` error.

The per-`access_token` refresh limit covers `POST /v1/refresh/tasks/` and `GET /v1/refresh/tasks/{task_id}/`, plus `GET /v1/links/{link_id}/` re-fetches. Requests beyond the allowed window return the error message `Refresh limit for the access_token exceeded`. See the canonical [Links](/api-reference/links/object) and [Refresh](/api-reference/refresh/object) reference pages for the per-endpoint detail.

<Note>
  These are the defaults for new accounts. Higher limits are available — see [Request a higher limit](#request-a-higher-limit) below.
</Note>

### Handle 429 responses

When a request exceeds a rate limit, Truv returns `429 Too Many Requests` with `error.code: throttled`. The connection is not penalized — subsequent requests succeed once your traffic drops back under the limit.

Respect the `Retry-After` response header on `429` responses. The value is the number of seconds to wait before retrying. If the header is not present, fall back to exponential backoff starting at 1 second and capped at 60 seconds.

```text theme={null}
# Pseudocode — Retry-After backoff with exponential fallback (capped at 60s)
attempt = 0
loop:
    response = HTTP request
    if response.status != 429:
        return response

    retry_after = response.headers.get("Retry-After")          # seconds, if Truv supplied it
    fallback    = min(2 ** attempt, 60)                        # 1, 2, 4, 8, 16, 32, 60, 60, ...
    sleep(int(retry_after) if retry_after else fallback)
    attempt += 1
```

<Note>
  Always check the response status before sleeping. The pseudocode above retries only on `429`; on `5xx` responses, [Truv-side error retry guidance](#status-codes) applies instead. On `2xx` or `4xx` other than `429`, return the response immediately — never retry blindly.
</Note>

### Best practices

* **Webhooks over polling.** Polling for status changes burns through your rate limit. Subscribe to [`order-status-updated` and `task-status-updated`](/api-reference/webhooks) and only call the API when a webhook fires.
* **Stagger bulk jobs.** Spread high-volume work across time rather than bursting it, so you stay under the 300 / minute limit.
* **Refresh deliberately.** The per-`access_token` refresh limit is designed for human-paced re-verification. Programmatic refresh on every page load exhausts the limit within minutes.
* **Don't retry blindly.** Order creation is not idempotent — retrying a failed `POST /v1/orders/` creates a new Order. Store your application-level reference and de-duplicate before retrying.

### Request a higher limit

Higher limits are available on request. To request one, contact your Truv Technical Account Manager or email [support@truv.com](mailto:support@truv.com) with:

* Truv account name and environment (sandbox or production).
* Current peak RPM and target peak RPM.
* Time window when peaks occur (e.g., 7–9 PM ET on weekdays).
* Use case context — e.g., "Recertification batch — 50,000 applicants over a 4-hour window."

***

## Task error states

For all task error states, their causes, and recommended actions, see [Task Lifecycle — Error states](/api-reference/tasks/lifecycle#error-states). Subscribe to `task-status-updated` webhooks to receive error notifications in real time.

***

## Bridge errors

Truv Bridge fires client-side errors through the `onEvent` callback when `type === 'ERROR'`. These are distinct from task error states — they fire in the browser during the connection flow, not through webhooks.

```javascript theme={null}
onEvent: function(type, payload) {
  if (type === 'ERROR') {
    console.error(payload.error.error_code, payload.error.error_message);
  }
}
```

For the full error code reference (`LOGIN_ERROR`, `MFA_ERROR`, `UNAVAILABLE`, `NO_DATA`, `LINK_EXISTS`, `ERROR`), error object shape, and recommended fallback routing, see [Bridge Events — Errors](/developers/sdks/bridge-events#errors).

***

## Document processing errors

For document upload errors — `config_error` and `no_data` messages, fraud detection, and the complete review workflow — see [Fraud & Manual Review](/developers/fraud-and-manual-review).

***

## Webhook delivery retries

For webhook timeout, retry policy, and signature verification, see [Webhooks — delivery and retries](/api-reference/webhooks).

***

## Next steps

<CardGroup cols={2}>
  <Card title="Task Lifecycle" icon="arrows-spin" href="/api-reference/tasks/lifecycle">
    Complete task status flow and error state transitions
  </Card>

  <Card title="Bridge Events" icon="bolt" href="/developers/sdks/bridge-events">
    Client-side error codes and fallback routing
  </Card>

  <Card title="Fraud & Manual Review" icon="shield-halved" href="/developers/fraud-and-manual-review">
    Document fraud detection and review workflows
  </Card>

  <Card title="Webhooks" icon="bell" href="/api-reference/webhooks">
    Real-time notifications for task and order status changes
  </Card>
</CardGroup>
