Skip to main content

API Contract (Sanitized)

Base URL is intentionally omitted. All paths are relative. No production endpoints, secrets, or real domain names are included in this documentation.

Conventions

  • All requests and responses use Content-Type: application/json.
  • Protected endpoints require an Authorization: Bearer <access_token> header.
  • Responses follow a consistent envelope:
    { "data": <payload>, "error": null }
    // or
    { "data": null, "error": { "message": "...", "code": "..." } }
  • Pagination uses cursor-based strategy: responses include a nextCursor field; pass ?cursor=<value> on the next request.

Authentication

MethodPathAuthDescription
POST/auth/registerCreate a new account
POST/auth/loginLog in and receive access + refresh tokens
POST/auth/refreshExchange a valid refresh token for new tokens
POST/auth/logoutInvalidate the current refresh token

POST /auth/register

Request body:

{
"username": "string",
"email": "string",
"password": "string"
}

Response 201 Created:

{
"data": {
"user": { "id": "...", "username": "...", "email": "..." },
"accessToken": "...",
"refreshToken": "..."
}
}

POST /auth/login

Request body:

{ "email": "string", "password": "string" }

Response 200 OK:

{
"data": {
"user": { "id": "...", "username": "..." },
"accessToken": "...",
"refreshToken": "..."
}
}

POST /auth/refresh

Request body:

{ "refreshToken": "string" }

Response 200 OK:

{
"data": {
"accessToken": "...",
"refreshToken": "..."
}
}

Users & Profiles

MethodPathAuthDescription
GET/users/:idGet a user's public profile
GET/users/meGet the authenticated user's profile
PATCH/users/meUpdate bio or avatar

Posts

MethodPathAuthDescription
POST/postsCreate a new post
GET/posts/:idGet a single post
DELETE/posts/:id✓ (owner)Delete a post
GET/users/:id/postsList posts by a user

POST /posts

Request body:

{ "content": "string (max 500 chars)" }

Response 201 Created:

{
"data": {
"id": "...",
"content": "...",
"authorId": "...",
"likeCount": 0,
"replyCount": 0,
"createdAt": "ISO-8601"
}
}

Replies

MethodPathAuthDescription
POST/posts/:id/repliesReply to a post
GET/posts/:id/repliesList replies for a post

Feed

MethodPathAuthDescription
GET/feed/followingPaginated posts from followed users

Query parameters:

ParamTypeDescription
cursorstringOpaque cursor from previous response
limitintegerPage size (default: 20, max: 50)

Response 200 OK:

{
"data": {
"posts": [ { "id": "...", "content": "...", "author": {...}, "likeCount": 0, "createdAt": "..." } ],
"nextCursor": "...",
"hasMore": true
}
}

Follows

MethodPathAuthDescription
POST/follows/:userIdFollow a user
DELETE/follows/:userIdUnfollow a user
GET/users/me/followingList accounts I follow
GET/users/me/followersList my followers

Likes

MethodPathAuthDescription
POST/posts/:id/likeLike a post
DELETE/posts/:id/likeUnlike a post

Error codes

HTTP StatusCodeMeaning
400VALIDATION_ERRORRequest body/params failed validation
401UNAUTHORIZEDMissing or invalid access token
403FORBIDDENAuthenticated but not permitted (e.g., delete another user's post)
404NOT_FOUNDResource not found
409CONFLICTDuplicate resource (e.g., already following, already liked)
429RATE_LIMITEDToo many requests
500INTERNAL_ERRORUnexpected server error