Skip to main content
Version: Current

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/providers lists the enabled providers. Mobile apps start the flow with PKCE (appCodeChallenge) and exchange the returned ticket with POST /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 routing availability, mail, gravatar and the setup state.

Disabled preview features answer 404 FEATURE_DISABLED.

Main areas​

AreaExamples
RecordingPOST /tracking/start (idempotent with a device-generated clientTripId), GPS point upload, POST /tracking/stop with timeZone
Tripslist, 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
RoutesGET /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
GeocodingGET /geocoding/search, /reverse, /route, POST /geocoding/route-path
Vehiclesvehicles, sharing and invitations, ownership periods, odometer readings
Statistics and reportsGET /statistics, monthly statistics, GET /reports/monthly
Export and importGET /export/pdf, /export/csv, /export/gpx, /export/summary; POST /import/gpx, /import/csv
UserGET/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
Administrationusers, 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.