Referência
Convenções e erros
As regras que se aplicam a todos os endpoints, para só ter de as aprender uma vez.
Paginação
Os endpoints de listagem recebem page (a começar em 1) e pageSize (1–100, por omissão 30) como parâmetros de query e envolvem os resultados num envelope:
{
"items": [ … ],
"pageNumber": 2,
"totalPages": 9,
"totalCount": 174,
"hasPreviousPage": true,
"hasNextPage": true
}Os enums são strings em camelCase
Os valores enum são sempre strings em camelCase, nunca inteiros: "pounds", "kilometers", "oneRepMax", "chest", "normal". Trate valores enum desconhecidos como compatíveis com versões futuras: podem surgir novos sem mudança de versão.
Unidades
| Medida | Unidade |
|---|---|
| Peso (séries, recordes) | Libras |
| Distância | Metros |
| Duração de série / recorde | Segundos |
| Duração do treino | Minutos (durationMinutes) |
| Medições corporais | O sistema de unidades indicado pelo weightUnit do registo (polegadas com libras, centímetros com quilogramas) |
As unidades de apresentação preferidas do utilizador estão em /api/v1/user. Converta na fronteira da sua app, não no armazenamento.
Identificadores
- Dados de utilizador (treinos, templates, splits, medições): GUIDs estáveis
- Dados de catálogo (exercícios, equipamento): ids inteiros estáveis partilhados com a app Gravl
- O utilizador: um id string opaco, estável em todos os endpoints e tokens
Datas
Todos os timestamps são UTC, ISO 8601 (2026-07-12T17:03:00Z). Os filtros de intervalo de datas (startDate, endDate) são inclusivos.
Limites de pedidos
| Superfície | Limite | Chave |
|---|---|---|
/api/v1/* | 100 pedidos / 15 min | app + utilizador |
/oauth/* | 10 pedidos / min | endereço IP |
Exceder um limite devolve 429 com um cabeçalho Retry-After quando disponível. Recue exponencialmente e evite polling: a maioria dos dados pessoais muda a ritmo humano.
Erros
| Estado | Quando | Corpo |
|---|---|---|
| 401 | Token em falta, malformado, expirado ou revogado; app suspensa | Vazio (challenge WWW-Authenticate) |
| 403 | Token válido, scope em falta | Problem details com o scope em falta identificado |
| 404 | O recurso não existe ou pertence a outro utilizador | Problem details |
| 429 | Limite de pedidos excedido | Vazio; cabeçalho Retry-After |
| 400 | Falha de validação (pageSize inválido, parâmetros malformados) | Problem details com erros por campo |
{
"status": 403,
"title": "Missing scope",
"detail": "This authorization is missing the 'measurements:read' scope."
}Note a regra do 404 para dados alheios: pedir o treino de outro utilizador por id devolve 404, não 403. A API nunca confirma a existência de dados que não pode ver.