Skip to content

Media

Media management endpoints. Handles file uploads and management. Uploaded files are served as static files.

Base path: /api/v1/media


List Media

GET /api/v1/media

Required permission: media:read

Query parameters

Parameter Type Default Description
page int 1 Page number
per_page int 20 Items per page
search string Search by filename or original filename

Response 200 OK

{
  "data": [
    {
      "id": "uuid",
      "filename": "550e8400-e29b-41d4-a716-446655440000.jpg",
      "original_filename": "my-photo.jpg",
      "mime_type": "image/jpeg",
      "size": 204800,
      "path": "uploads/media/550e8400-e29b-41d4-a716-446655440000.jpg",
      "alt_text": null
    }
  ],
  "pagination": {
    "total": 50,
    "page": 1,
    "per_page": 20,
    "pages": 3,
    "has_next": true,
    "has_prev": false
  }
}


List Images

Returns only image files (image/* mime types).

GET /api/v1/media/images

Required permission: media:read

Query parameters

Parameter Type Default Description
skip int 0 Pagination offset
limit int 100 Pagination limit

Response 200 OK — list of MediaSummary objects.


Upload File

Uploads a file to the server.

POST /api/v1/media/upload

Required permission: media:upload

Requestmultipart/form-data

Field Type Required Description
file file File to upload

Allowed mime types

Type Extensions
image/jpeg .jpg, .jpeg
image/png .png
image/gif .gif
image/webp .webp
image/svg+xml .svg
application/pdf .pdf
video/mp4 .mp4
video/webm .webm

File size limit

Maximum file size is 10MB. Requests exceeding this limit will be rejected.

Response 201 Created

{
  "id": "uuid",
  "filename": "550e8400-e29b-41d4-a716-446655440000.jpg",
  "original_filename": "my-photo.jpg",
  "mime_type": "image/jpeg",
  "size": 204800,
  "path": "uploads/media/550e8400-e29b-41d4-a716-446655440000.jpg",
  "alt_text": null,
  "uploaded_by": "uuid",
  "created_at": "2026-01-01T00:00:00Z",
  "updated_at": null
}

Errors

Status Description
400 File type not allowed
400 File size exceeds 10MB limit

Get Media

GET /api/v1/media/{id}

Required permission: media:read

Response 200 OK — full MediaResponse object.

Errors

Status Description
404 Media not found

Serve Media File

Streams the physical file directly. Useful for server-side file access.

GET /api/v1/media/{id}/file

Authentication: Not required

Response — raw file stream with appropriate Content-Type header.

Errors

Status Description
404 Media record not found
404 Physical file not found

Update Media

Updates media metadata. Currently only alt_text can be updated.

PATCH /api/v1/media/{id}

Required permission: media:upload

Request body

{
  "alt_text": "A beautiful sunset over the mountains"
}

Field Type Required Constraints
alt_text string Max 255 characters

Response 200 OK — updated MediaResponse object.

Errors

Status Description
404 Media not found

Delete Media

Soft-deletes a media record and removes the physical file from the server.

DELETE /api/v1/media/{id}

Required permission: media:delete

Response 204 No Content

Errors

Status Description
404 Media not found

Warning

Deleting a media file that is referenced by a post, page, or gallery as a featured image will not automatically remove those references. Handle with care.


Accessing Files

Uploaded files are served as static files and publicly accessible without authentication.

GET /uploads/media/{filename}

To construct the full URL for an uploaded file, combine the API base URL with the path field:

const fileUrl = `${API_BASE_URL}/${media.path}`;
// http://localhost:8100/uploads/media/550e8400-e29b-41d4-a716-446655440000.jpg