Skip to main content

API Documentation

Codex provides a comprehensive RESTful API for managing your digital library. This guide covers authentication, endpoints, and how to use the interactive API documentation.

Base URL

All API endpoints are prefixed with /api/v1:

http://localhost:8080/api/v1

Interactive API Documentation

Codex includes built-in interactive API documentation powered by Scalar (OpenAPI).

Enabling API Docs

API documentation is disabled by default. Enable it in your configuration:

api:
enable_api_docs: true
api_docs_path: "/docs" # Optional, defaults to /docs

Or via environment variable:

CODEX_API_ENABLE_API_DOCS=true

Accessing API Docs

Once enabled, access the interactive documentation at:

http://localhost:8080/docs

Using the API Documentation

  1. Explore Endpoints: Browse all available API endpoints organized by category
  2. Try It Out: Click on any endpoint to make live requests
  3. Authenticate: Use the authentication section to enter your JWT token
  4. View Schemas: Explore request/response schemas and data models

Exporting OpenAPI Specification

Export the OpenAPI spec for client generation or documentation:

# JSON format
codex openapi --output openapi.json --format json

# YAML format
codex openapi --output openapi.yaml --format yaml
Production Note

Disable API documentation in production environments for security:

api:
enable_api_docs: false

Authentication

Codex supports multiple authentication methods.

The primary authentication method for web clients.

1. Login to Get Token

curl -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"username": "admin",
"password": "your-password"
}'

Response:

{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 86400,
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"username": "admin",
"email": "admin@example.com",
"is_admin": true
}
}

2. Use Token in Requests

Include the token in the Authorization header:

curl -H "Authorization: Bearer YOUR_TOKEN_HERE" \
http://localhost:8080/api/v1/libraries

API Keys

For automation and service-to-service communication.

Create an API Key

curl -X POST http://localhost:8080/api/v1/api-keys \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Script Key",
"permissions": ["LibrariesRead", "BooksRead", "PagesRead"]
}'

Response:

{
"id": "550e8400-e29b-41d4-a716-446655440001",
"name": "My Script Key",
"key": "codex_abc12345_xyzSecretPart123456",
"key_prefix": "abc12345",
"permissions": ["LibrariesRead", "BooksRead", "PagesRead"],
"created_at": "2024-01-15T10:30:00Z"
}
warning

The full API key is only shown once! Store it securely.

Use API Key

curl -H "X-API-Key: codex_abc12345_xyzSecretPart123456" \
http://localhost:8080/api/v1/libraries

Or as a Bearer token:

curl -H "Authorization: Bearer codex_abc12345_xyzSecretPart123456" \
http://localhost:8080/api/v1/libraries

HTTP Basic Auth

For simple clients and legacy systems:

curl -u "username:password" http://localhost:8080/api/v1/libraries

API Endpoints

Setup (First Run)

MethodEndpointDescription
GET/setup/statusCheck if initial setup is needed
POST/setup/initializeCreate the initial admin user

Authentication

MethodEndpointDescription
POST/auth/loginUser login
POST/auth/registerUser registration
POST/auth/logoutUser logout
GET/auth/meGet current user info
POST/auth/verify-emailVerify email token
POST/auth/resend-verificationResend verification email

Libraries

MethodEndpointDescription
GET/librariesList all libraries
POST/librariesCreate a library
GET/libraries/{id}Get library details
PUT/libraries/{id}Update a library
DELETE/libraries/{id}Delete a library
GET/libraries/{id}/thumbnailGet library cover image

Create Library Example

curl -X POST http://localhost:8080/api/v1/libraries \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "My Comics",
"path": "/library/comics",
"scanning_config": {
"enabled": true,
"cron_schedule": "0 0 * * *",
"default_mode": "normal",
"scan_on_start": true
}
}'

Scanning

MethodEndpointDescription
POST/libraries/{id}/scanStart a library scan
GET/libraries/{id}/scan-statusGet current scan status
POST/libraries/{id}/scan/cancelCancel running scan
GET/scans/activeList all active scans
GET/scans/streamSSE: Scan progress events

Trigger Scan Example

# Normal scan (only new/changed files)
curl -X POST "http://localhost:8080/api/v1/libraries/{id}/scan?mode=normal" \
-H "Authorization: Bearer $TOKEN"

# Deep scan (re-analyze all files)
curl -X POST "http://localhost:8080/api/v1/libraries/{id}/scan?mode=deep" \
-H "Authorization: Bearer $TOKEN"

Series

MethodEndpointDescription
GET/seriesList all series
POST/series/listAdvanced filtering with conditions
POST/series/searchFull-text search
GET/series/in-progressSeries with in-progress books
GET/series/recently-addedRecently added series
GET/series/recently-updatedRecently updated series
GET/series/{id}Get series details
GET/series/{id}/booksGet books in series
GET/series/{id}/thumbnailGet series cover
POST/series/{id}/analyzeAnalyze all books in series
POST/series/{id}/readMark series as read
POST/series/{id}/unreadMark series as unread

