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

# Errors, retries, and conflicts

> Turn API failures into reliable retry and recovery behavior.

V2 resource errors use `application/problem+json`. The OAuth token endpoint uses standard OAuth error responses.

Branch on the stable `code`, not the human-readable message. Include the `request_id` when you contact Bahn support.

## Read a problem response

```json theme={null}
{
  "type": "https://api.bahnexpress.fi/problems/validation-error",
  "title": "The request is invalid.",
  "status": 400,
  "code": "validation_error",
  "detail": "One or more fields are invalid.",
  "instance": "/v2/orders",
  "request_id": "req_01k1a2b3c4d5e6f7g8h9j0k1m2",
  "errors": [{
    "path": "items.0.vin",
    "code": "invalid_length",
    "message": "The VIN must contain 17 characters."
  }]
}
```

The `errors` array can identify more than one invalid field. Do not parse the human message to select a program action.

## Choose a retry action

| Result                                            | Action                                              |
| ------------------------------------------------- | --------------------------------------------------- |
| Network timeout                                   | Retry a write with the same idempotency key.        |
| `429`                                             | Wait for `Retry-After`, then retry.                 |
| `500` to `599`                                    | Retry with exponential backoff and jitter.          |
| `invalid_client`                                  | Stop and check the credential and environment.      |
| `validation_error`                                | Correct the named fields.                           |
| `request_too_large`                               | Reduce the body. Do not retry the same body.        |
| `revision_conflict`                               | Read the order, then decide from the new revision.  |
| `idempotency_conflict`                            | Use the original body or a new key for a new write. |
| `order_not_updateable` or `order_not_cancellable` | Read `allowed_actions` and stop the action.         |

Set a maximum retry count. Do not retry a permanent `4xx` error without a request change.

## Use idempotency keys

Order commands and file-upload creation need an `Idempotency-Key`. File deletion is idempotent without this header.

Create one key for one logical write. Reuse the same key after a timeout or server error.

Use a new key for a new logical write. Do not reuse a key with a different body.

## Use order revisions

Order update and cancellation requests need `If-Match`. Set it to the current order `revision`.

Read the order again after a revision conflict. Do not overwrite a newer order without a new decision.

A live ETA update does not change the order revision.

## Store request IDs

You can send `X-Request-ID`. The response also includes a request ID.

Store the request ID with each write result. Send it to `support@bahnexpress.com` when you report a problem.
