- Delete root app.js (pre-Symfony legacy copy, no longer served anywhere) - CLAUDE.md: remove sync instruction, drop outdated pending-cleanup items, add AdminController to key files, fix i18n note (DE/EN/PL), fix Twig cache note - docs/api.md: document locale/is_admin in /api/me, PATCH locale, new GET /api/admin/users endpoint - docs/structure.md: add AdminController, clean up legacy table descriptions Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.6 KiB
API Reference
All endpoints are under /api/. JSON in, JSON out. Auth via session cookie + remember-me.
Auth
POST /api/login
{ "email": "...", "password": "..." }
Returns { ok, email, name } or 401.
POST /api/logout
Invalidates session. Returns { ok: true }.
GET /api/me
Returns { ok, email, id, name, locale, is_admin } or { ok: false } (401) if not logged in.
PATCH /api/me
{ "name": "Max" }
Updates display name. Returns { ok, name }.
{ "locale": "de" }
Updates UI language (de, en, pl). Returns { ok, locale }.
POST /api/register
{ "email": "...", "password": "...", "token": "<invite-token>", "name": "..." }
Requires a valid pending invite token. Registers + auto-logs in. Returns { ok, email, name }.
POST /api/reset-request
{ "email": "..." }
Sends password reset mail. Always returns { ok: true } (no email enumeration).
POST /api/reset-password
{ "selector": "...", "token": "...", "password": "..." }
POST /api/change-password
{ "old_password": "...", "new_password": "..." }
Goals
GET /api/goals
Returns array of goal objects for the authenticated user.
[{
"id": "1",
"name": "Liegestütz",
"unit": "Stück",
"daily": 50,
"days": 30,
"start": "2026-04-01 00:00:00",
"sets": { "2026-04-01": [20, 30], "2026-04-02": [50] }
}]
sets is a JSON object keyed by date (YYYY-MM-DD), values are arrays of logged amounts.
POST /api/goals
{ "name": "...", "unit": "Stück", "daily": 50, "days": 30, "start": "2026-04-01" }
PATCH /api/goals/{id}
Partial update — send only fields to change: name, unit, daily, days, sets.
DELETE /api/goals/{id}
Deletes goal. Only owner can delete.
Invites
POST /api/invite
{ "note": "Max" }
Creates a 7-day single-use invite token. Returns { url: "http://dudi.local/?invite=<token>" }.
GET /api/invites
Returns all invites created by the authenticated user.
[{
"url": "http://dudi.local/?invite=...", // null if used or expired
"note": "Max",
"status": "pending", // "pending" | "used" | "expired"
"created_at": "...",
"expires_at": "...",
"used_at": null,
"used_by_email": null
}]
Admin
GET /api/admin/users
Returns all users. Only accessible if the logged-in user's email matches ADMIN_EMAIL env var; returns 403 otherwise.
[{
"id": 1,
"email": "user@example.com",
"username": "Max",
"registered": 1714500000
}]