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

# Errors

> Understand the error responses returned by Lead's V2 APIs.

Every endpoint under the `/v2` path returns errors in the shape described on this page. Endpoints on earlier versions keep their existing error format. See [Errors](/api-reference/using-the-api/errors) for those.

Lead uses HTTP status codes to indicate the success or failure of an API request.

* Codes in the `2xx` range indicate success.
* Codes in the `4xx` range indicate a problem with the request. These are fixable using the information in the error response.
* Codes in the `5xx` range indicate a problem on Lead's side. These are rare and are usually safe to retry.

## Error response

An error response has three parts: the HTTP status line, response headers, and a JSON body.

```http theme={null}
HTTP/1.1 422 Unprocessable Content
Request-ID: req_7f3c9a12e4b5
Content-Type: application/json

{
  "code": "parameters_invalid",
  "message": "One or more parameters are invalid.",
  "errors": [
    {
      "code": "out_of_range",
      "message": "200 is outside of the allowable range of 300 and 850.",
      "parameters": ["credit_details.credit_score"]
    },
    {
      "code": "parameter_group_incomplete",
      "message": "All parameters must be provided together.",
      "parameters": [
        "identification_details.tax_identification.type",
        "identification_details.tax_identification.value"
      ]
    }
  ]
}
```

### Headers

| **Header** | **Type** | **Presence** | **Description** |
| - | - | - | - |
| Status line | string | Always | The HTTP status code and reason phrase, such as `HTTP/1.1 404 Not Found`. The status isn't repeated in the body. |
| `Request-ID` | string | Always | A unique ID for the request. It's returned on every response, including successful ones. Include it when you contact Lead about an error. |
| `Retry-After` | integer or date | Sometimes | The number of seconds, or the date, after which you can retry. May be included on `429` and `503` responses. |

### Body

| **Field** | **Type** | **Presence** | **Description** |
| - | - | - | - |
| `code` | enum | Always | A machine-readable code for the error. Each code groups errors by what you should do next. See [Error codes](#error-codes). |
| `message` | string | Always | A human-readable description of `code`. It's the same for every occurrence of the code and contains no request-specific details. |
| `errors` | array | Sometimes | One or more specific errors that make up this response. Lead returns all errors it can find in a single response where possible, most often for `parameters_invalid`. |
| `errors[].code` | string | Always, within `errors` | A machine-readable name for the specific condition that failed, such as `out_of_range` or `non_sufficient_funds`. |
| `errors[].message` | string | Always, within `errors` | A human-readable explanation of this specific error, including values from your request where relevant. **This is the only field that may include request values.** |
| `errors[].parameters` | array of strings | Sometimes | The request fields that caused the error. Body fields use dot notation (for example, `creditor.account_number`). Headers appear by name (for example, `Idempotency-Key`). On a `PATCH`, this can include fields on the stored object. |

### What you can rely on

Build your error handling on the HTTP status and `code`. Together they're stable: Lead treats any change to a status and `code` combination as a breaking change and announces it in advance.

| **Stable** | **No stability guarantee** |
| - | - |
| HTTP status | `Request-ID` header |
| `code` | `message` |
| `Request-ID` header | `errors[].code` |
| | `errors[].message` |
| | `errors[].parameters` |
| | Whether `errors` is present |

Fields in the right column may change without notice. Don't parse `message` or `errors[].message`. Show them to developers, not end users.

<Note>
  You can branch on `errors[].code` for more specific error handling, but always fall back to `code`. If an `errors[].code` value changes or is removed, your integration should still handle the error correctly using `code` alone.
</Note>

## Error codes

V2 APIs return 26 codes. Each code always uses the same HTTP status.

| **Status** | **Code** | **Meaning** | **What to do** |
| - | - | - | - |
| `400` | `request_malformed` | The request can't be parsed. The URL contains invalid characters, the body isn't valid JSON, or the `Content-Type` isn't supported. | Check `errors[].code` for the cause, fix the request, and resend. |
| `400` | `idempotency_key_missing` | The endpoint requires an `Idempotency-Key` header and the request didn't include one. | Add an `Idempotency-Key` header and resend. |
| `403` | `authentication_missing` | The request didn't include authentication credentials. | Add your access token to the `Authorization` header and resend. |
| `403` | `token_invalid` | The bearer token is missing, expired, malformed, or invalid. | Request a new access token and resend. |
| `403` | `source_ip_not_allowed` | The request came from an IP address that isn't on your program's allowlist. | Send the request from an allowlisted IP, or ask Lead to add the IP. |
| `404` | `url_invalid` | The path isn't a valid endpoint. | Check the path and version prefix against the API reference. |
| `404` | `object_not_found` | No object exists with the requested ID, or the object isn't visible to you. | Check the ID. Don't retry unchanged. |
| `405` | `method_not_allowed` | The endpoint doesn't support this HTTP method. This includes writes to read-only endpoints. | Use a method the endpoint supports. |
| `409` | `idempotency_key_in_use` | Another request with the same `Idempotency-Key` is still processing. | Wait for the first request to finish, then retry with the same key. |
| `409` | `object_modified_concurrently` | Another request changed the object while this request was processing, so this request wasn't applied. | Fetch the object's current state, then retry. |
| `422` | `idempotency_request_inconsistent` | This `Idempotency-Key` was already used with a different request body. | Use a new key for a different request, or resend the original body with the original key. |
| `422` | `parameters_invalid` | One or more fields in the request failed validation. | Fix each field listed in `errors[].parameters` and resend. |
| `422` | `related_object_invalid` | An object referenced in the request doesn't exist or can't be used. | Correct the reference, or create the object, then resend. |
| `422` | `related_object_not_ready` | An object the request depends on isn't in a state that allows this operation. | Update that object, then retry the request unchanged. |
| `422` | `related_object_conflict` | The request conflicts with an attribute of an object it references. | Change the request to match the referenced object, then resend. |
| `422` | `limit_exceeded` | The request exceeds a limit that applies to it, such as available balance or a payment limit. | Reduce the request, or retry after the limit resets. |
| `422` | `client_control_restricted` | A control you configured on a referenced object blocks this request. | Update the control, then retry the request unchanged. |
| `422` | `lead_control_restricted` | A control Lead configured on a referenced object blocks this request. | Ask Lead to update the control, then retry the request unchanged. |
| `422` | `object_state_conflict` | The object isn't in the state the request assumed. | Fetch the object's current state, then decide whether to retry. |
| `422` | `operation_invalid` | The operation isn't valid for this object and won't become valid. | Don't retry. |
| `429` | `rate_limit_exceeded` | You've exceeded the rate limit for this endpoint. | Retry with exponential backoff. If a `Retry-After` header is present, wait at least that long. |
| `500` | `internal_server_error` | Something went wrong on Lead's side. | Retry with the same idempotency key. If it keeps happening, contact Lead with the `Request-ID`. |
| `500` | `unclassified` | An error occurred that Lead couldn't map to a registered code. Lead tracks these and reclassifies them. | Contact Lead with the `Request-ID`. |
| `503` | `service_unavailable` | A system this request depends on, such as a payment network, is temporarily unavailable. | Retry after the interval in the `Retry-After` header, if available. |
| `503` | `endpoint_disabled` | The endpoint is temporarily disabled, for example during a migration. | Retry after the interval in the `Retry-After` header, if available. |
| `504` | `gateway_timeout` | An upstream system didn't respond in time. | Retry with the same idempotency key and exponential backoff. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.