Every route below is GET, answers JSON, and needs a key (see Get a key). The OpenAPI document describes the same routes, generated from the same table the server enforces (x-rt-routes), and is the place for every field of every answer: the answers here are trimmed to a few fields.
| Route | Path | Units | Freshness | Permission |
|---|---|---|---|---|
| Search and browse novels | GET /api/v1/novels/ |
5 | live | read:catalog |
| Genres, fandoms and tags | GET /api/v1/novels/hub |
5 | up to 1 hour | read:catalog |
| Popular | GET /api/v1/novels/popular/{time_range} |
5 | up to 10 minutes | read:catalog |
| A novel | GET /api/v1/novels/{novel_id} |
1 | live | read:catalog |
| A novel's chapter list | GET /api/v1/novels/{novel_id}/chapters/page |
5 | up to 1 minute | read:catalog |
| A novel's glossary | GET /api/v1/novels/{novel_id}/entities |
5 | live | read:glossary |
| Search a glossary | GET /api/v1/novels/{novel_id}/entities/search |
5 | live | read:glossary |
| Shared glossary terms | GET /api/v1/novels/{novel_id}/general-entities |
5 | live | read:glossary |
| Recaps | GET /api/v1/novels/{novel_id}/recaps |
1 | live | read:recaps |
| One arc's recap | GET /api/v1/novels/{novel_id}/recaps/arcs/{arc_index} |
1 | live | read:recaps |
| Your library | GET /api/v1/user-novels/bookmarks |
5 | live | read:library |
| Your place in a novel | GET /api/v1/user-novels/{novel_id} |
1 | live | read:library |
| Your notifications | GET /api/v1/user-novels/notifications |
5 | live | read:library |
| Your limits today | GET /api/v1/limits/me |
1 | live | read:library |
- Units is what one request costs against your key's limits (Limits): a record costs 1, a page of a list 5.
- Freshness is how old the server's own answer can be. Answers to a key are never cached at the edge.
- Permission matters only to an OAuth app's token (Get a key): a personal key holds all four.
- The four routes about you (your library, your place, your notifications, your limits) answer only for the key's own account.
- Every error below that is common to all routes is explained in Errors.
The examples use a key in the environment variable RT_KEY.
Search and browse novels#
GET /api/v1/novels/
Search and browse novels: title or author text, genre, tags, fandom, status and sort, 20 a page.
Cost 5 units; freshness live; scope read:catalog.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
title |
query | string | No | Search in original or translated title (at most 100 characters), or paste a novel URL for exact match | |
author |
query | string | No | Search in original or translated author | |
category |
query | string | No | Filter by original or translated category | |
status |
query | string | No | Filter by original or translated status | |
exclude_genres[] |
query | array | No | Genres (the category values) to hide. Case-insensitive; also accepted as comma-separated exclude_genres=a,b. A novel in any of them is dropped, even when category names it. Novels with no genre stay. Max 20. |
|
fandom |
query | string | No | Legacy single-fandom filter; folded into include_fandoms[]. Kept for old links and saved subscriptions. | |
include_fandoms[] |
query | array | No | Fandoms to include (exact stored names, case-insensitive). Novels must have at least one unless include_all_fandoms is true. Max 20. | |
include_all_fandoms |
query | boolean | No | false | If true, novels must have ALL specified include_fandoms. |
exclude_fandoms[] |
query | array | No | Fandoms to exclude. Novels must NOT have any of these. Max 20. | |
allow_crossovers |
query | boolean | No | true | With include_fandoms[]: false keeps only novels carrying no fandom outside the include list (no crossovers). No effect without include_fandoms. |
fanfic |
query | boolean | No | true: Fan-Fiction only; false: everything except Fan-Fiction (no category included); absent: no filter. | |
protagonist_gender |
query | string | No | Filter by protagonist gender: male, female | |
include_tags[] |
query | array | No | Filter by tags that must be included. Novels must have at least one of these tags. | |
include_all_tags |
query | boolean | No | false | If true, novels must have ALL specified include_tags. |
exclude_tags[] |
query | array | No | Filter by tags that must be excluded. Novels must NOT have any of these tags. | |
created_within |
query | string | No | Filter novels created within this duration (e.g., 1d, 1w, 1m, 3m, 6m, 1y) | |
created_older_than |
query | string | No | Filter novels created older than this duration (e.g., 1m, 6m, 1y, 2y) | |
updated_within |
query | string | No | Filter novels with new chapters added within this duration (e.g., 1d, 1w, 1m, 3m, 6m, 1y) | |
updated_older_than |
query | string | No | Filter novels with no new chapters added for longer than this duration (e.g., 1m, 6m, 1y, 2y) | |
min_word_count |
query | string | No | Minimum word count (e.g., 50k, 100k, 500k, 1m) | |
max_word_count |
query | string | No | Maximum word count (e.g., 100k, 500k, 1m, 2m) | |
sort_by |
query | string | No | Sort field: views, last_added, word_count, chapter_count, reader_count, rating_count, score (rating, best first), newest, relevance. Absent: relevance while a title or author search is active, else last_added. | |
order |
query | string | No | "desc" | Sort order: asc or desc |
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 50 | No | 20 | Number of items to return (max 50) |
view |
query | string (full, card) | No | "full" | full (default): every field. card: the lean row a list draws (9 metadata fields, at most 8 tags, a short plain English synopsis). Recommended. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/?title=sword&limit=2'
Trimmed answer:
{
"items": [
{
"id": 1234,
"slug": "sword-god",
"translated_title": "Sword God",
"original_title": "剑神",
"translated_author": "Ink Pavilion",
"translated_category": "Xianxia",
"status": "Ongoing"
}
],
"total": 87
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
Genres, fandoms and tags#
GET /api/v1/novels/hub
Every genre, fandom and tag with its number of novels: the values novels_search filters on.
Cost 5 units; freshness up to 1 hour; scope read:catalog.
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/hub'
Trimmed answer:
{
"totals": {
"works": 41200,
"genres": 24,
"fandoms": 310,
"tags": 1450
},
"genres": [
{
"name": "Xianxia",
"count": 5120
}
],
"fandoms": [
{
"name": "Naruto",
"count": 412
}
],
"tags": [
{
"name": "Cultivation",
"count": 6011
}
]
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
Popular#
GET /api/v1/novels/popular/{time_range}
The most read novels for daily, weekly, monthly or all time, with each novel's movement on the list.
Cost 5 units; freshness up to 10 minutes; scope read:catalog.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
time_range |
path | daily, weekly, monthly, all_time |
Yes | The window readers are counted over | |
include_fanfiction |
query | string | No | "true" | true: ONLY Fan-Fiction; false: every novel EXCEPT Fan-Fiction; all: no category filter |
system |
query | boolean | No | false | If false (default), exclude novels by default system user. If true, show only novels by default system user |
protagonist_gender |
query | string | No | male, female | |
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 50 | No | 20 | |
view |
query | string (full, card) | No | "full" | full (default): PopularNovelResponse rows. card: PaginatedPopularNovelCardResponse, the fields a list row draws (see GET /novels/). |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/popular/weekly?include_fanfiction=all&limit=2'
Trimmed answer:
{
"items": [
{
"id": 1234,
"translated_title": "Sword God",
"novel_metadata": {
"reader_count": "8.1K"
},
"list_move": 3,
"list_new": false
}
],
"total": 200
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
A novel#
GET /api/v1/novels/{novel_id}
One novel: titles, author, synopsis, genre, tags, status, chapter count, and your shelf status and place.
Cost 1 unit; freshness live; scope read:catalog.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
basic |
query | boolean | No | false | If true, return only basic novel info (id, titles) |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234'
Trimmed answer:
{
"id": 1234,
"translated_title": "Sword God",
"original_title": "剑神",
"translated_author": "Ink Pavilion",
"translated_category": "Xianxia",
"novel_metadata": {
"chapter_count": 1520,
"word_count": "4.6M"
},
"user_bookmarked": true,
"user_reading_status": "READING",
"current_chapter_sequence": 37
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
A novel's chapter list#
GET /api/v1/novels/{novel_id}/chapters/page
One page of a novel's chapter list: numbers and titles, never chapter text. Search by title or number.
Cost 5 units; freshness up to 1 minute; scope read:catalog.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 200 | No | 100 | |
search |
query | string | No | Case-insensitive literal match on the chapter title (translated, else original) or on the chapter number's digits. | |
order |
query | string (asc, desc) | No | "asc" | |
around |
query | integer | No | Serve the page that contains this sequence number (or where it would sit) instead of skip. Used to open the list on the reader's current chapter. |
|
indexed |
query | boolean | No | true | Set false to skip the summary-embedding lookup; indexed then comes back null instead of a boolean. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/chapters/page?skip=0&limit=2'
Trimmed answer:
{
"items": [
{
"id": 99001,
"sequence_number": 1,
"translated_title": "The Broken Sword",
"original_title": "断剑",
"word_count": "3.1K"
}
],
"total": 1520,
"skip": 0,
"chapter_count": 1520,
"current_sequence": 37
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
A novel's glossary#
GET /api/v1/novels/{novel_id}/entities
A page of the novel's glossary: characters, places and terms with their English names.
Cost 5 units; freshness live; scope read:glossary.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 100 | No | 100 | |
only_user_translated |
query | boolean | No | false | Return only entities the current user has a custom translation for. Requires auth. |
source_type |
query | string | No | Filter entities by how they were created: 'ai' or 'user'. Omit for all. | |
kind |
query | string | No | Filter by classifier kind (character, place, ... junk). Omit for all; unclassified rows only appear unfiltered. | |
sort |
query | string | No | occurrences (default), chapters, name, kind, newest | |
order |
query | string | No | asc, desc. Default: desc for occurrences/chapters/newest, asc for name/kind. | |
status |
query | string | No | active, hidden. Omit for all. | |
include_aliases |
query | boolean | No | false | Also list same-named alias rows on their own. Default: folded under their canonical row (its alias_entities). |
scope |
query | string | No | novel = the novel's own entries only; all (default) also lists the general entities stored on this novel. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/entities?limit=2'
Trimmed answer:
{
"items": [
{
"id": 501,
"original_name": "林凡",
"translated_name": "Lin Fan",
"kind": "character",
"total_occurrences": 4120
}
],
"total": 340
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
Search a glossary#
GET /api/v1/novels/{novel_id}/entities/search
Search the novel's glossary by Chinese or English name.
Cost 5 units; freshness live; scope read:glossary.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
query |
query | string max len 200 | Yes | Search query for entity names | |
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 100 | No | 100 | |
only_user_translated |
query | boolean | No | false | Return only entities the current user has a custom translation for. Requires auth. |
source_type |
query | string | No | ||
kind |
query | string | No | Filter by classifier kind (character, place, ... junk). Omit for all. | |
sort |
query | string | No | Same vocabulary as the list route. | |
order |
query | string | No | ||
status |
query | string | No | active, hidden. Omit for all. | |
scope |
query | string | No | Same as the list route. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/entities/search?query=Lin'
Trimmed answer:
{
"items": [
{
"id": 501,
"original_name": "林凡",
"translated_name": "Lin Fan",
"kind": "character",
"total_occurrences": 4120
}
],
"total": 1
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
Shared glossary terms#
GET /api/v1/novels/{novel_id}/general-entities
The shared glossary terms (fandom and genre-wide names) that apply to this novel.
Cost 5 units; freshness live; scope read:glossary.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 100 | No | 50 | |
search |
query | string | No | Case-insensitive substring of the original or translated name. Ignored when shorter than 2 characters, unless it holds a CJK glyph. | |
kind |
query | string | No | Filter by classifier kind. Omit for all. | |
sort |
query | string | No | occurrences (default), chapters, name, kind, newest, counted in this novel. | |
order |
query | string | No | asc, desc. Default: desc for occurrences/chapters/newest, asc for name/kind. | |
status |
query | string | No | included, excluded (the per-entity switch). Omit for both. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/general-entities?limit=2'
Trimmed answer:
{
"items": [
{
"id": 77,
"original_name": "筑基",
"translated_name": "Foundation Establishment"
}
],
"total": 52
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
Recaps#
GET /api/v1/novels/{novel_id}/recaps
The novel's volume and arc recap tree, opened at your arc; view=structure leaves out story text.
Cost 1 unit; freshness live; scope read:recaps.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
arc |
query | string | No | Arc to open (whose volume ships its full recap); anything invalid falls back to the reader's arc, else 0. It selects what is returned and never what is written. | |
view |
query | string | No | "full" | full (default): the tree with recap text. structure: the same tree with no title, preview or recap on any volume or arc (no story text, so no spoilers). |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/recaps?view=structure'
Trimmed answer:
{
"novel_id": 1234,
"total_chapters": 1200,
"arc_size": 25,
"volume_size": 100,
"current_chapter_sequence": 37,
"current_arc": 1,
"open_arc": 1,
"volumes": [
{
"index": 0,
"start_seq": 1,
"end_seq": 100,
"status": "ready"
}
]
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
One arc's recap#
GET /api/v1/novels/{novel_id}/recaps/arcs/{arc_index}
One arc's recap and its chapter summaries.
Cost 1 unit; freshness live; scope read:recaps.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes | ||
arc_index |
path | integer | Yes | ||
include_chapters |
query | boolean | No | true | False returns the arc's own recap with chapters: [] and reads no chapter summaries: the 25 summaries are ~95% of the response, and the recaps page draws only the arc's recap. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/novels/1234/recaps/arcs/1'
Trimmed answer:
{
"novel_id": 1234,
"arc": {
"index": 1,
"start_seq": 26,
"end_seq": 50,
"title": "Leaving the Village",
"recap": "Lin Fan leaves the village..."
},
"chapters": [
{
"chapter_id": 99026,
"sequence_number": 26,
"translated_title": "The Sect Gate",
"summary": "Lin Fan reaches the sect gate."
}
]
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 404 novel not found, 410 not_found_deleted / not_found_taken_down where the novel is gone, 422 for a parameter out of range.
Your library#
GET /api/v1/user-novels/bookmarks
Your library: a page of your saved novels with reading status and where you are in each.
Cost 5 units; freshness live; scope read:library.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
reading_status |
query | string | No | Filter by reading status: READING, PLAN_TO_READ, PAUSED, COMPLETED, DROPPED | |
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 50 | No | 20 | |
sort_by |
query | string | No | "last_read" | Sort by: last_read, last_updated, unread_chapters, or last_added |
continue_reading |
query | boolean | No | false | Only the rows the home page's Continue Reading shelf shows |
new_chapters |
query | boolean | No | false | Only rows with chapters added since the reader last read them |
with_total |
query | boolean | No | true | false skips the count query; total is then -1 |
novel_ids |
query | string | No | Comma-separated novel ids (at most 50): only those rows | |
q |
query | string | No | Title search: the novel's English, original or alternate titles contain it (case-insensitive, at most 100 characters; blank is no filter) | |
with_counts |
query | boolean | No | false | Add status_counts: the whole library's bookmarks per reading status |
view |
query | string (full, card) | No | "full" | full (default): unchanged. card: rows without is_bookmarked, stored_chapter_count and stored_unread_chapters, and without the stored-chapter subqueries. |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/user-novels/bookmarks?limit=2'
Trimmed answer:
{
"total": 41,
"items": [
{
"novel_id": 1234,
"translated_title": "Sword God",
"reading_status": "READING",
"current_chapter_number": 37
}
]
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
Your place in a novel#
GET /api/v1/user-novels/{novel_id}
Your library entry for one novel: status, rating and your reading position.
Cost 1 unit; freshness live; scope read:library.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
novel_id |
path | integer | Yes |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/user-novels/1234'
Trimmed answer:
{
"novel_id": 1234,
"is_bookmarked": true,
"reading_status": "READING",
"current_chapter_id": 99037,
"current_chapter_number": 37,
"last_read_at": "2026-11-01T20:14:03Z"
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
Your notifications#
GET /api/v1/user-novels/notifications
A page of your notifications: new chapters, replies and announcements.
Cost 5 units; freshness live; scope read:library.
| parameter | in | type | required | default | meaning |
|---|---|---|---|---|---|
skip |
query | integer >= 0, <= 1000000 | No | 0 | Number of items to skip |
limit |
query | integer >= 1, <= 50 | No | 20 | |
notification_type |
query | string | No | Filter by notification type (case-insensitive): SITE_UPDATE, CHAPTER_UPDATE, NOVEL_ADDITION, NOVEL_REQUEST, CONTRIBUTION, SOCIAL, PROGRESSION, GENERAL |
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/user-novels/notifications?limit=2'
Trimmed answer:
{
"total": 9,
"items": [
{
"id": 8812,
"notification_type": "CHAPTER_UPDATE",
"title": "Sword God",
"message": "3 new chapters",
"is_read": false,
"created_at": "2026-11-02T06:00:00Z"
}
]
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.
Your limits today#
GET /api/v1/limits/me
Your limits today: chapters (one ceiling for site, downloads, tools and EPUB), EPUB, read-aloud, originals, key units.
Cost 1 unit; freshness live; scope read:library.
curl -H "Authorization: Bearer $RT_KEY" \
-H "User-Agent: my-tool/1.0" \
'https://randomtranslator.com/api/v1/limits/me'
Trimmed answer:
{
"day_resets_at": "2026-11-03T00:00:00Z",
"chapters": {
"used": 212,
"limit": 1500,
"remaining": 1288
},
"epub_exports": {
"used": 1,
"limit": 10,
"remaining": 9
},
"api_units": {
"used_minute": 6,
"limit_minute": 120,
"used_day": 340,
"limit_day": 10000
},
"tts_characters": {
"used": 48210,
"limit": 1200000,
"remaining": 1151790
},
"original_views": {
"used": 0,
"limit": 1500,
"remaining": 1500
}
}
Errors: 401 invalid_key, 403 membership_required, 429 rate_limited / daily_limit, 503 api_disabled, 422 for a parameter out of range.