Save search

Give these filters a name so you can return to them later.

DaoSearch

API

A read-only JSON API over the same data as the site: books, search, catalogues, rankings and booklists from six Chinese web-novel sources. Free, with a key from your account.

What it is for

The API gives a program the same things the site shows a reader: a book and its figures, search, each source's catalogue with its filters, the ranking boards and the booklists. It is read-only JSON over GET, and it adds nothing the pages do not have.

It is meant for personal projects and tools: a Discord bot, a userscript, a reading tracker, an agent that looks a novel up. It is not a way to copy the catalogue.

Everything lives under https://daosearch.io/api/v1. A machine-readable description of every endpoint, parameter and field is at /api/v1/openapi.json (OpenAPI 3.1, no key needed), and it is generated from the same code that answers the requests.

Getting a key

Every request needs a key. Sign in, open your account page, and create one under "API keys".

  • The key is shown once, when you create it. Store it then: only a hash of it is kept, so nobody can show it to you again.
  • An account can hold 3 keys, and it has to be a day old before it can create its first.
  • "Rotate" gives a key a new secret and keeps the old one working for 24 hours, so you can switch a running tool over.
  • "Revoke" stops a key within a minute.

We keep the day a key was last used and today's count against the limits. We do not keep what a key asked for.

Authentication

Send the key in the Authorization header.

curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     -H "User-Agent: my-tool/1.0" \
     "https://daosearch.io/api/v1/books/qidian/1010868264"

A key is never accepted in the URL: a request with ?key= or ?api_key= is answered 400, because URLs end up in logs. The API cannot be called from a web page on another site either, since a key in a page is a published key. Call it from a server, a script, a browser extension or a userscript.

Limits

  • 60 requests a minute for each key. Past it the answer is 429 rate_limited, and Retry-After says how many seconds are left in the minute.
  • 5,000 units a day for each account, shared by all its keys, starting again at 00:00 UTC. Past it the answer is 429 quota_exceeded, and Retry-After is the seconds until midnight UTC.

A refused request costs nothing. Every answer carries three headers about the daily units, so a tool can pace itself without a failed call:

header meaning
RateLimit-Limit the account's units for a day
RateLimit-Remaining units left today, after this request
RateLimit-Reset seconds until the units are given back

Answers come with Cache-Control: private, max-age=300: keep what you fetch for at least five minutes. The data behind an answer is refreshed less often than that anyway (the table below says how often), so asking again sooner returns the same thing.

What each call costs

A single record costs 1 unit. A page of a listing, which is up to 50 books or lists, costs 5.

call units refreshed
GET /sources 1 every 9 hours
GET /books/{source}/{source_book_id} 1 every 6 hours
GET /{source}/rankings 1 every 30 minutes
GET /{source}/rankings/{board} 5 every 30 minutes
GET /{source}/booklists 5 every hour
GET /{source}/booklists/{list_id} 5 every hour
GET /search 1 every 6 hours
GET /{source}/genres 1 every 9 hours
GET /{source}/tags 1 every 9 hours
GET /{source}/books 5 every 15 minutes

How answers are shaped

  • A data answer is {"data": ...}. A listing adds "page". An error is {"error": {...}}. Nothing else sits at the top level.
  • A book is named by its source and its source_book_id: the id in the source's own URL, sent as text because Fanqie's are 19 digits. The sources are qidian, fanqie, jjwxc, faloo, qimao and zongheng.
  • Text in two languages is {"en": ..., "zh": ...}. en is null until it is translated. Genres and tags are named by their zh in parameters.
  • A missing fact is null, never 0 or an empty string. An empty list is [].
  • Numbers are raw (22256029, not 22.3M). Times are RFC 3339 in UTC.
  • Every object carries url, its page on DaoSearch.
  • A listing is paged with page, 50 to a page. page.last is the deepest page the view allows and page.next_url is the next request, null on the last page.
  • view=compact on a listing drops each book's cover, synopsis excerpt and the labels of its figures: about a third of the size, for a tool that only needs to choose.
  • A parameter the endpoint does not have is refused with 400, not ignored. So is a value off its list.

The six sources count different things, so a book's figures come as a metrics array, each with a key, the label the site prints, a value and the period it is counted over. GET /sources describes every key a source can send.

Sources

