Forum Wędkarskie API (0.3.0)

Download OpenAPI specification:

Fishing forum API (modular monolith, Clean Architecture).

auth

Register a new account

Request Body schema: application/json
required
username
required
string (Username) [ 3 .. 50 ] characters ^[a-zA-Z0-9_]+$
email
required
string <email> (Email)
password
required
string (Password) [ 8 .. 128 ] characters

Responses

Request samples

Content type
application/json
{
  • "username": "string",
  • "email": "user@example.com",
  • "password": "stringst"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "username": "string",
  • "email": "string",
  • "is_active": true,
  • "roles": [
    ],
  • "permissions": [
    ]
}

Log in with username/email + password

Request Body schema: application/json
required
login
required
string (Login) [ 1 .. 255 ] characters
password
required
string (Password) [ 1 .. 128 ] characters

Responses

Request samples

Content type
application/json
{
  • "login": "string",
  • "password": "string"
}

Response samples

Content type
application/json
{
  • "access_token": "string",
  • "refresh_token": "string",
  • "token_type": "bearer",
  • "expires_in": 0
}

Rotate a refresh token into a new access+refresh pair

cookie Parameters
Refresh Token (string) or Refresh Token (null) (Refresh Token)

Responses

Response samples

Content type
application/json
{
  • "access_token": "string",
  • "refresh_token": "string",
  • "token_type": "bearer",
  • "expires_in": 0
}

Revoke the current refresh token

Authorizations:
HTTPBearer
cookie Parameters
Refresh Token (string) or Refresh Token (null) (Refresh Token)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Revoke every refresh token of the current user

Authorizations:
HTTPBearer

Responses

users

Get the authenticated user's profile

Authorizations:
HTTPBearer

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "username": "string",
  • "email": "string",
  • "is_active": true,
  • "roles": [
    ],
  • "permissions": [
    ]
}

Get a user's public profile by UUID

path Parameters
user_id
required
string (User Id)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "username": "string",
  • "email": "string",
  • "is_active": true,
  • "roles": [
    ],
  • "permissions": [
    ]
}

admin-users

List users (admins / moderators)

Lightweight projection — phase-6 will turn this into a cursor-paginated view.

Authorizations:
HTTPBearer
query Parameters
limit
integer (Limit) [ 1 .. 200 ]
Default: 50
offset
integer (Offset) >= 0
Default: 0

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Assign a role to a user

Authorizations:
HTTPBearer
path Parameters
user_id
required
string <uuid> (User Id)
Request Body schema: application/json
required
role
required
string (Role) [ 1 .. 50 ] characters

Responses

Request samples

Content type
application/json
{
  • "role": "string"
}

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Revoke a role from a user

Authorizations:
HTTPBearer
path Parameters
user_id
required
string <uuid> (User Id)
role_name
required
string (Role Name)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Grant or deny a per-user permission override

Authorizations:
HTTPBearer
path Parameters
user_id
required
string <uuid> (User Id)
Request Body schema: application/json
required
permission
required
string (Permission) [ 1 .. 100 ] characters
granted
boolean (Granted)
Default: true

true => override grants the permission; false => override denies it (deny wins).

Responses

Request samples

Content type
application/json
{
  • "permission": "string",
  • "granted": true
}

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Block or unblock a user account

Authorizations:
HTTPBearer
path Parameters
user_id
required
string <uuid> (User Id)
Request Body schema: application/json
required
blocked
required
boolean (Blocked)

Responses

Request samples

Content type
application/json
{
  • "blocked": true
}

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

posts

List posts (keyset pagination)

query Parameters
Cursor (string) or Cursor (null) (Cursor)
limit
integer (Limit) [ 1 .. 100 ]
Default: 20
Category Id (string) or Category Id (null) (Category Id)
Tag (string) or Tag (null) (Tag)
Author Id (string) or Author Id (null) (Author Id)

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "next_cursor": "string"
}

Create a post

Authorizations:
HTTPBearer
Request Body schema: application/json
required
title
required
string (Title) [ 3 .. 200 ] characters
content
required
string (Content) non-empty
content_format
string (Content Format) ^(plain|markdown)$
Default: "markdown"
Category Id (string) or Category Id (null) (Category Id)
tags
Array of strings (Tags) <= 10 items

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "content": "string",
  • "content_format": "markdown",
  • "category_id": "8de4c9fd-61a4-4c0b-bf88-0ed3a0fe3fa2",
  • "tags": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "slug": "string",
  • "content": "string",
  • "content_format": "string",
  • "author": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "is_deleted": true,
  • "comment_count": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Fetch a single post

path Parameters
post_id
required
string <uuid> (Post Id)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "slug": "string",
  • "content": "string",
  • "content_format": "string",
  • "author": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "is_deleted": true,
  • "comment_count": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Update a post (author or moderator)

