42 KiB
Suwayomi-Server REST API Documentation
This document describes all REST API endpoints available in Suwayomi-Server.
Base URL: http://localhost:4567/api/v1/
Authentication
All API endpoints (except where noted) require HTTP Basic Authentication.
Authorization Header
Include the following header in your requests:
Authorization: Basic <base64-encoded-credentials>
How to Generate the Header
- Combine username and password with a colon:
username:password - Encode the string in Base64
- Prepend with
Basic
Example:
- Username:
admin - Password:
password123 - Credentials string:
admin:password123 - Base64 encoded:
YWRtaW46cGFzc3dvcmQxMjM= - Header:
Authorization: Basic YWRtaW46cGFzc3dvcmQxMjM=
Default Credentials
The default username and password are configured in the server settings:
- Default username:
admin - Default password:
admin
Note: These should be changed in production via server configuration.
Authentication Modes
The server supports different authentication modes (configured in server settings):
BASIC_AUTH- Requires Basic Auth header for all API requestsSIMPLE_LOGIN- Uses cookie-based session authentication for web interface, but requires Basic Auth for APINONE- No authentication required (not recommended for production)
Unauthorized Response
If authentication fails, the server returns:
HTTP 401 Unauthorized
WWW-Authenticate: Basic
Response Body:
{
"error": "Unauthorized",
"message": "Authentication required"
}
WebSocket Authentication
WebSocket endpoints use the same Basic Authentication mechanism. Include the Authorization header when establishing the WebSocket connection.
Table of Contents
- Extension Endpoints
- Source Endpoints
- Manga Endpoints
- Chapter Endpoints
- Category Endpoints
- Backup Endpoints
- Download Endpoints
- Update Endpoints
- Track Endpoints
- Global Meta Endpoints
- Settings Endpoints
- WebView Endpoints
- WebSocket Endpoints
- OPDS Endpoints
Extension Endpoints
GET /api/v1/extension/list
- What it does: List all installed extensions
- Expected request: No parameters required
- Expected response: JSON array of ExtensionDataClass objects (HTTP 200)
Response JSON Example:
[
{
"repo": "https://raw.githubusercontent.com/k对身体1/extensions/repo",
"apkName": "extensions/kofthub/Dramacafe",
"iconUrl": "/extension/icon/Dramacafe.apk",
"name": "Dramacafe",
"pkgName": "eu.kanade.tachiyomi.extension.en.dramacafe",
"versionName": "1.2.3",
"versionCode": 12,
"lang": "en",
"isNsfw": false,
"installed": true,
"hasUpdate": false,
"obsolete": false
}
]
GET /api/v1/extension/install/{pkgName}
- What it does: Install an extension by package name
- Expected request: Path parameter:
pkgName(string) - e.g.,eu.kanade.tachiyomi.extension.en.mangadex - Expected response: HTTP 201 (Created), HTTP 302 (Found), or HTTP 500 (Internal Server Error)
POST /api/v1/extension/install
- What it does: Install an extension from uploaded APK file
- Expected request: Multipart form data with file field named "file" containing the extension APK
- Expected response: HTTP 201 (Created), HTTP 302 (Found), or HTTP 500 (Internal Server Error)
GET /api/v1/extension/update/{pkgName}
- What it does: Update an extension by package name
- Expected request: Path parameter:
pkgName(string) - Expected response: HTTP 201 (Created), HTTP 302 (Found), HTTP 404 (Not Found), or HTTP 500 (Internal Server Error)
GET /api/v1/extension/uninstall/{pkgName}
- What it does: Uninstall an extension by package name
- Expected request: Path parameter:
pkgName(string) - Expected response: HTTP 200 (OK), HTTP 404 (Not Found), or HTTP 500 (Internal Server Error)
GET /api/v1/extension/icon/{apkName}
- What it does: Get the icon for an extension
- Expected request: Path parameter:
apkName(string) - e.g.,Dramacafe.apk - Expected response: Image file (PNG/JPEG) with HTTP 200, or HTTP 404 (Not Found)
Source Endpoints
GET /api/v1/source/list
- What it does: List all available sources
- Expected request: No parameters required
- Expected response: JSON array of SourceDataClass objects (HTTP 200)
Response JSON Example:
[
{
"id": "1234567890",
"name": "MangaDex",
"lang": "en",
"iconUrl": "/source/icon/1234567890",
"supportsLatest": true,
"isConfigurable": true,
"isNsfw": false,
"displayName": "MangaDex",
"baseUrl": "https://mangadex.org"
}
]
GET /api/v1/source/{sourceId}
- What it does: Get information about a specific source
- Expected request: Path parameter:
sourceId(long) - e.g.,1234567890 - Expected response: JSON SourceDataClass object (HTTP 200) or HTTP 404 (Not Found)
GET /api/v1/source/{sourceId}/popular/{pageNum}
- What it does: Get popular manga from a source
- Expected request: Path parameters:
sourceId(long),pageNum(int) - Expected response: JSON PagedMangaListDataClass object (HTTP 200)
Response JSON Example:
{
"mangaList": [
{
"id": 1,
"sourceId": "1234567890",
"url": "/manga/12345",
"title": "One Piece",
"thumbnailUrl": "https://example.com/cover.jpg",
"thumbnailUrlLastFetched": 1699999999,
"initialized": true,
"artist": "Eiichiro Oda",
"author": "Eiichiro Oda",
"description": "Monkey D. Luffy sets off on an adventure...",
"genre": ["Action", "Adventure", "Comedy"],
"status": "ONGOING",
"inLibrary": true,
"inLibraryAt": 1699999999,
"source": null,
"meta": {},
"realUrl": "https://mangadex.org/manga/12345",
"lastFetchedAt": 1699999999,
"chaptersLastFetchedAt": 1699999999,
"updateStrategy": "ALWAYS_UPDATE",
"freshData": false,
"unreadCount": 100,
"downloadCount": 0,
"chapterCount": 1000,
"lastReadAt": null,
"lastChapterRead": null,
"age": 0,
"chaptersAge": 0,
"trackers": null
}
],
"hasNextPage": true
}
GET /api/v1/source/{sourceId}/latest/{pageNum}
- What it does: Get latest manga from a source
- Expected request: Path parameters:
sourceId(long),pageNum(int) - Expected response: JSON PagedMangaListDataClass object (HTTP 200)
GET /api/v1/source/{sourceId}/preferences
- What it does: Get source preferences/settings
- Expected request: Path parameter:
sourceId(long) - Expected response: JSON array of preference objects (HTTP 200)
Response JSON Example:
[
{
"type": "EditTextPreference",
"props": {
"key": "username",
"title": "Username",
"summary": "",
"text": "",
"default": ""
}
},
{
"type": "SwitchPreferenceCompat",
"props": {
"key": "hentai",
"title": "Show Hentai",
"summary": "Show mature content",
"checked": false
}
}
]
POST /api/v1/source/{sourceId}/preferences
- What it does: Set a source preference
- Expected request: Path parameter:
sourceId(long), body: SourcePreferenceChange JSON object
Request JSON Example:
{
"position": 0,
"value": "myusername"
}
- Expected response: HTTP 200 (OK)
GET /api/v1/source/{sourceId}/filters
- What it does: Get source filters
- Expected request: Path parameter:
sourceId(long), optional query param:reset(boolean) - Expected response: JSON array of FilterObject objects (HTTP 200)
Response JSON Example:
[
{
"type": "Header",
"filter": {
"name": "Content"
}
},
{
"type": "Select",
"filter": {
"name": "Genre",
"state": 0,
"values": ["All", "Action", "Adventure", "Comedy"]
}
},
{
"type": "Text",
"filter": {
"name": "Year",
"state": ""
}
},
{
"type": "CheckBox",
"filter": {
"name": "Completed",
"state": false
}
}
]
POST /api/v1/source/{sourceId}/filters
- What it does: Set source filters
- Expected request: Path parameter:
sourceId(long), body: FilterChange object or array of FilterChange objects
Request JSON Example (Single filter):
{
"position": 1,
"state": "2"
}
Request JSON Example (Multiple filters):
[
{ "position": 1, "state": "2" },
{ "position": 2, "state": "2023" },
{ "position": 3, "state": "true" }
]
- Expected response: HTTP 200 (OK)
GET /api/v1/source/{sourceId}/search
- What it does: Search for manga in a single source
- Expected request: Path parameter:
sourceId(long), query params:searchTerm(string),pageNum(int, default: 1) - Expected response: JSON PagedMangaListDataClass object (HTTP 200)
POST /api/v1/source/{sourceId}/quick-search
- What it does: Quick search manga in a source using filters
- Expected request: Path parameter:
sourceId(long), query param:pageNum(int, default: 1), body: FilterData object
Request JSON Example:
{
"searchTerm": "One Piece",
"filter": [
{ "position": 1, "state": "0" },
{ "position": 2, "state": "" }
]
}
- Expected response: JSON PagedMangaListDataClass object (HTTP 200)
Manga Endpoints
GET /api/v1/manga/{mangaId}
- What it does: Get manga information
- Expected request: Path parameter:
mangaId(int), optional query param:onlineFetch(boolean) - Expected response: JSON MangaDataClass object (HTTP 200) or HTTP 404 (Not Found)
Response JSON Example:
{
"id": 1,
"sourceId": "1234567890",
"url": "/manga/12345",
"title": "One Piece",
"thumbnailUrl": "https://example.com/cover.jpg",
"thumbnailUrlLastFetched": 1699999999,
"initialized": true,
"artist": "Eiichiro Oda",
"author": "Eiichiro Oda",
"description": "Monkey D. Luffy sets off on an adventure...",
"genre": ["Action", "Adventure", "Comedy", "Fantasy"],
"status": "ONGOING",
"inLibrary": true,
"inLibraryAt": 1699999999,
"source": {
"id": "1234567890",
"name": "MangaDex",
"lang": "en",
"iconUrl": "/source/icon/1234567890",
"supportsLatest": true,
"isConfigurable": true,
"isNsfw": false,
"displayName": "MangaDex",
"baseUrl": "https://mangadex.org"
},
"meta": {},
"realUrl": "https://mangadex.org/manga/12345",
"lastFetchedAt": 1699999999,
"chaptersLastFetchedAt": 1699999999,
"updateStrategy": "ALWAYS_UPDATE",
"freshData": false,
"unreadCount": 100,
"downloadCount": 0,
"chapterCount": 1000,
"lastReadAt": 1699999999,
"lastChapterRead": {
"id": 100,
"url": "/chapter/12345/1",
"name": "Chapter 1: Dawn of Adventure",
"uploadDate": 1699999999,
"chapterNumber": 1.0,
"scanlator": "MangaDex",
"mangaId": 1,
"read": true,
"bookmarked": false,
"lastPageRead": 20,
"lastReadAt": 1699999999,
"index": 1,
"fetchedAt": 1699999999,
"realUrl": "https://mangadex.org/chapter/12345/1",
"downloaded": true,
"pageCount": 20,
"chapterCount": 1000,
"meta": {}
},
"age": 0,
"chaptersAge": 0,
"trackers": [
{
"trackerId": 1,
"trackerName": "MyAnimeList",
"remoteId": "12345",
"remoteUrl": "https://myanimelist.net/manga/12345",
"title": "One Piece",
"lastChapterRead": 100,
"totalChapters": 1000,
"score": 9.5,
"status": "Reading",
"startedReadingDate": null,
"finishedReadingDate": null,
"private": false
}
]
}
GET /api/v1/manga/{mangaId}/full
- What it does: Get full manga information with all data filled in
- Expected request: Path parameter:
mangaId(int), optional query param:onlineFetch(boolean) - Expected response: JSON MangaDataClass object (HTTP 200) or HTTP 404 (Not Found)
GET /api/v1/manga/{mangaId}/thumbnail
- What it does: Get manga thumbnail image
- Expected request: Path parameter:
mangaId(int) - Expected response: Image file (JPEG/PNG) with HTTP 200 or HTTP 404 (Not Found)
GET /api/v1/manga/{mangaId}/category
- What it does: Get categories assigned to a manga
- Expected request: Path parameter:
mangaId(int) - Expected response: JSON array of CategoryDataClass objects (HTTP 200)
Response JSON Example:
[
{
"id": 1,
"order": 0,
"name": "Favorites",
"default": false,
"size": 10,
"includeInUpdate": "INCLUDE",
"includeInDownload": "INCLUDE",
"meta": {}
}
]
GET /api/v1/manga/{mangaId}/category/{categoryId}
- What it does: Add manga to a category
- Expected request: Path parameters:
mangaId(int),categoryId(int) - Expected response: HTTP 200 (OK)
DELETE /api/v1/manga/{mangaId}/category/{categoryId}
- What it does: Remove manga from a category
- Expected request: Path parameters:
mangaId(int),categoryId(int) - Expected response: HTTP 200 (OK)
GET /api/v1/manga/{mangaId}/library
- What it does: Add manga to library
- Expected request: Path parameter:
mangaId(int) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
DELETE /api/v1/manga/{mangaId}/library
- What it does: Remove manga from library
- Expected request: Path parameter:
mangaId(int) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
PATCH /api/v1/manga/{mangaId}/meta
- What it does: Add/update metadata to a manga
- Expected request: Path parameter:
mangaId(int), form params:key(string),value(string) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
GET /api/v1/manga/{mangaId}/chapters
- What it does: Get manga chapter list
- Expected request: Path parameter:
mangaId(int), optional query param:onlineFetch(boolean) - Expected response: JSON array of ChapterDataClass objects (HTTP 200) or HTTP 404 (Not Found)
Response JSON Example:
[
{
"id": 100,
"url": "/chapter/12345/1000",
"name": "Chapter 1000: The Final Battle",
"uploadDate": 1699999999,
"chapterNumber": 1000.0,
"scanlator": "MangaDex",
"mangaId": 1,
"read": false,
"bookmarked": false,
"lastPageRead": 0,
"lastReadAt": 0,
"index": 1000,
"fetchedAt": 1699999999,
"realUrl": "https://mangadex.org/chapter/12345/1000",
"downloaded": false,
"pageCount": 18,
"chapterCount": 1000,
"meta": {}
},
{
"id": 99,
"url": "/chapter/12345/999",
"name": "Chapter 999: The Beginning",
"uploadDate": 1699999998,
"chapterNumber": 999.0,
"scanlator": "MangaDex",
"mangaId": 1,
"read": true,
"bookmarked": true,
"lastPageRead": 15,
"lastReadAt": 1699999999,
"index": 999,
"fetchedAt": 1699999998,
"realUrl": "https://mangadex.org/chapter/12345/999",
"downloaded": true,
"pageCount": 15,
"chapterCount": 1000,
"meta": {}
}
]
POST /api/v1/manga/{mangaId}/chapter/batch
- What it does: Batch update chapters (mark as read, bookmark, etc.)
- Expected request: Path parameter:
mangaId(int), body: MangaChapterBatchEditInput object
Request JSON Example (Mark as read and bookmark):
{
"chapterIds": [100, 101, 102],
"chapterIndexes": null,
"change": {
"isRead": true,
"isBookmarked": true,
"lastPageRead": null,
"delete": null
}
}
Request JSON Example (Mark previous as read):
{
"chapterIds": [100],
"chapterIndexes": null,
"change": {
"isRead": null,
"isBookmarked": null,
"lastPageRead": null,
"delete": null,
"markPrevRead": true
}
}
Request JSON Example (Delete downloaded chapters):
{
"chapterIds": [100, 101],
"change": {
"isRead": null,
"isBookmarked": null,
"lastPageRead": null,
"delete": true
}
}
- Expected response: HTTP 200 (OK)
GET /api/v1/manga/{mangaId}/chapter/{chapterIndex}
- What it does: Get a specific chapter with pages
- Expected request: Path parameters:
mangaId(int),chapterIndex(int) - Expected response: JSON ChapterDataClass object (HTTP 200) or HTTP 404 (Not Found)
PATCH /api/v1/manga/{mangaId}/chapter/{chapterIndex}
- What it does: Modify chapter (read status, bookmark, etc.)
- Expected request: Path parameters:
mangaId(int),chapterIndex(int), form params:read(boolean, optional),bookmarked(boolean, optional),markPrevRead(boolean, optional),lastPageRead(int, optional)
Form Data Example:
read=true
bookmarked=false
lastPageRead=5
markPrevRead=true
- Expected response: HTTP 200 (OK)
PUT /api/v1/manga/{mangaId}/chapter/{chapterIndex}
- What it does: Modify chapter (same as PATCH)
- Expected request: Same as PATCH
- Expected response: HTTP 200 (OK)
DELETE /api/v1/manga/{mangaId}/chapter/{chapterIndex}
- What it does: Delete downloaded chapter files
- Expected request: Path parameters:
mangaId(int),chapterIndex(int) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
PATCH /api/v1/manga/{mangaId}/chapter/{chapterIndex}/meta
- What it does: Add metadata to a chapter
- Expected request: Path parameters:
mangaId(int),chapterIndex(int), form params:key(string),value(string) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
GET /api/v1/manga/{mangaId}/chapter/{chapterIndex}/page/{index}
- What it does: Get a chapter page image
- Expected request: Path parameters:
mangaId(int),chapterIndex(int),index(int), optional query params:updateProgress(boolean),format(string),opds(boolean) - Expected response: Image file with HTTP 200 or HTTP 404 (Not Found)
Chapter Endpoints
POST /api/v1/chapter/batch
- What it does: Batch update chapters across any manga
- Expected request: Body: ChapterBatchEditInput object
Request JSON Example:
{
"chapterIds": [100, 101, 102, 200, 201],
"change": {
"isRead": true,
"isBookmarked": false,
"lastPageRead": null,
"delete": null
}
}
- Expected response: HTTP 200 (OK)
GET /api/v1/chapter/{chapterId}/download
- What it does: Download chapter as CBZ file
- Expected request: Path parameter:
chapterId(int), optional query param:markAsRead(boolean) - Expected response: CBZ file stream with HTTP 200 or HTTP 404 (Not Found)
Response Headers:
Content-Type: application/vnd.comicbook+zip
Content-Disposition: attachment; filename="One Piece - Chapter 1000.cbz"
Content-Length: 1234567
HEAD /api/v1/chapter/{chapterId}/download
- What it does: Get CBZ file metadata (HEAD request)
- Expected request: Path parameter:
chapterId(int) - Expected response: HTTP headers with file info, or HTTP 404 (Not Found)
Category Endpoints
GET /api/v1/category
- What it does: Get list of all categories
- Expected request: No parameters required
- Expected response: JSON array of CategoryDataClass objects (HTTP 200)
Response JSON Example:
[
{
"id": 1,
"order": 0,
"name": "Favorites",
"default": false,
"size": 10,
"includeInUpdate": "INCLUDE",
"includeInDownload": "INCLUDE",
"meta": {}
},
{
"id": 2,
"order": 1,
"name": "Reading",
"default": false,
"size": 5,
"includeInUpdate": "INCLUDE",
"includeInDownload": "EXCLUDE",
"meta": {}
},
{
"id": 3,
"order": 2,
"name": "Default",
"default": true,
"size": 100,
"includeInUpdate": "INCLUDE",
"includeInDownload": "INCLUDE",
"meta": {}
}
]
POST /api/v1/category
- What it does: Create a new category
- Expected request: Form param:
name(string)
Form Data Example:
name=My Category
- Expected response: HTTP 200 (OK) or HTTP 400 (Bad Request)
PATCH /api/v1/category/reorder
- What it does: Reorder categories
- Expected request: Form params:
from(int),to(int)
Form Data Example:
from=0
to=2
- Expected response: HTTP 200 (OK)
GET /api/v1/category/{categoryId}
- What it does: Get manga in a category
- Expected request: Path parameter:
categoryId(int) - Expected response: JSON array of MangaDataClass objects (HTTP 200)
PATCH /api/v1/category/{categoryId}
- What it does: Modify a category
- Expected request: Path parameter:
categoryId(int), optional form params:name(string),default(boolean),includeInUpdate(int),includeInDownload(int)
Form Data Example:
name=Updated Name
default=false
includeInUpdate=1
includeInDownload=0
- Expected response: HTTP 200 (OK)
DELETE /api/v1/category/{categoryId}
- What it does: Delete a category
- Expected request: Path parameter:
categoryId(int) - Expected response: HTTP 200 (OK)
PATCH /api/v1/category/{categoryId}/meta
- What it does: Add metadata to a category
- Expected request: Path parameter:
categoryId(int), form params:key(string),value(string) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
Backup Endpoints
POST /api/v1/backup/import
- What it does: Restore a backup from request body
- Expected request: Body: Tachiyomi protobuf backup data (binary)
- Expected response: HTTP 200 (OK)
POST /api/v1/backup/import/file
- What it does: Restore a backup from file upload
- Expected request: Multipart form data with file named "backup.proto.gz"
- Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
POST /api/v1/backup/validate
- What it does: Validate a backup from request body
- Expected request: Body: Tachiyomi protobuf backup data (binary)
- Expected response: JSON ValidationResult object (HTTP 200)
Response JSON Example:
{
"missingSources": ["com.source.example"],
"missingTrackers": ["myanimelist"],
"isValid": false
}
POST /api/v1/backup/validate/file
- What it does: Validate a backup from file upload
- Expected request: Multipart form data with file named "backup.proto.gz"
- Expected response: JSON ValidationResult object (HTTP 200)
GET /api/v1/backup/export
- What it does: Create a backup (returns as body)
- Expected request: No parameters required
- Expected response: Binary stream (protobuf) with HTTP 200
Response Headers:
Content-Type: application/octet-stream
GET /api/v1/backup/export/file
- What it does: Create a backup (returns as file download)
- Expected request: No parameters required
- Expected response: Binary stream (protobuf) as file download with HTTP 200
Response Headers:
Content-Type: application/octet-stream
Content-Disposition: attachment; filename="suwayomi_backup_20240101.proto.gz"
Download Endpoints
GET /api/v1/downloads/start
- What it does: Start the downloader
- Expected request: No parameters required
- Expected response: HTTP 200 (OK)
GET /api/v1/downloads/stop
- What it does: Stop the downloader
- Expected request: No parameters required
- Expected response: HTTP 200 (OK)
GET /api/v1/downloads/clear
- What it does: Clear the download queue
- Expected request: No parameters required
- Expected response: HTTP 200 (OK)
GET /api/v1/download/{mangaId}/chapter/{chapterIndex}
- What it does: Queue a chapter for download
- Expected request: Path parameters:
mangaId(int),chapterIndex(int) - Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
DELETE /api/v1/download/{mangaId}/chapter/{chapterIndex}
- What it does: Remove a chapter from download queue
- Expected request: Path parameters:
mangaId(int),chapterIndex(int) - Expected response: HTTP 200 (OK)
PATCH /api/v1/download/{mangaId}/chapter/{chapterIndex}/reorder/{to}
- What it does: Reorder a chapter in download queue
- Expected request: Path parameters:
mangaId(int),chapterIndex(int),to(int) - Expected response: HTTP 200 (OK)
POST /api/v1/download/batch
- What it does: Queue multiple chapters for download
- Expected request: Body: EnqueueInput object
Request JSON Example:
{
"chapterIds": [100, 101, 102, 103, 104]
}
- Expected response: HTTP 200 (OK)
DELETE /api/v1/download/batch
- What it does: Remove multiple chapters from download queue
- Expected request: Body: EnqueueInput object
Request JSON Example:
{
"chapterIds": [100, 101, 102]
}
- Expected response: HTTP 200 (OK)
Update Endpoints
GET /api/v1/update/recentChapters/{pageNum}
- What it does: Get recently updated chapters
- Expected request: Path parameter:
pageNum(int) - Expected response: JSON PagedMangaChapterListDataClass object (HTTP 200)
Response JSON Example:
{
"mangaList": [
{
"id": 1,
"mangaId": 1,
"mangaTitle": "One Piece",
"mangaThumbnail": "https://example.com/cover.jpg",
"chapters": [
{
"id": 100,
"url": "/chapter/1/100",
"name": "Chapter 100",
"uploadDate": 1699999999,
"chapterNumber": 100.0,
"scanlator": "MangaDex",
"read": false,
"bookmarked": false,
"lastPageRead": 0,
"lastReadAt": 0,
"index": 100,
"fetchedAt": 1699999999,
"downloaded": false
}
]
}
],
"hasNextPage": true
}
POST /api/v1/update/fetch
- What it does: Start library update (optionally for specific category)
- Expected request: Optional form param:
categoryId(int)
Form Data Examples:
(Updates entire library)
or
categoryId=1
- Expected response: HTTP 200 (OK) or HTTP 400 (Bad Request)
POST /api/v1/update/reset
- What it does: Stop and reset the updater
- Expected request: No parameters required
- Expected response: HTTP 200 (OK)
GET /api/v1/update/summary
- What it does: Get updater status summary
- Expected request: No parameters required
- Expected response: JSON UpdateStatus object (HTTP 200)
Response JSON Example:
{
"status": "Running",
"progress": {
"current": 5,
"total": 100
},
"pending": 0,
"running": true,
"mangaDone": 5,
"mangaTotal": 100,
"chapterDone": 50,
"chapterAdded": 10
}
Track Endpoints
GET /api/v1/track/list
- What it does: List all supported trackers
- Expected request: No parameters required
- Expected response: JSON array of TrackerDataClass objects (HTTP 200)
Response JSON Example:
[
{
"id": 1,
"name": "MyAnimeList",
"icon": "/track/thumbnail/1",
"isLogin": false,
"authUrl": "https://myanimelist.net/api/v2/oauth/authorize"
},
{
"id": 2,
"name": "AniList",
"icon": "/track/thumbnail/2",
"isLogin": true,
"authUrl": "https://anilist.co/api/v2/oauth/authorize"
}
]
POST /api/v1/track/login
- What it does: Login to a tracker
- Expected request: Body: LoginInput object
Request JSON Example:
{
"trackerId": 1,
"callbackUrl": "suwayomi://auth/myanimelist",
"username": "myuser",
"password": "mypassword"
}
- Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
POST /api/v1/track/logout
- What it does: Logout from a tracker
- Expected request: Body: LogoutInput object
Request JSON Example:
{
"trackerId": 1
}
- Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
POST /api/v1/track/search
- What it does: Search for manga on a tracker
- Expected request: Body: SearchInput object
Request JSON Example:
{
"trackerId": 1,
"title": "One Piece"
}
- Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
Response JSON Example:
[
{
"trackerId": 1,
"remoteId": "12345",
"remoteUrl": "https://myanimelist.net/manga/12345",
"title": "One Piece",
"coverUrl": "https://example.com/cover.jpg",
"summary": "A story about pirates...",
"match": 95
}
]
POST /api/v1/track/bind
- What it does: Bind a manga to a track record
- Expected request: Query params:
mangaId(int),trackerId(int),remoteId(string),private(boolean)
Request URL Example:
/api/v1/track/bind?mangaId=1&trackerId=1&remoteId=12345&private=false
- Expected response: HTTP 200 (OK)
POST /api/v1/track/update
- What it does: Update track record with tracker
- Expected request: Body: UpdateInput object
Request JSON Example (Update reading progress):
{
"recordId": 1,
"status": 1,
"lastChapterRead": 100,
"scoreString": "9.5",
"startDate": null,
"finishDate": null,
"private": false
}
Request JSON Example (Unbind from tracker):
{
"recordId": 1,
"unbind": true
}
Status values:
-
1 = Reading
-
2 = Completed
-
3 = On Hold
-
4 = Dropped
-
6 = Plan to Read
-
Expected response: HTTP 200 (OK)
GET /api/v1/track/{trackerId}/thumbnail
- What it does: Get tracker thumbnail image
- Expected request: Path parameter:
trackerId(int) - Expected response: Image file with HTTP 200 or HTTP 404 (Not Found)
Global Meta Endpoints
GET /api/v1/meta
- What it does: Get all global metadata
- Expected request: No parameters required
- Expected response: HTTP 200 (OK) with JSON key-value pairs
Response JSON Example:
{
"customKey": "customValue",
"lastSync": "1234567890"
}
PATCH /api/v1/meta
- What it does: Add/update global metadata
- Expected request: Form params:
key(string),value(string)
Form Data Example:
key=lastSync
value=1234567890
- Expected response: HTTP 200 (OK) or HTTP 404 (Not Found)
Settings Endpoints
GET /api/v1/settings/about
- What it does: Get application information
- Expected request: No parameters required
- Expected response: JSON AboutDataClass object (HTTP 200)
Response JSON Example:
{
"name": "Suwayomi-Server",
"version": "0.7.0",
"revision": "7a1b2c3",
"buildType": "release",
"buildTime": 1704067200,
"github": "https://github.com/Suwayomi/Suwayomi-Server",
"discord": "https://discord.gg/Suwayomi"
}
GET /api/v1/settings/check-update
- What it does: Check for application updates
- Expected request: No parameters required
- Expected response: JSON array of UpdateDataClass objects (HTTP 200)
Response JSON Example:
[
{
"name": "0.8.0",
"tagName": "v0.8.0",
"body": "## Bug fixes\n- Fixed bug #123\n- Improved performance",
"htmlUrl": "https://github.com/Suwayomi/Suwayomi-Server/releases/tag/v0.8.0",
"prerelease": false
}
]
WebView Endpoints
GET /api/v1/webview
- What it does: Open webview interface
- Expected request: Optional query param:
lang(string)
Request URL Example:
/api/v1/webview?lang=en
- Expected response: HTML page (HTTP 200)
WebSocket Endpoints
The server provides WebSocket connections for real-time communication and updates.
Note: Actions like starting/stopping downloads or updates are done via HTTP endpoints (GET /api/v1/downloads/start, GET /api/v1/downloads/stop, POST /api/v1/update/fetch, etc.), not through WebSocket messages. WebSocket connections are primarily for receiving real-time status updates.
WS /api/v1/downloads
- What it does: Real-time download queue status updates
- Expected request: WebSocket connection with authentication
Messages You Can Send to Server:
Request current download status:
STATUS
- Expected Response from Server:
{
"status": "Started",
"queue": [
{
"mangaId": 1,
"chapterId": 100,
"chapterIndex": 100,
"mangaTitle": "One Piece",
"chapterTitle": "Chapter 100",
"state": "DOWNLOADING",
"progress": 50,
"tries": 0,
"downloadSpeed": 1024000,
"errorMessage": null
}
]
}
State values: Queued, Downloading, Completed, Error
Invalid command response:
Invalid command.
Supported commands are:
- STATUS
sends the current download status
Messages Received from Server (Automatic Updates):
The server automatically sends status updates when:
- A download starts/completes/fails
- Queue changes (add/remove/reorder)
Example update:
{
"status": "Started",
"queue": [
{
"mangaId": 1,
"chapterId": 100,
"chapterIndex": 100,
"mangaTitle": "One Piece",
"chapterTitle": "Chapter 100",
"state": "Completed",
"progress": 100,
"tries": 0,
"downloadSpeed": 0,
"errorMessage": null
}
],
"downloads": [
{
"downloadQueueItem": {
"mangaId": 1,
"chapterId": 101,
"chapterIndex": 101,
"mangaTitle": "One Piece",
"chapterTitle": "Chapter 101",
"state": "Downloading",
"progress": 25,
"tries": 0
},
"downloadSpeed": 1024000
}
]
}
WS /api/v1/update
- What it does: Real-time library update progress
- Expected request: WebSocket connection with authentication
Messages You Can Send to Server:
Request current update status:
STATUS
- Expected Response from Server:
{
"status": "Running",
"pending": 0,
"running": true,
"mangaDone": 5,
"mangaTotal": 100,
"chapterDone": 50,
"chapterAdded": 10,
"progress": {
"current": 5,
"total": 100
},
"errors": []
}
Status values: Idle, Running, Completed, Stopped
Invalid command response:
Invalid command.
Supported commands are:
- STATUS
sends the current update status
Messages Received from Server (Automatic Updates):
The server automatically sends status updates during library updates.
Example update:
{
"status": "Running",
"pending": 95,
"running": true,
"mangaDone": 5,
"mangaTotal": 100,
"chapterDone": 50,
"chapterAdded": 10,
"progress": {
"current": 5,
"total": 100
},
"errors": []
}
WS /api/v1/webview
- What it does: Real-time webview communication for embedded browser functionality
- Expected request: WebSocket connection with authentication
Messages You Can Send to Server:
Load a URL in the webview:
{
"type": "loadUrl",
"url": "https://example.com",
"width": 1920,
"height": 1080
}
- Expected Response: None (webview loads the URL)
Resize the webview:
{
"type": "resize",
"width": 800,
"height": 600
}
- Expected Response: None
Send a JavaScript event:
{
"type": "event",
"eventType": "click",
"clickX": 100.5,
"clickY": 200.75,
"button": 0,
"ctrlKey": false,
"shiftKey": false,
"altKey": false,
"metaKey": false
}
- Expected Response: None (event is sent to the webview)
Keyboard event:
{
"type": "event",
"eventType": "keydown",
"key": "Enter",
"code": "Enter",
"ctrlKey": true
}
- Expected Response: None
Scroll event:
{
"type": "event",
"eventType": "wheel",
"deltaY": -100,
"clientX": 500,
"clientY": 500
}
- Expected Response: None
Paste text to webview:
{
"type": "paste",
"data": "pasted text content"
}
- Expected Response: None
Copy from webview:
{
"type": "copy"
}
- Expected Response: None
Ping to check connection:
{
"type": "ping"
}
- Expected Response from Server:
{
"type": "pong"
}
Messages Received from Server:
The server sends various responses based on webview interactions:
Pong response:
{
"type": "pong"
}
JavaScript console output (example):
{
"type": "console",
"level": "log",
"message": "Page loaded successfully"
}
Page load events:
{
"type": "loadStart",
"url": "https://example.com"
}
{
"type": "loadFinish",
"url": "https://example.com",
"httpStatusCode": 200
}
Error events:
{
"type": "error",
"description": "Failed to load resource",
"url": "https://example.com/broken-link"
}
GraphQL Endpoint
Base URL: http://localhost:4567/api/graphql
The server also provides a GraphQL API for more flexible queries and subscriptions. See the GraphQL schema for available queries, mutations, and subscriptions.
OPDS Endpoints
The OPDS API provides catalog feeds for integration with OPDS-compatible readers.
Base URL: http://localhost:4567/api/opds/v1.2/
GET /api/opds/v1.2/opds/v1.2
- What it does: OPDS Catalog Root Feed (Navigation)
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
Response XML Example:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:opds="http://opds-spec.org/2010/catalog">
<title>Suwayomi</title>
<link rel="start" href="/api/opds/v1.2/opds/v1.2" type="application/atom+xml"/>
<link rel="self" href="/api/opds/v1.2/opds/v1.2" type="application/atom+xml"/>
<entry>
<title>Library</title>
<link href="/api/opds/v1.2/library/series" type="application/atom+xml;profile=opds-catalog"/>
<content type="text">Your manga library</content>
</entry>
<entry>
<title>Explore</title>
<link href="/api/opds/v1.2/sources" type="application/atom+xml;profile=opds-catalog"/>
<content type="text">Browse sources</content>
</entry>
</feed>
GET /api/opds/v1.2/search
- What it does: OPDS Search Description Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/explore
- What it does: Explore Sources Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/history
- What it does: Reading History Acquisition Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library-updates
- What it does: Library Updates Acquisition Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/series
- What it does: All Series in Library / Search Results Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/sources
- What it does: Library Sources Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/source/{sourceId}
- What it does: Library Source-Specific Series Acquisition Feed
- Expected request: Path parameter:
sourceId(long) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/categories
- What it does: Library Categories Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/genres
- What it does: Library Genres Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/statuses
- What it does: Library Status Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/library/languages
- What it does: Library Content Languages Navigation Feed
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/sources
- What it does: All Sources Navigation Feed (Explore)
- Expected request: No parameters required
- Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/source/{sourceId}
- What it does: Source-Specific Series Acquisition Feed (Explore)
- Expected request: Path parameter:
sourceId(long) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/series/{seriesId}/chapters
- What it does: Series Chapters Acquisition Feed
- Expected request: Path parameter:
seriesId(int) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/series/{seriesId}/chapter/{chapterIndex}/metadata
- What it does: Chapter Metadata Acquisition Feed
- Expected request: Path parameters:
seriesId(int),chapterIndex(int) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/category/{categoryId}
- What it does: Category-Specific Series Acquisition Feed
- Expected request: Path parameter:
categoryId(int) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/genre/{genre}
- What it does: Genre-Specific Series Acquisition Feed
- Expected request: Path parameter:
genre(string) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/status/{statusId}
- What it does: Status-Specific Series Acquisition Feed
- Expected request: Path parameter:
statusId(int) - Expected response: XML OPDS feed (HTTP 200)
GET /api/opds/v1.2/language/{langCode}
- What it does: Language-Specific Series Acquisition Feed
- Expected request: Path parameter:
langCode(string) - Expected response: XML OPDS feed (HTTP 200)
Notes
- The server runs on port 4567 by default
- All JSON responses use UTF-8 encoding
- File uploads use multipart/form-data format
- WebSocket endpoints provide real-time updates for downloads, updates, and webview
- WebSocket messages are JSON formatted (except STATUS command which is plain text)
- Image responses include caching headers with 1-day max-age for thumbnails and pages
- OPDS feeds use Atom XML format for catalog navigation and acquisition
- Actions like start/stop for downloads and updates are done via HTTP endpoints, not WebSocket
- WebSocket endpoints only support "STATUS" command to query current status
- See Authentication section for details on how to authenticate with the API