Series Sorting

Use the sort parameter with format field,direction. Available fields: name, date_added, date_updated, release_date, date_read, book_count, file_size, page_count.

curl "http://localhost:8080/api/v1/series?sort=date_added,desc" \
-H "Authorization: Bearer $TOKEN"

Books

MethodEndpointDescription
GET/booksList all books
POST/books/listAdvanced filtering with conditions
GET/books/{id}Get book details
GET/books/{id}/thumbnailGet book cover
POST/books/{id}/analyzeTrigger book analysis
GET/books/in-progressGet books currently being read
GET/books/on-deckNext unread book in started series
GET/books/recently-addedGet recently added books
GET/books/recently-readGet recently read books

On Deck

The "On Deck" endpoint returns the next unread book in series where you have completed at least one book but have no books currently in progress.

curl "http://localhost:8080/api/v1/books/on-deck" \
-H "Authorization: Bearer $TOKEN"

Pages

MethodEndpointDescription
GET/books/{id}/pagesList pages in a book
GET/books/{book_id}/pages/{page_number}Get page image

Page Image Parameters

ParameterTypeDescription
widthintegerMaximum width for resizing
heightintegerMaximum height for resizing
formatstringOutput format: jpeg, png, webp

Example:

curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/api/v1/books/{id}/pages/1?width=800&format=webp"

Reading Progress

MethodEndpointDescription
GET/books/{id}/progressGet reading progress
PUT/books/{id}/progressUpdate reading progress
DELETE/books/{id}/progressClear reading progress
GET/progressGet all user progress
GET/progress/currently-readingGet currently reading books
POST/books/{id}/readMark book as read
POST/books/{id}/unreadMark book as unread

Update Progress Example

curl -X PUT http://localhost:8080/api/v1/books/{id}/progress \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"current_page": 15,
"is_completed": false
}'

Users (Admin Only)

MethodEndpointDescription
GET/usersList all users
POST/usersCreate a user
GET/users/{id}Get user details
PUT/users/{id}Update a user
DELETE/users/{id}Delete a user

API Keys

MethodEndpointDescription
GET/api-keysList your API keys
POST/api-keysCreate an API key
GET/api-keys/{id}Get API key details
PUT/api-keys/{id}Update an API key
DELETE/api-keys/{id}Revoke an API key

Tasks

MethodEndpointDescription
GET/tasksList background tasks
GET/tasks/{id}Get task details
POST/tasks/{id}/cancelCancel a running task
GET/tasks/statsGet task statistics
GET/tasks/streamSSE: Task progress events

Duplicates

MethodEndpointDescription
GET/duplicatesList duplicate book groups
POST/duplicates/scanScan for duplicates
DELETE/duplicates/{id}Dismiss a duplicate group

User Preferences

Per-user settings (theme, language, reader options). See User Management for details.

MethodEndpointDescription
GET/user/preferencesList all preferences
PUT/user/preferences/{key}Set a preference
DELETE/user/preferences/{key}Reset to default

User Integrations

Connect external services (AniList, MyAnimeList, etc.). See User Management for details.

MethodEndpointDescription
GET/user/integrationsList connected and available integrations
POST/user/integrationsConnect integration
DELETE/user/integrations/{name}Disconnect integration
POST/user/integrations/{name}/syncTrigger manual sync

Settings (Admin Only)

MethodEndpointDescription
GET/admin/settingsList all settings
GET/admin/settings/{key}Get a specific setting
PUT/admin/settings/{key}Update a setting
POST/admin/settings/bulkBulk update settings
POST/admin/settings/{key}/resetReset to default
GET/admin/settings/{key}/historyGet setting change history

System Integrations (Admin Only)

App-wide external service connections (metadata providers, notifications).

MethodEndpointDescription
GET/admin/integrationsList all system integrations
POST/admin/integrationsCreate integration
POST/admin/integrations/{id}/testTest connection

Filesystem (Admin Only)

MethodEndpointDescription
GET/filesystem/browseBrowse server directories
GET/filesystem/drivesList available drives (Windows)

Health & Metrics

MethodEndpointDescription
GET/healthHealth check
GET/metricsServer metrics

Real-Time Events (SSE)

Codex uses Server-Sent Events (SSE) for real-time updates.

Entity Events Stream

curl -H "Authorization: Bearer $TOKEN" \
-H "Accept: text/event-stream" \
http://localhost:8080/api/v1/events/stream

Event types:

EventDescription
book_createdNew book added
book_updatedBook metadata changed
book_deletedBook removed
series_createdNew series discovered
series_updatedSeries metadata changed
series_deletedSeries removed
library_createdNew library added
library_updatedLibrary settings changed
cover_updatedThumbnail regenerated

Event format:

event: book_created
data: {"type":"book_created","book_id":"uuid","series_id":"uuid","library_id":"uuid","timestamp":"2024-01-15T10:30:00Z"}

Task Progress Stream

curl -H "Authorization: Bearer $TOKEN" \
-H "Accept: text/event-stream" \
http://localhost:8080/api/v1/tasks/stream

