> ## 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.

> ## Agent Instructions
> For Bahn Customer API V2 integration work, start with /skill.md and /guides/agent-integration.md on this documentation site. Use /llms.txt to find the guides for the requested workflow.
> The main integration orders your company's transports from existing software. Follow the requested screen, service, or job. Omit ordered_for for own-account orders. Use the platform-ordering guide to choose order ownership and billing for businesses using a platform. Add a customer-facing interface only when requested.
> Use /openapi.yaml for paths, schemas, scopes, and operation preconditions. Use the guides for transport rules and recovery behavior. Load only the relevant pages.
> Use the sandbox for development and tests. Keep credentials on the server. Production orders start real transport work; follow the customer's authorized workflow and account context.
> For required writes, preserve write keys and request data across retries, and use current actions and quoted revisions for order changes. When consuming webhooks, verify and durably store them before acknowledgement.
> Deliver the implemented workflow with test evidence, setup steps, and remaining gaps. Distinguish simulated checks from requests actually verified against Bahn.

# Order status and driver assignment

> Find out where a transport is, whether a driver has booked it, and which actions are still available.

Read the full order with `GET /v2/orders/{order_id}` to answer three questions:

* How far has the transport progressed? Read `status` and `items[].status`.
* Has a driver booked the work, and which part? Read `driver_assignments`.
* Can you still change or cancel the order? Read `allowed_actions` and `cancellation_unavailable_reason`.

Order creation and driver booking are different events. You create an order when you request a transport. A driver books the order later, when the driver accepts transport work on it. One order can have several driver bookings, for example one for each vehicle or leg. A leg is one part of a vehicle's route.

## Order status

The order status summarizes all vehicles in the order.

| Status | Meaning |
| - | - |
| `accepted` | Bahn accepted the order. No driver has a booking on it, and no vehicle is in transit. |
| `driver_assigned` | Bahn found a driver: at least one driver booked part of the order. No vehicle has been collected. |
| `in_transit` | At least one vehicle was collected, and the order is not complete. |
| `delivered` | All vehicles in the order are delivered. |
| `cancelled` | You or Bahn cancelled the order. |

```mermaid theme={null}
stateDiagram-v2
    [*] --> accepted
    accepted --> driver_assigned: Driver books
    driver_assigned --> accepted: Last driver unbooks
    accepted --> in_transit: Vehicle collected
    driver_assigned --> in_transit: Vehicle collected
    in_transit --> delivered: All delivered
```

An order can become `cancelled` from any status before `delivered`. You can cancel it only while `allowed_actions` contains `cancel`.

A truck carrier booking does not show a driver, so the order stays `accepted` until a vehicle is collected. A trade-in order stays `in_transit` after Bahn delivers the primary vehicle, until the trade-in vehicle is back at the pickup address.

### Vehicle status

Each vehicle in `items` has its own status. Use it when the primary and trade-in vehicles are at different stages.

| Vehicle status | Meaning |
| - | - |
| `awaiting_pickup` | The vehicle has not been collected. |
| `in_transit` | The vehicle was collected and has not been delivered. |
| `delivered` | The vehicle was delivered. |

A cancelled order keeps the last vehicle statuses and the actual pickup and delivery times.

## Driver assignment

`driver_assignments` lists the drivers with a booking on the order. Each entry describes one driver's work on one vehicle.

```json theme={null}
{
  "status": "driver_assigned",
  "driver_assignments": [
    {
      "driver_name": "Aino Virtanen",
      "item_id": "item_01k1a2b3c4d5e6f7g8h9j0k1m2_primary",
      "pickup": true,
      "delivery": false
    },
    {
      "driver_name": "Mikko Laine",
      "item_id": "item_01k1a2b3c4d5e6f7g8h9j0k1m2_primary",
      "pickup": false,
      "delivery": true
    }
  ]
}
```

In this example, two drivers share the primary vehicle's route. The first driver collects the vehicle. The second driver hands it over at the delivery address.

| Field | Meaning |
| - | - |
| `driver_name` | The driver's display name. The order does not contain contact details. |
| `item_id` | The vehicle that this driver moves. |
| `pickup` | `true` when this driver collects the vehicle at its pickup address. |
| `delivery` | `true` when this driver hands the vehicle over at its delivery address. |

For a trade-in vehicle, the pickup address is the order's delivery address, and the delivery address is the order's pickup address.

Use these rules when you show drivers:

* One driver booking does not mean that every leg or vehicle has a driver. Check `pickup` and `delivery` for each vehicle.
* A driver who works on both vehicles has two entries.
* `pickup` and `delivery` are both `false` when the driver moves the vehicle on an intermediate leg.
* `pickup` is `null` when Bahn recorded the booking in an older format that does not say whether this driver collects the vehicle.
* Drivers who finished their part stay in the list after pickup and delivery.
* A name disappears when that driver unbooks or when Bahn gives the work to a different driver. Replace your displayed list each time you read the order.
* If the last driver unbooks before pickup, the status returns to `accepted` and the list becomes empty.

A driver booking does not start location tracking. The tracking resource stays `not_started` until the driver starts to travel to pickup. Read [Live tracking](/guides/tracking-and-inspections) for the map and the pickup approach.

## Available actions

`allowed_actions` tells you which operations the current order state permits. Use it to enable or disable controls in your system. Do not decide from `status` alone: an order can be `accepted` without `update` or `cancel`.

The list contains each action under this condition:

* `update`: You can [change the order](/guides/manage-orders#change-an-order).
* `cancel`: You can [cancel the order](/guides/manage-orders#cancel-an-order).
* `get_files`: Always.
* `get_inspection_report`: The order uses the `full` inspection service.
* `get_tracking`: The order is not `delivered` or `cancelled`.

The list does not check the scopes of your credential. A credential without `orders:write` still sees `update` and `cancel`, and its write request returns `403 permission_denied`.

### When changes and cancellation close

`update` and `cancel` are always available together. They close permanently when one of these events occurs:

* The first driver books the order. Unbooking does not open them again.
* A transport company books the transport, or Bahn has already arranged it. In these cases you may not see a driver name.

Bahn can offer the transport to drivers before anyone books it. This offer alone does not close changes or cancellation.

After they close, contact Bahn to request a change or cancellation.

### Explain a closed action

`cancellation_unavailable_reason` is `null` while `update` and `cancel` are available. When they are not available, it contains a sentence that you can show to the person who requested the transport. For example:

> A driver has already booked this order. Contact Bahn to request cancellation.

Show the text as written. Its wording can change, so do not use it in program logic. Use the same text to explain a disabled change control, because changes close at the same time as cancellation.

## Keep your copy current

Bahn sends a webhook when the driver bookings change:

* `com.bahn.order.status.changed.v1`: The first driver books an `accepted` order, or the last driver unbooks before pickup.
* `com.bahn.order.updated.v1`: Another driver books, a driver unbooks, or Bahn gives the work to a different driver, and the status stays the same.

There is no separate event for a driver booking. After either event, read the order for the current status, drivers, and actions. Read [Webhooks](/guides/webhooks#event-types) for delivery and ordering rules.

A booking, an unbooking, and a change of driver also change the order `revision`. Read the order again before you send a change or cancellation.

Test these changes in the sandbox with the `driver_booked`, `driver_unbooked`, and `driver_reassigned` scenarios. Read [Sandbox testing](/guides/sandbox).

These statuses and fields belong to API V2. The V1 order status values have not changed.


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