282 lines
6.2 KiB
Markdown
282 lines
6.2 KiB
Markdown
# Scrum4Me REST API
|
|
|
|
REST-API contract voor Claude Code en andere clients.
|
|
|
|
## Authenticatie
|
|
|
|
Alle endpoints behalve `GET /api/health` vereisen een Bearer-token:
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
Tokens beheer je via Instellingen → Tokens (`/settings/tokens`). Een token is gekoppeld aan één gebruiker; een demo-account-token kan lezen maar niet schrijven (`403`).
|
|
|
|
## Status-enums
|
|
|
|
De API gebruikt **lowercase** statussen. De database gebruikt UPPER_SNAKE; de vertaling gebeurt op de boundary.
|
|
|
|
| Entiteit | Waarden |
|
|
|---|---|
|
|
| Task status | `todo`, `in_progress`, `review`, `done` |
|
|
| Story status | `open`, `in_sprint`, `done` |
|
|
|
|
## Foutcodes
|
|
|
|
| Code | Betekenis |
|
|
|---|---|
|
|
| `200` | OK |
|
|
| `201` | Created |
|
|
| `400` | Malformed body (bv. ongeldige JSON) |
|
|
| `401` | Token ontbreekt of ongeldig |
|
|
| `403` | Token heeft geen toegang (demo-account, geen lid van product) |
|
|
| `404` | Resource niet gevonden |
|
|
| `422` | Validatiefout — body is wel-gevormd maar niet acceptabel |
|
|
| `500` | Onverwachte serverfout |
|
|
|
|
---
|
|
|
|
## Endpoints
|
|
|
|
### `GET /api/health`
|
|
|
|
Health-probe. Geen authenticatie vereist.
|
|
|
|
**Query params:** `?db=1` voegt een DB-ping toe.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{ "status": "ok", "version": "0.3.x", "time": "2026-04-26T20:00:00Z" }
|
|
```
|
|
|
|
Met `?db=1`:
|
|
```json
|
|
{ "status": "ok", "version": "0.3.x", "time": "...", "database": "ok" }
|
|
```
|
|
|
|
`database` is `"ok"` of `"down"`. De endpoint zelf retourneert altijd `200`.
|
|
|
|
```bash
|
|
curl https://scrum4me.app/api/health?db=1
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /api/products`
|
|
|
|
Lijst van actieve producten waar de tokengebruiker eigenaar of lid van is.
|
|
|
|
**Response (200):**
|
|
```json
|
|
[
|
|
{
|
|
"id": "cmofu...",
|
|
"code": "SCRUM4ME",
|
|
"name": "Scrum4Me",
|
|
"description": "...",
|
|
"repo_url": "https://github.com/...",
|
|
"definition_of_done": "..."
|
|
}
|
|
]
|
|
```
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" https://scrum4me.app/api/products
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /api/products/:id/claude-context`
|
|
|
|
Bundled context voor Claude Code: product, actieve sprint, volgende story (met tasks) en open todos van de tokengebruiker — in één call.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"product": { "id", "code", "name", "description", "repo_url", "definition_of_done" },
|
|
"active_sprint": { "id": "...", "sprint_goal": "...", "status": "ACTIVE" } | null,
|
|
"next_story": {
|
|
"id", "code", "title", "description", "acceptance_criteria",
|
|
"priority", "status",
|
|
"tasks": [
|
|
{ "id", "code", "title", "description", "implementation_plan",
|
|
"priority", "sort_order", "status" }
|
|
]
|
|
} | null,
|
|
"open_todos": [
|
|
{ "id", "title", "description", "created_at" }
|
|
]
|
|
}
|
|
```
|
|
|
|
`open_todos` is gelimiteerd op 50 items, gesorteerd op `created_at` asc. Demo-tokens kunnen dit endpoint lezen.
|
|
|
|
```bash
|
|
curl -H "Authorization: Bearer $TOKEN" \
|
|
https://scrum4me.app/api/products/$PRODUCT_ID/claude-context
|
|
```
|
|
|
|
---
|
|
|
|
### `GET /api/products/:id/next-story`
|
|
|
|
Hoogst geprioriteerde open story in de actieve sprint.
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"id": "...",
|
|
"code": "ST-356",
|
|
"title": "Solo Kanban-bord met DnD en Zustand",
|
|
"description": "...",
|
|
"acceptance_criteria": "...",
|
|
"status": "in_sprint",
|
|
"tasks": [
|
|
{
|
|
"id": "...",
|
|
"code": "ST-356.1",
|
|
"title": "Store stores/solo-store.ts",
|
|
"description": "...",
|
|
"implementation_plan": null,
|
|
"priority": 2,
|
|
"sort_order": 1,
|
|
"status": "todo"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Foutcodes:** `404` als geen actieve sprint of geen open stories.
|
|
|
|
---
|
|
|
|
### `GET /api/sprints/:id/tasks`
|
|
|
|
Lijst taken van de sprint, geordend op `(story.sort_order, task.priority, task.sort_order)`.
|
|
|
|
**Query params:** `?limit=N` (default 10, max 50)
|
|
|
|
**Response (200):**
|
|
```json
|
|
[
|
|
{
|
|
"id": "...",
|
|
"code": "ST-356.1",
|
|
"title": "...",
|
|
"description": "...",
|
|
"implementation_plan": null,
|
|
"story_id": "...",
|
|
"story_code": "ST-356",
|
|
"priority": 2,
|
|
"sort_order": 1,
|
|
"status": "todo"
|
|
}
|
|
]
|
|
```
|
|
|
|
---
|
|
|
|
### `PATCH /api/stories/:id/tasks/reorder`
|
|
|
|
Volgorde van taken binnen een story aanpassen.
|
|
|
|
**Body:**
|
|
```json
|
|
{ "task_ids": ["task-id-a", "task-id-b", "task-id-c"] }
|
|
```
|
|
|
|
Alle IDs moeten bij de story horen. **Foutcodes:** `422` bij Zod-fouten of als een task_id niet tot de story behoort.
|
|
|
|
---
|
|
|
|
### `PATCH /api/tasks/:id`
|
|
|
|
Status of implementation_plan bijwerken. Minstens één van beide is verplicht.
|
|
|
|
**Body:**
|
|
```json
|
|
{ "status": "in_progress", "implementation_plan": "..." }
|
|
```
|
|
|
|
**Response (200):**
|
|
```json
|
|
{
|
|
"id": "...",
|
|
"status": "in_progress",
|
|
"implementation_plan": "..."
|
|
}
|
|
```
|
|
|
|
**Foutcodes:** `422` bij ongeldige body of onbekende status. `403` bij demo-token.
|
|
|
|
---
|
|
|
|
### `POST /api/stories/:id/log`
|
|
|
|
Activiteit vastleggen op een story.
|
|
|
|
**Body — IMPLEMENTATION_PLAN:**
|
|
```json
|
|
{
|
|
"type": "IMPLEMENTATION_PLAN",
|
|
"content": "Plan: ...",
|
|
"metadata": { "branch": "feat/x" }
|
|
}
|
|
```
|
|
|
|
**Body — TEST_RESULT:**
|
|
```json
|
|
{
|
|
"type": "TEST_RESULT",
|
|
"content": "Alle tests groen",
|
|
"status": "PASSED",
|
|
"metadata": { "ci_run": "..." }
|
|
}
|
|
```
|
|
|
|
**Body — COMMIT:**
|
|
```json
|
|
{
|
|
"type": "COMMIT",
|
|
"content": "Werk afgerond",
|
|
"commit_hash": "abc123",
|
|
"commit_message": "feat(ST-XXX): ...",
|
|
"metadata": { "branch": "feat/x" }
|
|
}
|
|
```
|
|
|
|
`metadata` is optioneel, vrij JSON-object. **Response (201):**
|
|
```json
|
|
{ "id": "...", "created_at": "..." }
|
|
```
|
|
|
|
---
|
|
|
|
### `POST /api/todos`
|
|
|
|
Nieuwe todo voor de tokengebruiker.
|
|
|
|
**Body:**
|
|
```json
|
|
{
|
|
"title": "Een ding doen",
|
|
"description": "Optionele uitleg, max 2000 tekens",
|
|
"product_id": "cmof..."
|
|
}
|
|
```
|
|
|
|
**Response (201):**
|
|
```json
|
|
{ "id": "...", "title": "...", "description": "...", "created_at": "..." }
|
|
```
|
|
|
|
---
|
|
|
|
## Voorbeeldworkflow voor Claude Code
|
|
|
|
1. **Probe:** `GET /api/health?db=1` — bevestig dat de service en DB bereikbaar zijn.
|
|
2. **Context:** `GET /api/products/$ID/claude-context` — haal product, sprint, volgende story en todos op in één call.
|
|
3. **Plan vastleggen:** `POST /api/stories/$STORY_ID/log` met `type: IMPLEMENTATION_PLAN`.
|
|
4. **Per task:** `PATCH /api/tasks/$TASK_ID` met `status: "in_progress"`, daarna met `status: "done"` plus eventueel `implementation_plan`.
|
|
5. **Test:** `POST /api/stories/$STORY_ID/log` met `type: TEST_RESULT` en `status: PASSED|FAILED`.
|
|
6. **Commit:** `POST /api/stories/$STORY_ID/log` met `type: COMMIT`, `commit_hash`, `commit_message`, optioneel `metadata: { branch }`.
|