- 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>
123 lines
2.6 KiB
Markdown
123 lines
2.6 KiB
Markdown
# API Reference
|
|
|
|
All endpoints are under `/api/`. JSON in, JSON out. Auth via session cookie + remember-me.
|
|
|
|
## Auth
|
|
|
|
### `POST /api/login`
|
|
```json
|
|
{ "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`
|
|
```json
|
|
{ "name": "Max" }
|
|
```
|
|
Updates display name. Returns `{ ok, name }`.
|
|
|
|
```json
|
|
{ "locale": "de" }
|
|
```
|
|
Updates UI language (`de`, `en`, `pl`). Returns `{ ok, locale }`.
|
|
|
|
### `POST /api/register`
|
|
```json
|
|
{ "email": "...", "password": "...", "token": "<invite-token>", "name": "..." }
|
|
```
|
|
Requires a valid pending invite token. Registers + auto-logs in. Returns `{ ok, email, name }`.
|
|
|
|
### `POST /api/reset-request`
|
|
```json
|
|
{ "email": "..." }
|
|
```
|
|
Sends password reset mail. Always returns `{ ok: true }` (no email enumeration).
|
|
|
|
### `POST /api/reset-password`
|
|
```json
|
|
{ "selector": "...", "token": "...", "password": "..." }
|
|
```
|
|
|
|
### `POST /api/change-password`
|
|
```json
|
|
{ "old_password": "...", "new_password": "..." }
|
|
```
|
|
|
|
---
|
|
|
|
## Goals
|
|
|
|
### `GET /api/goals`
|
|
Returns array of goal objects for the authenticated user.
|
|
|
|
```json
|
|
[{
|
|
"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`
|
|
```json
|
|
{ "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`
|
|
```json
|
|
{ "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.
|
|
|
|
```json
|
|
[{
|
|
"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.
|
|
|
|
```json
|
|
[{
|
|
"id": 1,
|
|
"email": "user@example.com",
|
|
"username": "Max",
|
|
"registered": 1714500000
|
|
}]
|
|
```
|