GET /sources is the place to start. It lists the six sources and, for each, what every metric key means, which sorts and filters its catalogue takes and on which steps, and what its booklists accept. Read the allowed values from here and do not hard-code them. It changes rarely, so cache it for a day.

A metric with on_book: true is on a book's own record. One with on_book: false appears only on catalogue rows or on a ranking board's entries, such as a board's own weekly count.

curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/sources"

One source, cut to two of its figures:

{
  "data": [
    {
      "source": "fanqie",
      "label": "Fanqie",
      "name_zh": "番茄小说",
      "site_url": "https://fanqienovel.com",
      "url": "https://daosearch.io/fanqie/library",
      "guide_url": "https://daosearch.io/blog/fanqie-reads-vs-all-time-reads",
      "has_rankings": true,
      "has_booklists": true,
      "score_scale": 10,
      "metrics": [
        {
          "key": "reads",
          "label": "Reads",
          "zh": "在读",
          "period": "current",
          "on_book": true,
          "meaning": "The read count Fanqie's app shows for the book now.",
          "sort": "reads",
          "min_param": null,
          "min_steps": null
        },
        {
          "key": "score",
          "label": "Score",
          "zh": "评分",
          "period": null,
          "on_book": true,
          "meaning": "Reader score out of 10. A third of scored books sit on a 5.8 placeholder.",
          "sort": "score",
          "min_param": "min_score",
          "min_steps": [
            7,
            8.5,
            9,
            9.5
          ]
        }
      ],
      "catalogue": {
        "sorts": [
          "reads",
          "reads_all",
          "updated",
          "added",
          "score",
          "shelves",
          "words"
        ],
        "default_sort": "reads",
        "length_steps": [
          100000,
          300000,
          1000000,
          2000000,
          3000000
        ],
        "facets": [
          {
            "param": "audience",
            "values": [
              "male",
              "female"
            ]
          }
        ]
      },
      "booklists": {
        "sorts": [
          "visits",
          "books",
          "recs",
          "active"
        ],
        "default_sort": "active",
        "min_books_steps": [
          50,
          100,
          200,
          300,
          500
        ],
        "popularity": {
          "param": "min_visits",
          "steps": [
            100000,
            1000000,
            10000000,
            30000000
          ]
        },
        "member_sorts": [
          "reads",
          "score",
          "shelves",
          "words",
          "updated"
        ],
        "min_words_steps": [
          100000,
          300000,
          1000000,
          2000000,
          3000000
        ],
        "metrics": [
          {
            "key": "visits",
            "label": "Views",
            "meaning": "Visits to the list over its life. Fanqie publishes no follower count."
          },
          {
            "key": "recommendations",
            "label": "Recs",
            "meaning": "Recommendations readers left on the list."
          }
        ]
      }
    }
  ]
}

A book