Event format:

event: task_progress
data: {"task_id":"uuid","task_type":"scan_library","status":"running","progress":{"current":25,"total":100,"message":"Scanning file 25/100"}}

SSE Keep-Alive

SSE connections send a keep-alive comment every 15 seconds:

: keep-alive

Pagination

List endpoints support pagination with query parameters:

ParameterDefaultMaxDescription
page0-Page number (0-indexed)
page_size20100Items per page

Example:

curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/api/v1/books?page=2&page_size=50"

Response:

{
"data": [...],
"page": 2,
"page_size": 50,
"total": 500,
"total_pages": 10
}

Filtering & Sorting

Common Query Parameters

ParameterDescriptionExample
library_idFilter by librarylibrary_id=uuid
series_idFilter by seriesseries_id=uuid
sortSort fieldsort=created_at
orderSort directionorder=desc

Sort Fields

Books: title, number, file_size, page_count, created_at, modified_at

Series: name, date_added, date_updated, release_date, date_read, book_count, file_size, filename, page_count

Example:

curl -H "Authorization: Bearer $TOKEN" \
"http://localhost:8080/api/v1/books?library_id=uuid&sort=title&order=asc"

Advanced Filtering

Use POST /series/list or POST /books/list for condition-based filtering.

Condition Structure

Filters use a tree structure with allOf (AND) and anyOf (OR) combinators:

{
"condition": {
"allOf": [
{ "genre": { "operator": "is", "value": "Action" } },
{ "genre": { "operator": "isNot", "value": "Horror" } }
]
},
"fullTextSearch": "batman",
"page": 0,
"pageSize": 20,
"sort": "name,asc"
}

Operators

OperatorDescription
isEquals value
isNotNot equals value
isNullField is null
isNotNullField has value
containsContains substring
beginsWithStarts with

Filter Fields

Series: libraryId, genre, tag, status, publisher, language, name, readStatus

Books: libraryId, seriesId, genre, tag, title, readStatus, hasError

Example: Genre filter with exclusion

curl -X POST http://localhost:8080/api/v1/series/list \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"condition": {
"allOf": [
{ "genre": { "operator": "is", "value": "Action" } },
{ "genre": { "operator": "isNot", "value": "Horror" } }
]
}
}'

See the Filtering & Search guide for more examples.

Error Responses

All errors follow a consistent format:

{
"error": "NotFound",
"message": "Book not found",
"details": null
}

HTTP Status Codes

CodeMeaningDescription
200OKRequest successful
201CreatedResource created
204No ContentSuccess, no response body
400Bad RequestInvalid request data
401UnauthorizedAuthentication required
403ForbiddenInsufficient permissions
404Not FoundResource not found
409ConflictResource conflict
500Internal ErrorServer error

Permissions

API endpoints require specific permissions:

PermissionDescription
LibrariesReadView libraries
LibrariesWriteCreate/update libraries
LibrariesDeleteDelete libraries
SeriesReadView series
SeriesWriteUpdate series
SeriesDeleteDelete series
BooksReadView books
BooksWriteUpdate books/progress
BooksDeleteDelete books
PagesReadView page images
UsersReadView users (admin)
UsersWriteManage users (admin)
UsersDeleteDelete users (admin)
ApiKeysReadView API keys
ApiKeysWriteManage API keys
ApiKeysDeleteDelete API keys
TasksReadView tasks
TasksWriteManage tasks
SystemHealthView metrics
SystemAdminFull admin access

Code Examples

JavaScript/TypeScript

const API_URL = 'http://localhost:8080/api/v1';

// Login
const loginResponse = await fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'admin', password: 'password' })
});
const { access_token } = await loginResponse.json();

// Get libraries
const libraries = await fetch(`${API_URL}/libraries`, {
headers: { 'Authorization': `Bearer ${access_token}` }
}).then(r => r.json());

// Subscribe to events
const eventSource = new EventSource(
`${API_URL}/events/stream`,
{ headers: { 'Authorization': `Bearer ${access_token}` } }
);

eventSource.onmessage = (event) => {
console.log('Event:', JSON.parse(event.data));
};

Python

import requests

API_URL = 'http://localhost:8080/api/v1'

# Login
response = requests.post(f'{API_URL}/auth/login', json={
'username': 'admin',
'password': 'password'
})
token = response.json()['access_token']

headers = {'Authorization': f'Bearer {token}'}

# Get libraries
libraries = requests.get(f'{API_URL}/libraries', headers=headers).json()

# Create a library
new_library = requests.post(f'{API_URL}/libraries', headers=headers, json={
'name': 'My Library',
'path': '/media/comics'
}).json()

cURL

# Login and save token
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password"}' | jq -r '.access_token')

# List libraries
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/api/v1/libraries

# Create library
curl -X POST http://localhost:8080/api/v1/libraries \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Comics","path":"/media/comics"}'

# Get book cover
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/api/v1/books/{id}/thumbnail > cover.jpg

Next Steps