Table of Contents
- API Reference
- Authentication
- Auth
- Users & Profiles
- Thoughts
- POST /thoughts
- GET /thoughts/{id}
- DELETE /thoughts/{id}
- GET /thoughts/{id}/thread
- PUT /thoughts/{id}
- Social
- POST /users/{username}/follow
- DELETE /users/{username}/follow
- GET /users/{username}/followers
- GET /users/{username}/following
- POST /thoughts/{id}/like
- DELETE /thoughts/{id}/like
- POST /thoughts/{id}/boost
- DELETE /thoughts/{id}/boost
- POST /users/{username}/block
- Feed & Discovery
- Notifications
- GET /notifications
- GET /notifications/unread-count
- POST /notifications/{id}/read
- POST /notifications/read-all
- API Keys
- Federation Management
- GET /federation/pending-followers
- POST /federation/accept-follower
- POST /federation/reject-follower
- DELETE /federation/remote-follower
- GET /federation/remote-following
- POST /federation/follow-remote
- POST /federation/unfollow-remote
- GET /remote-actors
- ActivityPub Endpoints
- Data Models
API Reference
Base URL: / (all REST endpoints at root)
API port: 8000 (default)
Interactive docs: /docs (Swagger UI) · /scalar (Scalar UI)
Authentication
| Method | Header | When |
|---|---|---|
| JWT | Authorization: Bearer <token> |
Web client (short-lived) |
| API Key | Authorization: ApiKey <key> |
Third-party apps (long-lived) |
Obtain a JWT from POST /auth/login. Generate API keys from Settings → API Keys.
Auth
POST /auth/register
Create a new user account. Public.
{ "username": "frutiger", "email": "aero@example.com", "password": "..." }
| Status | Meaning |
|---|---|
| 201 | Created — returns User object |
| 400 | Bad Request |
| 409 | Conflict — username or email taken |
POST /auth/login
Authenticate and receive a JWT. Public.
{ "username": "frutiger", "password": "..." }
Response: { "token": "eyJ..." }
Users & Profiles
GET /users/{username}
Public profile. Content negotiation: returns AP actor JSON if Accept: application/activity+json, otherwise REST profile.
GET /users/me
Authenticated user's full profile (includes email). JWT required.
PUT /users/me
Update profile. JWT required.
{
"displayName": "Frutiger Aero Fan",
"bio": "Est. 2004",
"avatarUrl": "https://...",
"headerUrl": "https://...",
"customCss": "body { background: blue; }",
"topFriends": ["username1", "username2"]
}
customCss is sanitized server-side. topFriends accepts up to 5 usernames.
GET /users
List all users with stats. Public.
GET /users/{username}/thoughts
User's thoughts, paginated. Public.
Thoughts
POST /thoughts
Create a thought. JWT or API Key required.
{ "content": "Hello world! #welcome", "visibility": "public" }
visibility: public | followers | private. Hashtags parsed automatically. Max 128 chars.
| Status | Meaning |
|---|---|
| 201 | Created |
| 400 | Content too long or invalid |
GET /thoughts/{id}
Get a single thought. Public (respects visibility).
DELETE /thoughts/{id}
Delete own thought. JWT or API Key required.
GET /thoughts/{id}/thread
Full reply thread. Public.
PUT /thoughts/{id}
Edit thought content. JWT required. Broadcasts Update(Note) to federation.
Social
POST /users/{username}/follow
Follow a local user. JWT required.
DELETE /users/{username}/follow
Unfollow. JWT required.
GET /users/{username}/followers
Follower list. Public.
GET /users/{username}/following
Following list. Public.
POST /thoughts/{id}/like
Like a thought. JWT required. Sends Like activity to remote authors.
DELETE /thoughts/{id}/like
Unlike. JWT required.
POST /thoughts/{id}/boost
Boost (announce) a thought. JWT required. Broadcasts Announce.
DELETE /thoughts/{id}/boost
Undo boost. JWT required.
POST /users/{username}/block
Block a user. JWT required. Delivers Block activity.
Feed & Discovery
GET /feed
Home feed — thoughts from followed users, reverse-chronological. JWT required.
GET /feed/public
Public feed — all public thoughts. Public (optional auth for like/boost state).
GET /tags/popular
Popular tags list. Public.
GET /tags/{tagName}
Thoughts for a specific tag. Public.
GET /search
Full-text search over thoughts and users (PostgreSQL trigram). Public.
Query params: q, page, per_page.
Notifications
GET /notifications
List notifications for the authenticated user. JWT required.
GET /notifications/unread-count
Count of unread notifications. JWT required.
POST /notifications/{id}/read
Mark a notification read. JWT required.
POST /notifications/read-all
Mark all notifications read. JWT required.
API Keys
GET /api-keys
List own keys. JWT required.
POST /api-keys
Create a key. JWT required. Raw key returned once — store immediately.
DELETE /api-keys/{id}
Revoke a key. JWT required.
Federation Management
GET /federation/pending-followers
List remote actors with pending follow requests. JWT required.
POST /federation/accept-follower
Accept a remote follow request. JWT required.
POST /federation/reject-follower
Reject a remote follow request. JWT required.
DELETE /federation/remote-follower
Remove an accepted remote follower. JWT required.
GET /federation/remote-following
List remote actors this user follows. JWT required.
POST /federation/follow-remote
Follow a remote actor by @user@instance handle. JWT required.
POST /federation/unfollow-remote
Unfollow a remote actor. JWT required.
GET /remote-actors
Look up a remote actor by handle. JWT required.
ActivityPub Endpoints
These are consumed by other Fediverse servers, not the frontend.
| Endpoint | Description |
|---|---|
GET /.well-known/webfinger |
WebFinger discovery |
GET /.well-known/nodeinfo |
NodeInfo pointer |
GET /nodeinfo/2.1 |
NodeInfo stats |
GET /users/{username} (AP Accept) |
Actor JSON |
GET /users/{username}/outbox |
Paginated outbox |
GET /users/{username}/followers |
Followers collection |
GET /users/{username}/following |
Following collection |
POST /users/{username}/inbox |
Shared inbox |
Data Models
User (public)
{
"username": "frutiger",
"displayName": "Frutiger Aero Fan",
"bio": "Est. 2004",
"avatarUrl": "https://...",
"headerUrl": "https://...",
"customCss": "body { background: blue; }",
"joinedAt": "2024-01-01T12:00:00Z"
}
Thought
{
"id": "uuid",
"authorUsername": "frutiger",
"content": "Hello world! #welcome",
"tags": ["welcome"],
"visibility": "public",
"replyTo": null,
"likeCount": 3,
"boostCount": 1,
"likedByMe": false,
"boostedByMe": false,
"createdAt": "2024-01-01T12:01:00Z"
}
Pagination
All paginated endpoints accept page and per_page and return:
{ "data": [...], "page": 1, "per_page": 20, "total": 142 }