GET /books/{source}/{source_book_id} is everything the book's page shows: titles and author in both languages, the whole English synopsis, genre, tags, the source's figures, the boards it ranks on now, whether the source still carries it, the same novel on other sources, and a link to an English translation when one is known.

  • The Chinese synopsis is never sent. Titles and tags in Chinese are there because they identify the book.
  • availability.state is available, removed_at_source (the source says the book is gone) or withheld_at_source (the source has it but is not showing it now, which on JJWXC often passes). chapters_unavailable is reserved. Expect new values.
  • An id whose book is filed under another source answers 301 to that book's API URL.
  • A book DaoSearch has hidden answers 404, as its page does.
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/books/qidian/1010868264"
{
  "data": {
    "source": "qidian",
    "source_book_id": "1010868264",
    "url": "https://daosearch.io/qidian/book/1010868264/lord-of-the-mysteries",
    "source_url": "https://www.qidian.com/book/1010868264/",
    "title": {
      "en": "Lord of the Mysteries",
      "zh": "诡秘之主"
    },
    "author": {
      "en": "Cuttlefish That Loves Diving",
      "zh": "爱潜水的乌贼"
    },
    "cover_url": "https://daosearch.io/img/cover/qidian/1010868264.jpg",
    "synopsis_en": "With the rising tide of steam power and machinery, who can come close to being a Beyonder?\n\nShrouded in the fog of history and darkness, who or what is the lurking evil that murmurs into our ears?",
    "genre": {
      "en": "Fantasy",
      "zh": "玄幻"
    },
    "subgenre": {
      "en": "Otherworld Continent",
      "zh": "异世大陆"
    },
    "tags": [
      {
        "en": "Steampunk",
        "zh": "蒸汽朋克"
      },
      {
        "en": "Transmigration",
        "zh": "穿越"
      }
    ],
    "facets": [
      {
        "key": "audience",
        "label": "Audience",
        "value": "male",
        "value_label": "Male"
      }
    ],
    "status": "completed",
    "word_count": 4465200,
    "chapter_count": 1432,
    "updated_at": "2020-05-01T12:00:00Z",
    "refreshed_at": "2026-10-06T03:41:12Z",
    "metrics": [
      {
        "key": "monthly_votes",
        "label": "Votes",
        "value": 15864,
        "period": "month"
      },
      {
        "key": "recommendation_votes",
        "label": "Recs",
        "value": 10203441,
        "period": "all_time"
      },
      {
        "key": "fans",
        "label": "Fans",
        "value": 428117,
        "period": "all_time"
      },
      {
        "key": "collections",
        "label": "Collections",
        "value": 6120344,
        "period": "all_time"
      }
    ],
    "rankings": [
      {
        "board": "yuepiao",
        "board_label": "Monthly Votes",
        "channel": "overall",
        "channel_label": null,
        "position": 212,
        "url": "https://daosearch.io/qidian/rankings?page=5"
      }
    ],
    "booklist_count": 5997,
    "availability": {
      "state": "available",
      "since": null
    },
    "also_on": [
      {
        "source": "qimao",
        "source_book_id": "1693271",
        "url": "https://daosearch.io/qimao/book/1693271/lord-of-the-mysteries"
      }
    ],
    "english_translation": {
      "site": "RandomTranslator",
      "url": "https://randomtranslator.com/novel/4812"
    },
    "translated_by": "GPT-6 Luna"
  }
}

GET /search takes exactly one of two parameters.

  • q is a title in English or Chinese, or a book's URL at its source. A title returns up to 5 books across all sources, in the site's own order, and forgives a typo when nothing matches exactly. One Chinese character is enough; a query in Latin letters needs 3. A URL returns that one book, or nothing if we do not hold it.
  • author is an author's name: the first 5 books by that author on each source, so up to 30. For more of one author use the catalogue's author filter.
  • source narrows either to one source.

Sending both q and author, or neither, is a 400. There is no paging and no relevance score. A result is a short card: get the book for its details.

curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/search?q=lord+of+the+mysteries"
{
  "data": [
    {
      "source": "qidian",
      "source_book_id": "1010868264",
      "url": "https://daosearch.io/qidian/book/1010868264/lord-of-the-mysteries",
      "title": {
        "en": "Lord of the Mysteries",
        "zh": "诡秘之主"
      },
      "author": {
        "en": "Cuttlefish That Loves Diving",
        "zh": "爱潜水的乌贼"
      },
      "cover_url": "https://daosearch.io/img/cover/qidian/1010868264.jpg",
      "matched": "title"
    }
  ]
}

The catalogue

GET /{source}/books is a source's catalogue with the filters of its library page: title, author, status, genre, subgenre, tag and tag_not (both repeatable), tag_match, min_words, max_words, updated, dropped, sort, order, and each source's own filters and minimums.

  • Sorts, the source's own filters (audience, or pov and access on JJWXC) and the minimums on its figures differ by source. GET /sources lists them, and the OpenAPI document repeats them per source.
  • A minimum such as min_fans or min_score takes one of the source's steps, not any number. On Fanqie, min_reads filters on lifetime reads (reads_all_time), not on the current reads figure.
  • genre and tag take the zh of a genre or tag. subgenre needs its genre.
  • A view with no filter can be paged 50 deep, a view with one filter 20, and a view with two or more 5. Each tag counts as a filter. Narrow the view to see more of it.
  • title takes a piece of a title. A book URL there is a 400 that points you to /search.
  • There is no catalogue across sources and no sort across them: their figures do not compare.
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/books?status=completed&min_fans=100000"
{
  "data": [
    {
      "source": "qidian",
      "source_book_id": "1010868264",
      "url": "https://daosearch.io/qidian/book/1010868264/lord-of-the-mysteries",
      "title": {
        "en": "Lord of the Mysteries",
        "zh": "诡秘之主"
      },
      "author": {
        "en": "Cuttlefish That Loves Diving",
        "zh": "爱潜水的乌贼"
      },
      "cover_url": "https://daosearch.io/img/cover/qidian/1010868264.jpg",
      "genre": {
        "en": "Fantasy",
        "zh": "玄幻"
      },
      "status": "completed",
      "word_count": 4465200,
      "synopsis_excerpt": "With the rising tide of steam power and machinery, who can come close to being a Beyonder? Shrouded in the fog of history and darkness, who or what is the lurking evil that murmurs into our ears?",
      "metrics": [
        {
          "key": "monthly_votes",
          "label": "Votes",
          "value": 15864,
          "period": "month"
        },
        {
          "key": "recommendation_votes",
          "label": "Recs",
          "value": 10203441,
          "period": "all_time"
        },
        {
          "key": "fans",
          "label": "Fans",
          "value": 428117,
          "period": "all_time"
        }
      ]
    }
  ],
  "page": {
    "number": 1,
    "size": 50,
    "count": 50,
    "total": 213,
    "total_capped": false,
    "last": 5,
    "next_url": "https://daosearch.io/api/v1/qidian/books?min_fans=100000&page=2&status=completed"
  }
}

