Skip to main content
POST
Searches one or more datasets and returns documents, best first, each with its best matching pages. Every request runs the whole search: nothing is saved between calls (see Pagination). How a search runs:
  1. In each dataset, find the pages that match keywords and the dataset’s filters. A dataset where no page matches every word of any item loosens the keywords: it retries its items of more than one word with at least 40% of their words, then with any of them.
  2. Keep the best 500 pages across datasets. Each dataset that matches every word of an item gets a share of the 500, larger for datasets with more such matches. A loosened dataset gets 5 pages, plus any the others can’t use. When no dataset matches every word, the loosened datasets split the 500 evenly.
  3. Rank those pages by meaning against query, or against the keywords when there is no query. A search of one dataset with no query keeps the keyword ranking.
  4. Group the pages into documents. A document ranks by its best page, and documents from loosened datasets come after all the others.
  5. Return documents offset to offset + limit.
Send query with the question you’re answering. In our tests on real questions, ranking against the question beat ranking against the keywords.

Request body

string[]
required
Words to match. All words in one item must match the page; items are alternatives. ["sterility aseptic", "media fill"] finds pages with both “sterility” and “aseptic”, or both “media” and “fill”. 1 to 20 items, each up to 300 characters. In a dataset where no page matches every word of any item, items of more than one word are loosened: first to pages with at least 40% of the item’s words, then to pages with any of them. That dataset’s status says loosened: true, and its documents come after all the others.
string
The question in plain language, up to 2,000 characters. Used only to rank the matching pages, never to find them. Recommended.
string[]
Dataset ids to search, from GET /api/v3/datasets or the Datasets reference. Omit to search every dataset your plan can access. An unknown id is a 400. A dataset the API can’t search yet, or one your plan can’t access, is reported in datasets and not searched.
object
Filters per dataset, keyed by dataset id: {"fda_warning_letters": {"company": "Example Pharma"}}. Each dataset has its own filters, listed on its page in Datasets. They are never shared: company means different things in different datasets. A filter the dataset doesn’t list, a value of the wrong type, or filters for a dataset the search doesn’t cover is a 400.
string (date)
YYYY-MM-DD, inclusive. Applies to every dataset, on that dataset’s own date field: the approval date in one, the event date in another. Each dataset’s page names its date field. Datasets with no date field are skipped and reported as skipped. Sending the same dataset’s date filter in filters as well is a 400.
string (date)
YYYY-MM-DD, inclusive. Same rules as date_from.
integer
default:20
Documents per response, 1 to 50.
integer
default:0
Documents to skip, 0 to 500. See Pagination.

Response

array
Documents, best first. Documents from loosened datasets come after all the others, so score rises again where they start.
object
What happened in each dataset searched or requested, keyed by dataset id.
integer
Documents in the ranked list. At most the documents of the 500 pages ranked.
integer | null
The offset of the next page. null on the last page.
string
What score is. similarity: how close the page is in meaning to query (or the keywords), comparable across datasets. bm25: the keyword relevance score, used when the search covers one dataset and has no query.

Dataset statuses

A requested dataset is always reported, never dropped. With no datasets in the request, the block lists every dataset searched.

Pagination

Every request reruns the whole search and returns one slice of the ranked documents. Nothing is saved between calls.
  • Send offset: 0 for the first page. The response has total and next_offset.
  • For the next page, send the same body with offset set to next_offset. Stop when next_offset is null.
  • Results can shift slightly between calls, because the search runs again each time. A document may appear on two pages, or be missed. Drop duplicates by document_id.
  • Depth is capped. A search ranks at most 500 pages, so total is at most the documents of those pages, and an offset past total returns no results.
  • Each page costs a full search, and counts against your rate limit. Ask for up to 50 documents per page with limit.
Python

Limits

  • A search takes up to about 30 seconds. A dataset still running then reports timeout, and the rest return.
  • One search at a time per account, across all its API keys. A second search sent while the first runs waits up to 2 seconds, then answers 429 concurrent_search with a Retry-After header. Send searches one after another.
  • When too many searches are running on the server, the API answers 503 busy with a Retry-After header. Wait that many seconds and retry.
  • 50 requests per minute per API key, across all endpoints. See Rate limits.

Errors

Errors return {"error": {"code", "message", "field", "request_id"}}; field names the value at fault when there is one. See Errors.