Skip to main content
Use the OpenAPI document as the machine contract. Use the guides to explain the product decisions that schemas cannot express. The published site supplies /llms.txt and /llms-full.txt. Give the agent only the pages that its task needs. Read Integration workflows before the agent selects an operation.

Give the agent the right context

Provide the environment base URL, the operation goal, and only the relevant OpenAPI operations. Give the agent access to the client secret through a secret tool. Do not put the secret in the prompt. Keep test agents on https://sandbox.api.bahnexpress.fi. Do not let a test agent select the production base URL.

Use one write loop

For each write, the agent must follow this sequence:
  1. Read the current resource when the action depends on current state.
  2. Check the required scope, allowed_actions, and preconditions.
  3. Prepare the request from the OpenAPI schema.
  4. Create one idempotency key for the logical write.
  5. Send the request and store the response with its request ID.
  6. Stop or retry from the stable problem code.
Reuse an idempotency key only after a timeout or server error for the same request body. An update or cancellation also needs the current revision in If-Match.

Build valid time input

Send RFC 3339 timestamps with an offset. Send the IANA time zone for each requested window. Pickup needs available_from or one requested window. Windows for one stop must not overlap.

Prevent time and state mistakes

Handle prices

Use an available price check result as the current price. It is not a reservation or guarantee. Treat custom_quote_required as no automatic price. Do not promise that Bahn will provide a quote. Read the accepted price from the created order.

Handle webhooks

Verify the signature against the raw body before you trust the event. Deduplicate by event id. Use data.order_sequence only to order events for one order. Read data.resource_url when you need current state. Resolve the path against the origin in source. Do not expect an additional order status event after an item transition or cancellation.

Handle ordering channels

Send ordered_for for each ordering-channel price check and order. Use the official business ID and country code. Omit ordered_for for a direct customer credential. Store the returned value with the Bahn order ID. Use webhook data.ordered_for to select the correct customer.

Stop on permanent errors

Stop after a validation, authentication, permission, or business-rule error. Continue only after the request or authorization changes. After revision_conflict, read the order and make a new decision. After idempotency_conflict, use the original body or start a new logical write.