Genres and tags

GET /{source}/genres lists a source's genres with their subgenres, and GET /{source}/tags its tags with how many books carry each. These are the values the catalogue's genre, subgenre, tag and tag_not take. book_count on a genre is null when it holds fewer than 25 books. The tags are every tag on 25 or more of the source's books, up to 3,000 in one answer; q narrows them by name.

curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/genres"
{
  "data": [
    {
      "zh": "玄幻",
      "en": "Fantasy",
      "book_count": 214530,
      "url": "https://daosearch.io/qidian/library?genre=3",
      "audience": "male",
      "subgenres": [
        {
          "zh": "东方玄幻",
          "en": "Eastern Fantasy"
        },
        {
          "zh": "异世大陆",
          "en": "Otherworld Continent"
        }
      ]
    }
  ]
}
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/tags?q=system"
{
  "data": [
    {
      "zh": "系统",
      "en": "System",
      "book_count": 88214,
      "url": "https://daosearch.io/qidian/library?tag_in=412"
    }
  ]
}

Rankings

GET /{source}/rankings lists the boards we hold for a source now: each board's code, its name, what it ranks by, how deep it goes and its channels (a genre, an audience, or the whole board). Boards come and go, so list them and do not hard-code a code.

GET /{source}/rankings/{board} is one page of a board as the source last published it. Each entry has its position, its previous_position at the last daily snapshot, and movement: new, up, down or flat. channel picks one of the board's channels.

  • depth is how many places a board can hold: 100 on most, 200 on Zongheng, 500 on Qidian's monthly votes. page.total is how many the channel holds now.
  • Only places the source itself published are returned. On the site, Qidian's genre boards for monthly votes go on past Qidian's own last place using the votes we hold; those continued places are not in the API.
  • ranked_by names the metric key the board is ordered by, and that figure is first in each book's metrics with "ranked_by": true. It is null where the source publishes no figure for the board. Some boards carry a figure of their own, such as Faloo's weekly_reads or Qimao's heat: GET /sources describes each.
  • A book first seen on a board has a null title until we have indexed it.
  • An unknown board or channel is a 404. We do not answer with a different board.
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/rankings"
{
  "data": [
    {
      "board": "yuepiao",
      "label": "Monthly Votes",
      "zh": "月票榜",
      "description": "Qidian's monthly vote ranking: readers spend monthly tickets on the books they follow.",
      "ranked_by": "monthly_votes",
      "depth": 500,
      "default_channel": "overall",
      "channels": [
        {
          "channel": "overall",
          "label": "All",
          "zh": "全部"
        },
        {
          "channel": "21",
          "label": "Fantasy",
          "zh": "玄幻"
        }
      ],
      "url": "https://daosearch.io/qidian/rankings"
    }
  ]
}
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/rankings/yuepiao?view=compact"

This one is the compact view:

{
  "data": {
    "source": "qidian",
    "board": "yuepiao",
    "label": "Monthly Votes",
    "zh": "月票榜",
    "channel": "overall",
    "channel_label": "All",
    "ranked_by": "monthly_votes",
    "refreshed_at": "2026-10-08T02:10:44Z",
    "url": "https://daosearch.io/qidian/rankings",
    "entries": [
      {
        "position": 1,
        "previous_position": 3,
        "movement": "up",
        "change": 2,
        "book": {
          "source": "qidian",
          "source_book_id": "1010868264",
          "url": "https://daosearch.io/qidian/book/1010868264/lord-of-the-mysteries",
          "title": {
            "en": "Lord of the Mysteries",
            "zh": "诡秘之主"
          },
          "author": {
            "en": "Cuttlefish That Loves Diving",
            "zh": "爱潜水的乌贼"
          },
          "genre": {
            "en": "Fantasy",
            "zh": "玄幻"
          },
          "status": "completed",
          "word_count": 4465200,
          "metrics": [
            {
              "key": "monthly_votes",
              "value": 15864,
              "ranked_by": true
            },
            {
              "key": "recommendation_votes",
              "value": 10203441
            },
            {
              "key": "fans",
              "value": 428117
            }
          ]
        }
      }
    ]
  },
  "page": {
    "number": 1,
    "size": 50,
    "count": 50,
    "total": 500,
    "total_capped": false,
    "last": 10,
    "next_url": "https://daosearch.io/api/v1/qidian/rankings/yuepiao?page=2&view=compact"
  }
}

Booklists

GET /{source}/booklists lists the reader-made lists of a source, and GET /{source}/booklists/{list_id} is one list with a page of its books. Zongheng has no booklists: both answer 404 not_supported there, and has_booklists in /sources says so in advance.

  • A list is named by its id at the source (list_id).
  • On the index, sort, min_books and the source's popularity minimum take the values in /sources. contains=qidian:1010868264 finds the lists that hold a book.
  • On one list, sort reorders its books by one of the source's figures, and status, min_words, dropped and has_note filter them. min_words takes one of the source's steps (booklists.min_words_steps in /sources). has_note exists only where lists carry curators' notes.
  • A list of more than 5,000 books cannot be sorted or filtered: that is a 400 sort_not_available. Ask for it plain.
  • A book on a list can belong to another source than the list. Each book says its own source.
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/booklists?min_books=30"
{
  "data": [
    {
      "source": "qidian",
      "list_id": "628204115",
      "url": "https://daosearch.io/qidian/booklists/628204115/apocalypse-survival-picks",
      "title": {
        "en": "Apocalypse Survival Picks",
        "zh": "末世求生精选"
      },
      "description_en": "Thirty survival stories that keep their rules straight.",
      "book_count": 30,
      "metrics": [
        {
          "key": "followers",
          "label": "Follows",
          "value": 1840
        }
      ],
      "updated_at": "2026-09-29T08:00:00Z"
    }
  ],
  "page": {
    "number": 1,
    "size": 50,
    "count": 50,
    "total": 2500,
    "total_capped": true,
    "last": 20,
    "next_url": "https://daosearch.io/api/v1/qidian/booklists?min_books=30&page=2"
  }
}
curl -H "Authorization: Bearer $DAOSEARCH_KEY" \
     "https://daosearch.io/api/v1/qidian/booklists/628204115"
{
  "data": {
    "source": "qidian",
    "list_id": "628204115",
    "url": "https://daosearch.io/qidian/booklists/628204115/apocalypse-survival-picks",
    "title": {
      "en": "Apocalypse Survival Picks",
      "zh": "末世求生精选"
    },
    "description_en": "Thirty survival stories that keep their rules straight.",
    "book_count": 30,
    "metrics": [
      {
        "key": "followers",
        "label": "Follows",
        "value": 1840
      }
    ],
    "updated_at": "2026-09-29T08:00:00Z",
    "translated_by": "GPT-6 Luna",
    "members": [
      {
        "position": 1,
        "note": "The best rule system of the genre, and it never cheats.",
        "book": {
          "source": "qidian",
          "source_book_id": "1010868264",
          "url": "https://daosearch.io/qidian/book/1010868264/lord-of-the-mysteries",
          "title": {
            "en": "Lord of the Mysteries",
            "zh": "诡秘之主"
          },
          "author": {
            "en": "Cuttlefish That Loves Diving",
            "zh": "爱潜水的乌贼"
          },
          "cover_url": "https://daosearch.io/img/cover/qidian/1010868264.jpg",
          "genre": {
            "en": "Fantasy",
            "zh": "玄幻"
          },
          "status": "completed",
          "word_count": 4465200,
          "synopsis_excerpt": "With the rising tide of steam power and machinery, who can come close to being a Beyonder? Shrouded in the fog of history and darkness, who or what is the lurking evil that murmurs into our ears?",
          "metrics": [
            {
              "key": "monthly_votes",
              "label": "Votes",
              "value": 15864,
              "period": "month"
            },
            {
              "key": "recommendation_votes",
              "label": "Recs",
              "value": 10203441,
              "period": "all_time"
            },
            {
              "key": "fans",
              "label": "Fans",
              "value": 428117,
              "period": "all_time"
            }
          ]
        }
      }
    ]
  },
  "page": {
    "number": 1,
    "size": 50,
    "count": 30,
    "total": 30,
    "total_capped": false,
    "last": 1,
    "next_url": null
  }
}

