> ## Documentation Index
> Fetch the complete documentation index at: https://direct-api.reap.global/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Every error shares one envelope: status, type, message and often a code. Program against code when present, type otherwise, and retry only what this page marks retryable.

Every error response has the same shape:

```json theme={"system"}
{
  "statusCode": 422,
  "code": "CARDHOLDER_NOT_FOUND",
  "type": "INVALID_REQUEST_ERROR",
  "message": "No approved team member has that userId.",
  "requestId": "req_01JZ2..."
}
```

| Field | Meaning |
| - | - |
| `statusCode` | HTTP status |
| `code` | Stable machine-readable code when present. Program against `code`, and fall back to `type` when it's absent (validation, `404` and upstream errors carry no `code`) |
| `type` | Broad error class (below), always present |
| `message` | Human-readable explanation |
| `param` | Optional; the offending parameter, on validation errors |
| `requestId` | Unique request ID; quote it when contacting support. Absent on version `404`/`410` rejections |
| `details` | Optional extra context; an array of `{ path, message, code }` entries on validation errors |

## `type`

| Value | Meaning | Retryable? |
| - | - | - |
| `INVALID_REQUEST_ERROR` | The request itself is wrong | No; fix the request |
| `AUTHENTICATION_ERROR` | Key missing or invalid | No; fix the key |
| `PERMISSION_ERROR` | Key valid but not allowed | No; fix scopes, allowlist or access |
| `RATE_LIMIT_ERROR` | Too many requests | Yes; back off, same `Idempotency-Key` |
| `API_ERROR` | Something failed on Reap's side | Yes; retry shortly |
| `UPSTREAM_ERROR` | A provider Reap depends on failed | Yes; retry shortly |

One exception: `IDEMPOTENCY_KEY_IN_FLIGHT` (`409`) has type
`INVALID_REQUEST_ERROR` but is safe to retry: the first request is still
running; retry the same request shortly.

## Validation errors

A `400` validation failure carries **no `code`**. `type` is
`INVALID_REQUEST_ERROR`, `param` names the first offending field, and
`details` is an array of every failing field:

```json theme={"system"}
{
  "statusCode": 400,
  "type": "INVALID_REQUEST_ERROR",
  "message": "Validation failed.",
  "param": "amount",
  "details": [
    {
      "path": ["amount"],
      "message": "Amount must be at least 1.",
      "code": "custom"
    }
  ],
  "requestId": "req_01JZ2..."
}
```

## Common codes

Codes that apply across endpoints; each endpoint page also lists the codes
specific to it.

| Code | Status | What to do |
| - | - | - |
| `AUTH_CREDENTIAL_MISSING` | 401 | Send `x-api-key` |
| `API_KEY_INVALID` | 401 | Check or rotate the key |
| `AUTH_INSUFFICIENT_PERMISSIONS` | 403 | Add the endpoint's scope to the key |
| `AUTH_METHOD_NOT_ALLOWED` | 403 | Use an API key, not another credential type |
| `API_KEY_IP_NOT_ALLOWED` | 403 | Add your egress IP to the key's allowlist |
| `API_KEY_RATE_LIMITED` | 429 | Back off and retry; see [Rate limits](/api-reference/rate-limits.md) |
| `IDEMPOTENCY_KEY_IN_FLIGHT` | 409 | The first request is still running, so retry the same request shortly |
| `IDEMPOTENCY_KEY_REUSED` | 422 | Same key, different body. Use one key per logical request |
| `IDEMPOTENCY_UNAVAILABLE` | 503 | Outcome unknown. Check the resource, then retry with the same key |

See [Idempotency](/api-reference/idempotency.md) for the full retry contract.


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