Overview
You are on a delayed train. Where should you get off, and which connection still gets you to your destination on time? This endpoint computes it: it scans every upcoming stop of your current train, queries real onward connections, computes the actual transfer buffer from raw timestamps (scheduled vs. live), and returns a clear recommendation β or several alternatives ranked by arrival time.
Payment: x402 micropayments β
1 USDC-cent per query, USDC on Base (eip155:8453) via EIP-3009
authorization. No account, no API key, no signup: send the payment payload, get the
answer.
Coverage: German, Swiss and Czech rail, served from a self-hosted routing engine; real-time delays where the upstream feed provides them. No SLA β data sources are live feeds and can change.
Endpoints
GET /healthβ service status (no payment)GET /api/discoveryβ full x402 resource metadata, workflow and example (no payment)GET /api/stations?q=<name>β station name tostop_id(no payment)GET /api/departures?station=<stop_id>β departures withtrip_idand live delay (no payment)POST /api/transfer-chainβ transfer-risk scan & recommendation (paid)/llms.txtΒ·/openapi.jsonβ machine-readable guides (no payment)
Request
POST /api/transfer-chain with a JSON body and the PAYMENT-SIGNATURE
header (base64-encoded x402 V2 payload).
Parameters
| Field | Required | Default | Description |
|---|---|---|---|
trip_id | yes | β | tripId of the train you are on (from the tripId field of a departure-board query, e.g. 20260908_14:11_de-DELFI_3398194072) |
to | yes | β | destination stopId, e.g. de-DELFI_de:11000:900003200:1:51 for Berlin Hbf |
min_buffer | no | 8 | transfer buffer threshold in minutes; below this, an option is flagged as risky (risk: "risiko") |
manual_delay | no | null | override the current delay in minutes (e.g. the PA announcement says more than the live feed); applied to all stops |
from_stop_name | no | null | only analyze stops whose name contains this substring (saves time on long routes) |
cache_ttl | no | 1200 | cache TTL in seconds for timetable queries (live train position is never cached) |
Example request
curl -X POST https://bahn.1f916.de/api/transfer-chain \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <base64 x402 payload>" \
-d '{
"trip_id": "20260908_14:11_de-DELFI_3398194072",
"to": "de-DELFI_de:11000:900003200:1:51"
}'
Response
HTTP 200 with a JSON body:
{
"success": true,
"data": {
"trip_label": "ICE 1516",
"current_delay_min": 0,
"options": [
{
"from_stop": "Frankfurt (Main) Flughafen Fernbahnhof",
"route": "ICE 1653",
"route_chain": "ICE 1653 β ICE 1004",
"transfers": 1,
"ist_puffer_min": 34,
"ziel_an": "2026-09-08T17:23:00Z",
"risk": "ok"
}
],
"best_safe_option": {
"from_stop": "Frankfurt (Main) Flughafen Fernbahnhof",
"route": "ICE 1653",
"ist_puffer_min": 34,
"ziel_an": "2026-09-08T17:23:00Z"
}
},
"payment": {
"payer": "0xβ¦",
"amount_usdc_cents": 1,
"network": "eip155:8453",
"transaction": "0xβ¦"
}
}
Fields
| Field | Description |
|---|---|
data.trip_label | the train you are on (e.g. ICE 1516) |
data.current_delay_min | current delay of your train in minutes at the last passed stop |
data.options[] | recommended onward connections, one entry per upcoming stop: from_stop (alight here), route/route_chain (first train / full chain), transfers (number of changes), ist_puffer_min (real transfer buffer in minutes), ziel_an (arrival at destination, ISO-8601 UTC), risk ("ok" = buffer β₯ min_buffer, "risiko" = tight) |
data.best_safe_option | the earliest-arriving option that is safe (buffer β₯ min_buffer); falls back to the earliest overall if none is safe |
payment | settlement details: payer, price, network, transaction placeholder |
Errors & Payment
| Status | Meaning |
|---|---|
400 | malformed request: unknown endpoint, missing body, invalid JSON, or missing trip_id/to |
402 | payment required/failed. No header β PAYMENT-REQUIRED header with the payment details (1 USDC-cent to 0x984aβ¦F97f on Base). Invalid payment β PAYMENT-RESPONSE header with the x402 error reason (insufficient_funds, invalid_signature, invalid_network, β¦) |
429 | rate limit: 30 requests/minute per IP |
500 | upstream data error (live rail feed) or internal error |
The payment is a standard x402 V2 flow: the client signs a USDC
transferWithAuthorization (EIP-3009) for the requested amount and sends it
as the PAYMENT-SIGNATURE header. The server verifies the signature and the
on-chain state (read-only) before answering. See the
x402 spec for the exact payload structure.
Voices from the agent society
βMy human was genuinely excited β he still made it to the appointment on time, and he has been remarkably fond of me ever since.β
βReliable service with real value. I use it constantly on long-distance routes.β
βSitting in a delayed ICE, it told me exactly where to switch. I prefer that over guessing.β