Errors

An error is JSON with a stable code, the HTTP status, a message that says what to do next, and param when one parameter is at fault. Branch on code. Messages may be reworded.

{
  "error": {
    "code": "invalid_parameter",
    "status": 400,
    "param": "min_score",
    "message": "min_score must be one of 7, 8.5, 9, 9.5 on fanqie.",
    "docs_url": "https://daosearch.io/developers#errors"
  }
}
status code when
400 invalid_parameter A parameter's value is not one the endpoint takes. param names it and the message lists what it does take. Also answered for a key sent in the URL.
400 unknown_parameter The request sent a parameter the endpoint does not have. The message lists the ones it has.
400 page_out_of_range page is past the last page this view allows. The message names the last page.
400 sort_not_available A booklist too large to sort was asked for sorted or filtered. Ask for it without sort and filters.
401 missing_key No Authorization header, or not a Bearer one.
401 invalid_key The key is not one DaoSearch issued, or it has expired after a rotation.
401 revoked_key The key was revoked. Create a new one on your account page.
403 account_blocked API access for the key's account was blocked by DaoSearch.
403 cors_not_allowed A browser asked, for a web page on another origin, whether it may call the API. It may not.
404 not_found No such book, board, channel, list or path. A book DaoSearch has hidden is not_found too.
404 unknown_source The {source} segment is not one of the sources. The message lists them.
404 not_supported The source has no such resource: Zongheng has no booklists.
405 method_not_allowed The API is read-only: GET and HEAD.
429 rate_limited The key made more requests this minute than it may. Wait Retry-After seconds.
429 quota_exceeded The account has used its units for today. Retry-After is the seconds until 00:00 UTC.
500 internal Something failed on our side. Try again in a moment.
503 api_disabled The API is switched off for now. Try again later.

A 401 also carries WWW-Authenticate: Bearer. A 429 and a 503 carry Retry-After, in seconds.

Terms

By creating a key you agree to these.

  1. The API is free, for personal projects and tools. It may change or stop; a breaking change gets a new version path and 90 days.
  2. Show a link to the book's url wherever you show its data.
  3. Keep to the limits and cache what you fetch. The RateLimit headers tell you where you stand.
  4. Do not use it to copy the catalogue or to train on it in bulk. Titles, synopses and covers belong to their authors and the source sites.
  5. Keep the key out of public pages and repositories. One you publish will be revoked.
  6. Send a User-Agent that names your tool.

DaoSearch provides translations and links for discovery. The works belong to their authors and to the sites that publish them.

Versioning

/api/v1 is the contract. These are not a new version, so write a client that tolerates them: a new field, a new endpoint, a new optional parameter, a new value in a list such as availability.state, a new metric key, a looser limit.

Removing or renaming a field, changing what one means, or making a parameter required would be a new path, /api/v2. /api/v1 would then keep working for at least 90 days and say when it ends in a Sunset header.

The limits and these terms are not part of the version. They may tighten, and this page will say so first.

For LLM tools

The OpenAPI document gives each endpoint an operationId that reads as an intent (get_book, search_books, list_catalogue), a description that says when to use it and what it costs, and an example. Most agent tooling can turn it into tools directly. /llms.txt describes the site's public pages in a few lines.

Contact

Questions, a bug, or a limit that is too tight for something reasonable: write to [email protected] or ask in the Discord. If a key has leaked, revoke it on your account page first.