Reference

Conventions & errors

The rules that hold across every endpoint, so you only have to learn them once.

Pagination

List endpoints take page (1-based) and pageSize (1–100, default 30) as query parameters and wrap results in one envelope:

{
  "items": [ … ],
  "pageNumber": 2,
  "totalPages": 9,
  "totalCount": 174,
  "hasPreviousPage": true,
  "hasNextPage": true
}

Enums are camelCase strings

Enum values are always strings in camelCase — never integers: "pounds", "kilometers", "oneRepMax", "chest", "normal". Treat unknown enum values as forward-compatible: new ones may appear without a version bump.

Units

MeasureUnit
Weight (sets, records)Pounds
DistanceMeters
Set / record durationSeconds
Workout durationMinutes (durationMinutes)
Body measurementsThe unit system in the entry’s weightUnit (inches with pounds, centimeters with kilograms)

The user’s preferred display units are on /api/v1/user — convert at the edge of your app, not in storage.

Identifiers

  • User data (workouts, templates, splits, measurements) — stable GUIDs
  • Catalog data (exercises, equipment) — stable integer ids shared with the Gravl app
  • The user — an opaque string id, stable across all endpoints and tokens

Dates

All timestamps are UTC, ISO 8601 (2026-07-12T17:03:00Z). Date-range filters (startDate, endDate) are inclusive.

Rate limits

SurfaceLimitKeyed by
/api/v1/*100 requests / 15 minapp + user
/oauth/*10 requests / minIP address

Exceeding a limit returns 429 with a Retry-After header when available. Back off exponentially; don’t poll — most personal data changes at human speed.

Errors

StatusWhenBody
401Missing, malformed, expired or revoked token; suspended appEmpty (WWW-Authenticate challenge)
403Valid token, missing scopeProblem details with the missing scope named
404Resource doesn’t exist — or belongs to another userProblem details
429Rate limitedEmpty; Retry-After header
400Validation failure (bad page size, malformed parameters)Problem details with field errors
Problem details (RFC 7807)
{
  "status": 403,
  "title": "Missing scope",
  "detail": "This authorization is missing the 'measurements:read' scope."
}

Note the 404-for-foreign-data rule: requesting another user’s workout by id returns 404, not 403 — the API never confirms that data you can’t see exists.