diff --git a/API-Reference.md b/API-Reference.md new file mode 100644 index 0000000..de38ef3 --- /dev/null +++ b/API-Reference.md @@ -0,0 +1,291 @@ +# API Reference + +**Base URL:** `/api/v1` +**Data format:** JSON +**Interactive docs:** `/api/swagger` (served by the backend at runtime) + +## Authentication + +| Method | Header | When | +|---|---|---| +| JWT | `Authorization: Bearer ` | Web client (short-lived) | +| API Key | `Authorization: ApiKey ` | Third-party apps (long-lived) | + +Generate API keys from the Settings → API Keys page. + +--- + +## Auth Endpoints + +### `POST /auth/register` + +Creates a new user account. + +**Public** — no auth required. + +```json +{ + "username": "frutiger", + "email": "aero@example.com", + "password": "strongpassword123" +} +``` + +| Status | Meaning | +|---|---| +| 201 | Created — returns new User object (password omitted) | +| 400 | Bad Request — invalid input | +| 409 | Conflict — username or email already exists | + +--- + +### `POST /auth/login` + +Authenticates a user and returns a JWT. + +**Public** — no auth required. + +```json +{ + "username": "frutiger", + "password": "strongpassword123" +} +``` + +**Response:** +```json +{ + "token": "eyJhbGci..." +} +``` + +| Status | Meaning | +|---|---| +| 200 | OK — returns JWT | +| 400 | Bad Request | +| 401 | Unauthorized | + +--- + +## User & Profile Endpoints + +### `GET /users/{username}` + +Retrieves the public profile of a user. + +**Public.** + +| Status | Meaning | +|---|---| +| 200 | OK — returns public User object | +| 404 | Not Found | + +--- + +### `GET /users/me` + +Retrieves the full profile of the authenticated user (includes private fields like email). + +**Required:** JWT. + +--- + +### `PUT /users/me` + +Updates the authenticated user's profile. + +**Required:** JWT. + +```json +{ + "displayName": "Frutiger Aero Fan", + "bio": "Est. 2004", + "avatarUrl": "https://...", + "headerUrl": "https://...", + "customCss": "body { background: blue; }", + "topFriends": ["username1", "username2"] +} +``` + +- `topFriends`: up to 8 usernames displayed on your profile +- `customCss`: sanitized on the server (malicious patterns stripped) + +--- + +### `GET /users/{username}/thoughts` + +All thoughts for a specific user, paginated. + +**Public.** + +--- + +## Thoughts Endpoints + +### `POST /thoughts` + +Creates a new thought. + +**Required:** JWT or API Key. + +```json +{ + "content": "This is my first thought! #welcome" +} +``` + +| Status | Meaning | +|---|---| +| 201 | Created — returns new Thought object | +| 400 | Bad Request (e.g. content > 128 chars) | + +Hashtags in `content` are parsed automatically. + +--- + +### `DELETE /thoughts/{id}` + +Deletes a thought. Caller must be the author. + +**Required:** JWT or API Key. + +| Status | Meaning | +|---|---| +| 204 | No Content | +| 403 | Forbidden | +| 404 | Not Found | + +--- + +## Social Endpoints + +### `POST /users/{username}/follow` + +Follow a user. + +**Required:** JWT. + +| Status | Meaning | +|---|---| +| 204 | No Content | +| 404 | Not Found | +| 409 | Conflict — already following | + +--- + +### `DELETE /users/{username}/follow` + +Unfollow a user. + +**Required:** JWT. + +--- + +### `GET /feed` + +The authenticated user's main feed — thoughts from all followed users in reverse-chronological order, paginated. + +**Required:** JWT. + +--- + +## Discovery Endpoints + +### `GET /tags/popular` + +List of currently trending tags. + +**Public.** + +--- + +### `GET /tags/{tagName}` + +All thoughts with a specific tag, paginated, chronological. + +**Public.** + +--- + +### `GET /search` + +Full-text search across thoughts and users. + +**Public** (optional auth for personalized results). + +--- + +## API Key Endpoints + +### `GET /api-keys` + +List all API keys for the authenticated user. + +**Required:** JWT. + +--- + +### `POST /api-keys` + +Create a new API key. + +**Required:** JWT. + +The raw key is returned **once** at creation time — store it securely. + +--- + +### `DELETE /api-keys/{id}` + +Revoke an API key. + +**Required:** JWT. + +--- + +## Data Models + +### User (Public) + +```json +{ + "username": "frutiger", + "displayName": "Frutiger Aero Fan", + "bio": "Est. 2004", + "avatarUrl": "https://...", + "headerUrl": "https://...", + "customCss": "body { background: blue; }", + "topFriends": ["username1", "username2"], + "joinedAt": "2024-01-01T12:00:00Z" +} +``` + +### Thought + +```json +{ + "id": "uuid-v4-string", + "authorUsername": "frutiger", + "content": "This is my first thought! #welcome", + "tags": ["welcome"], + "visibility": "public", + "replyTo": null, + "createdAt": "2024-01-01T12:01:00Z" +} +``` + +`visibility` values: `public`, `followers`, `private`. +`replyTo`: UUID of the parent thought if this is a reply. + +### Pagination + +Paginated endpoints accept `page` and `per_page` query params and return: + +```json +{ + "data": [...], + "page": 1, + "per_page": 20, + "total": 142 +} +```