Authorizations:
HTTPBearer
path Parameters
post_id
required
string <uuid> (Post Id)
Request Body schema: application/json
required
Title (string) or Title (null) (Title)
Content (string) or Content (null) (Content)
Content Format (string) or Content Format (null) (Content Format)
Category Id (string) or Category Id (null) (Category Id)
Array of Tags (strings) or Tags (null) (Tags)

Responses

Request samples

Content type
application/json
{
  • "title": "string",
  • "content": "string",
  • "content_format": "string",
  • "category_id": "8de4c9fd-61a4-4c0b-bf88-0ed3a0fe3fa2",
  • "tags": [
    ]
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "title": "string",
  • "slug": "string",
  • "content": "string",
  • "content_format": "string",
  • "author": {
    },
  • "category": {
    },
  • "tags": [
    ],
  • "is_deleted": true,
  • "comment_count": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Soft-delete a post (author or moderator)

Authorizations:
HTTPBearer
path Parameters
post_id
required
string <uuid> (Post Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

comments

Comment tree for a post (DFS-ordered)

query Parameters
post_id
required
string <uuid> (Post Id)

UUID of the post to fetch comments for

Responses

Response samples

Content type
application/json
{
  • "items": [
    ]
}

Add a comment (top-level or reply)

Authorizations:
HTTPBearer
Request Body schema: application/json
required
post_id
required
string <uuid> (Post Id)
content
required
string (Content) non-empty
content_format
string (Content Format) ^(plain|markdown)$
Default: "markdown"
Parent Id (string) or Parent Id (null) (Parent Id)

Responses

Request samples

Content type
application/json
{
  • "post_id": "dd3504b4-6e8d-47e2-aab1-573a0c9d6149",
  • "content": "string",
  • "content_format": "markdown",
  • "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "post_id": "dd3504b4-6e8d-47e2-aab1-573a0c9d6149",
  • "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  • "depth": 0,
  • "path": "string",
  • "content": "string",
  • "content_format": "string",
  • "is_deleted": true,
  • "author": {
    },
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Edit a comment (author or moderator)

Authorizations:
HTTPBearer
path Parameters
comment_id
required
string <uuid> (Comment Id)
Request Body schema: application/json
required
content
required
string (Content) non-empty
Content Format (string) or Content Format (null) (Content Format)

Responses

Request samples

Content type
application/json
{
  • "content": "string",
  • "content_format": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "post_id": "dd3504b4-6e8d-47e2-aab1-573a0c9d6149",
  • "parent_id": "1c6ca187-e61f-4301-8dcb-0e9749e89eef",
  • "depth": 0,
  • "path": "string",
  • "content": "string",
  • "content_format": "string",
  • "is_deleted": true,
  • "author": {
    },
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Soft-delete a comment (author or moderator)

Authorizations:
HTTPBearer
path Parameters
comment_id
required
string <uuid> (Comment Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

categories

List categories

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a new category (any authenticated user)

Authorizations:
HTTPBearer
Request Body schema: application/json
required
name
required
string (Name) [ 1 .. 100 ] characters
Slug (string) or Slug (null) (Slug)
Description (string) or Description (null) (Description)

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "slug": "string",
  • "description": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "slug": "string",
  • "description": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05"
}

Delete a category (moderator+)

Authorizations:
HTTPBearer
path Parameters
category_id
required
string <uuid> (Category Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

tags

List all tags

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Create a new tag (moderator+)

Authorizations:
HTTPBearer
Request Body schema: application/json
required
name
required
string (Name) [ 1 .. 50 ] characters

Responses

Request samples

Content type
application/json
{
  • "name": "string"
}

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "name": "string",
  • "slug": "string"
}

files

Start a presigned upload (returns a PUT URL to MinIO)

Authorizations:
HTTPBearer
Request Body schema: application/json
required
original_name
required
string (Original Name) [ 1 .. 255 ] characters
content_type
required
string (Content Type) [ 3 .. 150 ] characters
size_bytes
required
integer (Size Bytes) > 0

Responses

Request samples

Content type
application/json
{
  • "original_name": "string",
  • "content_type": "string",
  • "size_bytes": 0
}

Response samples

Content type
application/json
{
  • "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767",
  • "storage_key": "string",
  • "upload_url": "string",
  • "method": "string",
  • "expires_in_seconds": 0,
  • "max_size_bytes": 0
}

Finalise a presigned upload (validate bytes + thumbnails)

Authorizations:
HTTPBearer
path Parameters
file_id
required
string <uuid> (File Id)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

Upload a file through the backend (proxied fallback)

Authorizations:
HTTPBearer
Request Body schema: multipart/form-data
required
file
required
string <application/octet-stream> (File)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

List my uploaded files (lightweight reuse gallery)

Authorizations:
HTTPBearer
query Parameters
limit
integer (Limit) [ 1 .. 100 ]
Default: 20
offset
integer (Offset) >= 0
Default: 0

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Fetch a file's metadata + fresh presigned URLs

Authorizations:
HTTPBearer
path Parameters
file_id
required
string <uuid> (File Id)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

Delete a file (uploader or file.delete.any)

Authorizations:
HTTPBearer
path Parameters
file_id
required
string <uuid> (File Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Redirect to the file bytes in MinIO (presigned, offloads backend)

Authorizations:
HTTPBearer
path Parameters
file_id
required
string <uuid> (File Id)
query Parameters
download
boolean (Download)
Default: false
Variant (string) or Variant (null) (Variant)

Responses

Response samples

Content type
application/json
null

Attach uploaded files to a post (author or moderator)

Authorizations:
HTTPBearer
path Parameters
post_id
required
string <uuid> (Post Id)
Request Body schema: application/json
required
file_ids
required
Array of strings <uuid> (File Ids) [ 1 .. 20 ] items [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "file_ids": [
    ]
}

Response samples

Content type
application/json
[
  • {
    }
]

List a post's attachments (public)

path Parameters
post_id
required
string <uuid> (Post Id)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Attach uploaded files to a comment (author or moderator)

Authorizations:
HTTPBearer
path Parameters
comment_id
required
string <uuid> (Comment Id)
Request Body schema: application/json
required
file_ids
required
Array of strings <uuid> (File Ids) [ 1 .. 20 ] items [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "file_ids": [
    ]
}

Response samples

Content type
application/json
[
  • {
    }
]

List a comment's attachments (public)

path Parameters
comment_id
required
string <uuid> (Comment Id)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Upload and set the caller's avatar (image only)

Authorizations:
HTTPBearer
Request Body schema: multipart/form-data
required
file
required
string <application/octet-stream> (File)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

Redirect to a user's avatar image (404 if none)

path Parameters
user_id
required
string <uuid> (User Id)
query Parameters
Variant (string) or Variant (null) (Variant)

Responses

Response samples

Content type
application/json
null

Set a category image (owner or category.manage)

Authorizations:
HTTPBearer
path Parameters
category_id
required
string <uuid> (Category Id)
Request Body schema: multipart/form-data
required
file
required
string <application/octet-stream> (File)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

Redirect to a category's image (404 if none)

path Parameters
category_id
required
string <uuid> (Category Id)
query Parameters
Variant (string) or Variant (null) (Variant)

Responses

Response samples

Content type
application/json
null

Set a post (thread) icon (author or post.update.any)

Authorizations:
HTTPBearer
path Parameters
post_id
required
string <uuid> (Post Id)
Request Body schema: multipart/form-data
required
file
required
string <application/octet-stream> (File)

Responses

Response samples

Content type
application/json
{
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "original_name": "string",
  • "content_type": "string",
  • "kind": "string",
  • "size_bytes": 0,
  • "sha256": "string",
  • "status": "string",
  • "owner_type": "string",
  • "owner_id": "8826ee2e-7933-4665-aef2-2393f84a0d05",
  • "width": 0,
  • "height": 0,
  • "created_at": "2019-08-24T14:15:22Z",
  • "updated_at": "2019-08-24T14:15:22Z",
  • "url": "string",
  • "download_url": "string",
  • "variants": {
    }
}

Redirect to a post's icon image (404 if none)

path Parameters
post_id
required
string <uuid> (Post Id)
query Parameters
Variant (string) or Variant (null) (Variant)

Responses

Response samples

Content type
application/json
null

engagement

Like Post

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Unlike Post

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Post Likes

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Like Comment

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Unlike Comment

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Comment Likes

Authorizations:
HTTPBearer
path Parameters
public_id
required
string <uuid> (Public Id)

Responses

Response samples

Content type
application/json
{
  • "count": 0,
  • "liked": true
}

Featured Post

Thread with the most likes (optionally within a category).

The path is deliberately not under /posts/... to avoid colliding with the content module's GET /posts/{id} route.

query Parameters
Category Id (string) or Category Id (null) (Category Id)

Responses

Response samples

Content type
application/json
{
  • "post_id": "dd3504b4-6e8d-47e2-aab1-573a0c9d6149",
  • "likes": 0
}

User Stats

path Parameters
user_id
required
string <uuid> (User Id)

Responses

Response samples

Content type
application/json
{
  • "posts_count": 0,
  • "comments_count": 0,
  • "likes_received": 0,
  • "joined_at": "string"
}

health

Root

Responses

Response samples

Content type
application/json
{
  • "property1": "string",
  • "property2": "string"
}

Health Legacy

Responses

Response samples

Content type
application/json
{
  • "property1": "string",
  • "property2": "string"
}

Health Live

Responses

Response samples

Content type
application/json
{
  • "property1": "string",
  • "property2": "string"
}

Health Ready

Responses

Response samples

Content type
application/json
{
  • "property1": "string",
  • "property2": "string"
}

Metrics

Endpoint that serves Prometheus metrics.

Responses

Response samples

Content type
application/json
null