GET
/v1/users/profile
Public profile
A user's public profile, looked up by username or id.
Parameters
-
username
optional
username to look up
-
userId
optional
user id to look up
response200
{ "success": true, "profile": { "username": "alice", "bio": "…", "avatar_url": "…" } }
POST
/v1/users/avatar
Upload avatar
Multipart form-data. Images only, 5 MB ceiling.
request
Content-Type: multipart/form-data
field: avatar (image file, max 5MB)
response200
{ "success": true, "avatarUrl": "https://cdn.weggle.xyz/…" }
GET
/v1/users/search
Search people
Match accounts by username or display name. Every result carries follow state in both directions, so a client can draw the right button without a request per row.
Parameters
-
q
required
search query, two characters minimum
-
limit
optional
max results, default 15, ceiling 25
response200
{
"success": true,
"users": [{ "id": "…", "username": "alice", "displayName": "Alice", "bio": "…",
"avatarUrl": "…", "presence": "online", "followerCount": 12,
"isFollowing": false, "followsYou": true, "isSelf": false }]
}
GET
/v1/users/:username
Somebody else's profile
One person, by name, matched case-insensitively. A private profile answers 200 carrying the identity and private: true rather than 404 — the account exists, and a client has to be able to tell "no such person" from "not for you".
response200
{
"success": true,
"data": {
"profile": {
"id": "…", "username": "alice", "displayName": "Alice", "bio": "…",
"avatarUrl": "…", "bannerUrl": "…", "verified": false, "private": false,
"presence": "online", "statusText": null, "lastSeen": "…",
"counts": { "followers": 12, "following": 30, "posts": 8, "memes": 4 },
"viewer": { "isSelf": false, "isFollowing": false, "followsYou": true }
}
}
}
GET
/v1/users/:username/posts
Their posts
The same row shape as /v1/posts/feed, deliberately, so one component in a client draws both.
Parameters
-
limit
optional
max results, default 20, ceiling 50
-
offset
optional
pagination offset
response200
{ "success": true, "posts": [{ "id": 1, "content": "…", "like_count": "3", "liked": true, "comment_count": "1" }] }
GET
/v1/users/:username/memes
Their memes
Public memes, or every one of them on your own profile. Authorised on visibility, never on the stale is_public boolean that nothing keeps in step with it.
Parameters
-
limit
optional
max results, default 24, ceiling 48
-
offset
optional
pagination offset
response200
{ "success": true, "data": { "memes": [{ "id": 1, "title": "…", "imageUrl": "…", "isPublic": true }], "pagination": { "total": 4, "hasMore": false } } }
05 / Social
Social
Friends, followers, and the wall.
/v1/friendsList friendsEvery accepted friendship for the current account.
{ "success": true, "friends": [{ "id": "…", "username": "bob" }] }/v1/friendsSend requestOpen a friend request to another account.
{ "addresseeId": 123 }{ "success": true, "friendship": { "status": "pending" } }/v1/friends/respondRespond to requestAccept or decline an incoming request.
{ "friendshipId": "…", "action": "accept" }{ "success": true }/v1/followersFollowersAccounts following the current user.
{ "success": true, "followers": [{ "username": "…" }], "total": 42 }/v1/followFollowFollow another account.
{ "followingId": 123 }{ "success": true }/wallWall postsPublic wall posts, paginated.
Parameters
pageoptional page number, default 1{ "success": true, "posts": [{ "id": "…", "content": "Hello world", "username": "alice" }] }/wallCreate wall postPost to the public wall. Requires authentication.
{ "content": "Hello, world!" }{ "success": true, "post": { "id": "…" } }/v1/savedWhat you keptMemes, posts and files you have saved, newest save first. Each is re-resolved on read, so anything since made private or deleted is either absent or marked unavailable — a save is a pointer, never a copy.
Parameters
typeoptional meme, post or filelimitoptional max results, default 24, ceiling 48offsetoptional pagination offset{ "success": true, "data": { "items": [{ "type": "meme", "id": 1, "title": "…", "imageUrl": "…", "savedAt": "…", "creator": { "username": "alice" } }, { "type": "meme", "id": 2, "savedAt": "…", "unavailable": true }], "pagination": { "limit": 24, "offset": 0, "hasMore": false } } }/v1/savedSave or unsaveA toggle. Answers with the state it settled on, so a second call from a slow connection ends up showing what is true rather than what it assumed. You may save anything public, and anything of your own.
{ "type": "meme", "id": 1 }{ "success": true, "saved": true }/v1/saved/stateWhich of these are savedOne request for a screenful, so a bookmark glyph does not need a saved column added to the feed, to explore, to a profile and to the file list.
Parameters
typerequired meme, post or fileidsrequired comma-separated, up to 100{ "success": true, "saved": ["1", "4"] }