Skip to main content
The Bahn Customer API uses the OAuth 2.0 client credentials grant. It is a server-to-server flow with no user sign-in or redirect. Authentication has two parts. First, you create and store a credential. Then, your system gets short-lived access tokens with that credential.
Store the client secret in a secret manager. Do not put it in source code, browser code, logs, or an agent prompt.

Complete the one-time setup

1

Create a sandbox credential

Open API integrations in the Bahn customer portal. Select Create credential, then give the credential a name that identifies one system.Copy the client ID and client secret before you close the window. The portal shows the client secret one time.
2

Store the credential

Store the client ID and client secret in your server-side secret manager. Do not send the secret to a browser or mobile application.
3

Add the environment URLs

Store the API base URL and token URL with the credential. Do not combine sandbox and production configuration.
4

Verify the sandbox connection

Get an access token. Then call GET /v2/orders with that token.Complete your order and webhook tests in the sandbox before you create a production credential.
Use a separate credential for each system and environment. This separation lets you replace one credential while other systems stay active.

Run the token flow

Your system repeats this flow automatically:
  1. Read the client ID and client secret from secure storage.
  2. Request an access token with HTTP Basic authentication.
  3. Cache the token for its credential and scope set.
  4. Send the token in the Authorization header for API requests.
  5. Request a new token before the current token expires.
Do not request a new token for each API call.

Get an access token

Use the client ID as the HTTP Basic username. Use the client secret as the password. Send the request body as form data.
The response contains the token, its expiry, and its granted scopes.
The token is valid for 15 minutes. Request a new token 60 seconds before it expires. The flow does not use refresh tokens.

Use the access token

Send the access token as a Bearer token.
The access token belongs to one environment. A sandbox token cannot access production, and a production token cannot access the sandbox.

Select scopes

Omit the scope form field to request every scope assigned to the credential. Send it when your process needs a smaller set. A request for a scope that is not assigned to the credential fails. Most integrations can omit the scope field.

Handle token failures

If an API request returns 401, get a new token and retry the request once. Stop if the new token also fails. If the token endpoint returns invalid_client, check that the credential belongs to the environment in the token URL. Do not retry the same values in a loop. If the token endpoint returns invalid_request, check the content type, grant_type, and optional scope field.

Replace a credential

Create the replacement credential before you revoke the old credential. Update your system, verify a new token, and then revoke the old credential. Contact support@bahnexpress.com if a credential is exposed or you need integration support. An ordering-channel credential uses the same token flow. It can act for represented businesses through ordered_for. Read Platform ordering for its access rules.