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

# Troubleshooting

> The widget's error contract, and what to do when a session ends.

### Error contract

Every error response from the widget's API carries a `code` and a `detail`:

```json theme={null}
{
  "code": 40001,
  "detail": "Authentication credentials were not provided."
}
```

`detail` is a plain string, with one exception: when the request itself failed validation, `detail` is an object keyed by the field that failed instead — one array of messages per field, the same shape you'd get from any field-level validation error.

```json theme={null}
{
  "code": 20000,
  "detail": {
    "requested_operations": {
      "0": ["\"no-existe\" is not a valid choice."]
    }
  }
}
```

`20000` is the only code that carries this shape today — every other code below always answers with a single string message.

| Code | Meaning |
| - | - |
| `20000` | Validation error — something in the request is malformed. `detail` is an object keyed by field, not a string. |
| `20002` | Not found. |
| `40000` | Authentication failed — invalid credentials on [`POST /auth`](/crypto-as-a-service/widget/get-started/authentication). |
| `40001` | Not authenticated — no session token was provided. |
| `40002` | Permission denied — the session doesn't have this operation enabled. |
| `40003` | Session not found or expired. |
| `40004` | Throttled — too many requests. |
| `40008` | Buy not approved — your endpoint answered the [approval request](/crypto-as-a-service/widget/webhooks#transaction_approval_request) with a status other than `200`, or with a signed response whose `approved` isn't `true`. |
| `40011` | Session code invalid, expired or already used. The same answer for all three, on purpose — request a new code. |
| `50005` | Buy approval unavailable — your webhook didn't answer in time, or answered with something that isn't a JSON object. |
| `50006` | Buy approval is enabled but the webhook isn't fully configured on your account. Contact Ripio. |
| `50007` | Buy approval couldn't be verified — your response had a missing or invalid `X-Partner-Signature-Ed25519`, or its `event_id` didn't match the request. See [Signing your response](/crypto-as-a-service/widget/webhooks#signing-your-response). |
| `50000` and above | An internal or upstream error. Retry the request. |

### When a session ends

A user's session can end in several ways. The widget handles all of them the same way: it shows a "session ended" screen and fires `ripio-session-expired` — see [Session lifecycle](/crypto-as-a-service/widget/get-started/session-lifecycle).

| Situation | What it means | What to do |
| - | - | - |
| **Code rejected** (`40011`) | The session code was invalid, had expired, or was already used — typically a cached code, a code reused for a second widget, or a page reload. | Request a new code via `POST /auth` and call `renew(code)`. |
| **Session expired** | The hour since `POST /auth` ran out. | Same fix. It can surface mid-flow, not only on load. |
| **Session not found** (`40003`) | The session was revoked on Ripio's side. | Same fix. |

<Note>
  A reload doesn't recover a session: the code in the URL was already used. If your users see the "session ended" screen right after opening the widget, check that you request a fresh code every time you open it and that nothing caches it.
</Note>


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