REST API reference
This page describes the REST API of Fahrtenbuch v0.6.11 (build 209). The web dashboard and the Android app use the same API, so everything they do is available to your own clients, too.
Authoritative contract: OpenAPI specification (v0.6.11). Use the property names and enums from there rather than guessing them.
On a running server, set SHOW_API_UI=true to enable Swagger UI at /api and /api/docs; the specification is then also served at /api/v1/openapi.yml.
Authentication
All endpoints live under https://your-domain.example/api/v1. Protected endpoints need an access token:
Authorization: Bearer <accessToken>
Sign in with POST /auth/login and renew the access token with POST /auth/refresh:
{
"identifier": "admin@example.com",
"password": "your-password",
"deviceName": "Android",
"platform": "android",
"appVersion": "1.0.0"
}
Refresh tokens are rotated: every refresh returns a new one, and the old one stops working. Retry a request once with the new access token after a 401, and avoid refresh loops.
GET /auth/methods tells a client which sign-in methods the server offers (password, TOTP, passkeys). Further methods:
- Passkeys (WebAuthn) for the web and the Android app.
- Google / Microsoft:
GET /auth/oauth/providerslists the enabled providers. Mobile apps start the flow with PKCE (appCodeChallenge) and exchange the returned ticket withPOST /auth/oauth/exchange. - Pairing by QR code: the web dashboard creates a one-time pairing token that a device exchanges for a session.
Server capabilities
GET /config/services returns what the server offers, so clients can hide what is not available:
features– active preview features (expenses,monthlyReportSendNow),- geocoding and
routingavailability,mail,gravatarand thesetupstate.
Disabled preview features answer 404 FEATURE_DISABLED.
Main areas
| Area | Examples |
|---|---|
| Recording | POST /tracking/start (idempotent with a device-generated clientTripId), GPS point upload, POST /tracking/stop with timeZone |
| Trips | list, details, POST /trips (also manual trips with coordinates and distanceKm), PUT /trips/{id}/classify (type, special category, purpose, contact, notes), PUT /trips/{id}/tags, POST /trips/{id}/split, POST /trips/merge, GET /trips/archive, POST /trips/{id}/restore |
| Routes | GET /trips/{id}/matched-route, PUT /trips/{id}/route (points with source), POST /trips/{id}/route/recalculate, POST /trips/{id}/points/remove, POST /trips/{id}/dawarich-import |
| Geocoding | GET /geocoding/search, /reverse, /route, POST /geocoding/route-path |
| Vehicles | vehicles, sharing and invitations, ownership periods, odometer readings |
| Statistics and reports | GET /statistics, monthly statistics, GET /reports/monthly |
| Export and import | GET /export/pdf, /export/csv, /export/gpx, /export/summary; POST /import/gpx, /import/csv |
| User | GET/PATCH /users/me/settings (units, formats, mapStyle, map matching, Gravatar, monthly report), /users/me/dawarich, devices, passkeys, linked accounts |
| Costs (preview) | /expenses, /expenses/summary, CSV import |
| Administration | users, system settings, geocoding, /admin/settings/ai, background jobs, system backup |
Errors
Errors are returned as JSON with a machine-readable code in error, a German message, optional details and a requestId:
{ "error": "TRIP_PERIOD_LOCKED", "message": "…", "details": {}, "requestId": "…" }
Examples: 409 TRIP_PERIOD_LOCKED for a trip in a closed period, 409 TRACKING_ALREADY_ACTIVE when another recording is running. Use the code in your client, not the message.
Time zones
Timestamps are ISO 8601 in UTC. Trips additionally carry startTimeZone and endTimeZone (IANA zone ids); show trip times in those zones. Distances are returned in metres and kilometres, durations in seconds.