- Add RefreshToken model with rotation - Add POST /auth/refresh endpoint - Add POST /auth/logout that revokes refresh token - Login returns JWT (8h) + refresh_token (30 days) - Refresh rotates token (old is revoked) - Fix Carbon\Carbon::now() calls instead of now() helper - Update API docs
84 lines
3.0 KiB
Markdown
84 lines
3.0 KiB
Markdown
# DriveTime Planner API
|
|
|
|
## Base URL
|
|
`https://api.fahrschultermin.de/api/v1`
|
|
|
|
## Authentication
|
|
JWT Bearer Token. Login returns a token valid for 8 hours.
|
|
|
|
```
|
|
Authorization: Bearer <token>
|
|
```
|
|
|
|
## Endpoints
|
|
|
|
### Auth
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| POST | `/auth/login` | Login with email/password, returns JWT + refresh_token |
|
|
| POST | `/auth/refresh` | Exchange refresh_token for new JWT + refresh_token |
|
|
| POST | `/auth/logout` | Revoke refresh token (logout) |
|
|
| GET | `/auth/me` | Current user info (requires auth) |
|
|
|
|
### Bootstrap
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/bootstrap` | Full frontend data: user, tenant, students, instructors, lessonTypes, templates (requires auth) |
|
|
|
|
### CRUD
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/students` | List students (requires auth) |
|
|
| POST | `/students` | Create student (requires auth) |
|
|
| PATCH | `/students/{id}` | Update student (requires auth) |
|
|
| DELETE | `/students/{id}` | Delete student (requires auth) |
|
|
| GET | `/instructors` | List instructors (requires auth) |
|
|
| POST | `/instructors` | Create instructor (requires auth) |
|
|
| PATCH | `/instructors/{id}` | Update instructor (requires auth) |
|
|
| GET | `/appointments` | List appointments, optionally filter by `from`/`to` query params (requires auth) |
|
|
| POST | `/appointments` | Create appointment with instructor conflict detection (requires auth) |
|
|
| PATCH | `/appointments/{id}` | Update appointment with conflict check (requires auth) |
|
|
| DELETE | `/appointments/{id}` | Delete appointment (requires auth) |
|
|
| GET | `/lesson-types` | List lesson types (requires auth) |
|
|
| GET | `/license-class-templates` | List license class templates with requirements (requires auth) |
|
|
|
|
## Error Responses
|
|
| Code | Meaning |
|
|
|------|---------|
|
|
| 400 | Bad Request — missing or invalid parameters |
|
|
| 401 | Unauthorized — missing or invalid JWT |
|
|
| 404 | Not Found — resource doesn't exist or wrong tenant |
|
|
| 409 | Conflict — e.g. instructor has overlapping appointment |
|
|
| 500 | Internal Server Error |
|
|
|
|
## Environment Variables
|
|
|
|
| Variable | Description |
|
|
|----------|-------------|
|
|
| `JWT_SECRET` | 256-bit secret for JWT signing (required) |
|
|
|
|
## Example
|
|
|
|
```bash
|
|
# Login
|
|
TOKEN=$(curl -s -X POST https://api.fahrschultermin.de/api/v1/auth/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"admin@nordring.test","password":"Tanja82"}' | jq -r '.token')
|
|
|
|
# Get bootstrap data
|
|
curl https://api.fahrschultermin.de/api/v1/bootstrap \
|
|
-H "Authorization: Bearer $TOKEN" | jq .
|
|
|
|
# Create appointment
|
|
curl -X POST https://api.fahrschultermin.de/api/v1/appointments \
|
|
-H "Authorization: Bearer $TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"instructor_id":1,"lesson_type_id":1,"start_at":"2026-05-25 10:00","end_at":"2026-05-25 11:00","title":"Test"}'
|
|
```
|
|
|
|
## Tech Stack
|
|
- Slim 4 (PSR-7 HTTP factory)
|
|
- Eloquent ORM (Illuminate Database)
|
|
- Firebase JWT for authentication
|
|
- PHP-DI for dependency injection
|
|
- CORS middleware (tuupola/cors-middleware) |