Docs/API

Data API

Data API

The Data API is the search behind Patalyze as a plain HTTP service. It runs the same searches over the same data as the search dialog in the app, so you can use our patents, scientific papers, technical standards and CPC/IPC classifications from your own code.

The API is read-only. This page starts with how to authenticate and run your first search. The Endpoints section below then describes every endpoint in detail.

Authentication#

Every request needs your organization's API key. You can find the key in the Patalyze app under Settings > API key, where you can also replace it with a new one at any time.

Simply send the key as a bearer token in the Authorization header:

Authorization: Bearer pat_...

Secure 5€ in free AI & Data usage

All interactive demos below automatically use your organization's API key. If you are not registered yet, you can create an account to receive 5€ in free AI & Data usage which you can use to execute the interactive demos below.

Keep your key secret

The key grants access to your organization's AI & Data usage. Keep it out of client-side code and version control, and replace it the moment you suspect it has leaked.

Make your first request#

A search is a POST to /patents with a JSON body. The filters describe what to match. The example below finds patents that contain the words solid state electrolyte and prints how many there are.

POST/patents
const res = await fetch("https://data.patalyze.com/patents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PATALYZE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    filters: [
      { field: "Text", operator: "contains", value: "solid state electrolyte" },
    ],
    limit: 5,
  }),
});

const data = await res.json();
console.log(data.total);

The response is a page of matching patents together with the total number of matches. To read a single patent in full, use the fetch endpoint: GET /patents/{publication_number}.

Filter and search syntax#

Every search is a list of filters, and each filter pairs a field (such as Text, Claims or Territory) with an operator and a value. There are two ways to match, boolean and semantic, and you can mix them in one request.

Boolean filters match exact terms. Use them for hard constraints such as a territory, a date range, an assignee or a classification code.

{ "field": "Text", "operator": "contains", "value": "solid state electrolyte" }

The similar to operator on Text or Claims ranks results by meaning. Pass a short description and the closest matches come back first, including patents that describe the same idea in different words.

{ "field": "Claims", "operator": "similar to", "value": "lithium-ion battery" }

In practice you combine the two. A similar to filter ranks the results, and boolean filters narrow them to the territories, dates and statuses you care about.

Defaults to US and EP

Without a Territory filter, a patent search only returns US and EP publications.

Semantic search on papers and standards returns no results yet

similar to currently only works on patents. Use the boolean operators on papers and standards until then.

The same search as our MCP tools

The Patents (by Patalyze) MCP server offers these endpoints to AI assistants as tools, with the same filters and the same responses.

Endpoints#

All endpoints live under https://data.patalyze.com. Patents, papers, standards and classifications each have a search endpoint and a fetch endpoint. Papers and standards can also be read in batches of up to 100 ids.


Search patents#

Searches our patent corpus. The JSON body is a list of filters, plus optional paging, sorting and deduplication.

POST/patents

Example code#

const res = await fetch("https://data.patalyze.com/patents", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PATALYZE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    filters: [
      { field: "Claims", operator: "similar to", value: "lithium-ion battery" },
      { field: "Territory", operator: "is any of", value: ["US", "EP"] },
      { field: "Priority date", operator: "after", value: "2018-01-01" },
      { field: "Status", operator: "is", value: "In-force" },
    ],
    sort: [{ field: "publication_date", order: "desc" }],
    deduplication: "application",
    limit: 20,
  }),
});

const data = await res.json();
console.log(data.total);

Example response#

{
  "results": [
    {
      "publication_number": "US11735790B2",
      "country": "US",
      "kind": "B2",
      "publication_date": "2023-08-22",
      "status": "In-force",
      "title": "Solid-state electrolyte for lithium batteries",
      "abstract": "A solid-state electrolyte for lithium-metal cells that suppresses dendrite growth.",
      "assignees": ["SolidPower Inc."],
      "inventors": ["Jane Doe"],
      "cpc": ["H01M10/0562", "H01M10/052"],
      "earliest_priority_date": "2022-01-15",
      "family": [
        { "publication_number": "EP4123456A1", "country": "EP", "kind": "A1", "status": "Filed" }
      ]
    }
  ],
  "total": 1542,
  "offset": 0,
  "limit": 20
}

Body parameters#

Filter object#

Filter fields and operators#

Every field takes its own set of operators, listed below. You don't have to match their spelling to the letter. Letter case and spacing don't matter, and contains works just as well as contain. If a field doesn't take an operator at all, the error message lists the ones it accepts.

Text and claim searches take a trailing * wildcard: electrolyte* also matches electrolytes. Classification codes already match by prefix, so they need no wildcard.

Combining filters#

Each filter's combination controls how it joins the others. It defaults to And, so you only set it to broaden a query with Or.

  • And means every result must match the filter.
  • Or means a result that matches any of the Or filters is included.
  • A negative operator (such as does not contain or is not) always excludes its matches.

The first similar to filter ranks the results. A request can hold up to four of them, and you can mix them freely with boolean filters.

The order of the filters matters. A boolean filter before the first similar to filter narrows what the semantic search runs over, and one after it is applied to its results. So a Status filter placed before it gives you the best in-force matches, while the same filter placed after it gives you the in-force patents among the best matches overall.

Attachments#

A similar to value does not have to be text. It can also hold attachments, so you can search with a datasheet or a product photo instead of describing it in words. You can combine text and attachments in one filter, e.g. to add a sentence of context to a document.

{
  "field": "Claims",
  "operator": "similar to",
  "value": [
    "solid-state electrolyte with a lithium-metal anode",
    {
      "kind": "file",
      "type": "application/pdf",
      "name": "cell-datasheet.pdf",
      "data": "JVBERi0xLjQKJeLjz9MKMy..."
    }
  ]
}

Attachments only work with similar to on Text or Claims, and one filter holds up to four of them.

Aggregations#

Aggregations count the matching patents by a field, e.g. by year or by assignee. That way one request returns both a page of results and an overview of all matches. You can ask for up to five aggregations per request. The counts cover every match, so set the request limit low when the counts are all you want.

POST/patents

The response then carries an aggregations object with a list of { value, count } for each field you asked for.

{
  "results": [ ... ],
  "total": 1542,
  "offset": 0,
  "limit": 1,
  "aggregations": {
    "priority_year": [
      { "value": "2021", "count": 214 },
      { "value": "2022", "count": 389 },
      { "value": "2023", "count": 471 }
    ],
    "assignee": [
      { "value": "SolidPower Inc.", "count": 96 },
      { "value": "Toyota Motor Corporation", "count": 74 }
    ]
  }
}

Response fields#


Fetch patent#

Returns one patent in full, including its claims, description, legal events and family members.

GET/patents/US11735790B2

Example code#

const res = await fetch(
  "https://data.patalyze.com/patents/US11735790B2",
  { headers: { Authorization: `Bearer ${process.env.PATALYZE_API_KEY}` } },
);
const patent = await res.json();
console.log(patent.title);

Example response#

The example below is shortened. A real response also carries the claims and the other fields listed below. An unknown publication number returns 404.

{
  "publication_number": "US11735790B2",
  "country": "US",
  "doc_number": "11735790",
  "kind": "B2",
  "status": "In-force",
  "title": "Solid-state electrolyte for lithium batteries",
  "publication_date": "2023-08-22",
  "earliest_priority_date": "2022-01-15",
  "cpc": ["H01M10/0562", "H01M10/052"],
  "assignees": [{ "name": "SolidPower Inc.", "city": "Louisville", "country": "US" }],
  "inventors": [{ "name": "Jane Doe" }],
  "citations": [
    { "type": "patent", "publication_number": "US10511055B2", "cited_phase": "SEA" },
    { "type": "npl", "text": "Smith et al., J. Power Sources 2020" }
  ],
  "family": [
    { "publication_number": "EP4123456A1", "country": "EP", "kind": "A1", "status": "Filed" }
  ],
  "abstract": [
    {
      "type": "paragraph",
      "content": [
        { "type": "text", "text": "A solid-state electrolyte composition for lithium-ion cells ..." }
      ]
    }
  ],
  "abstract_language": "en"
}

Response fields#

The record also carries application_number, application_date, grant_date and language. Every date is a YYYY-MM-DD string, and a field the patent has no value for is left out.


Search classifications#

Searches the CPC/IPC classifications. The mode decides how the query is matched: by symbol, by text or by meaning.

POST/classifications

Example code#

const res = await fetch("https://data.patalyze.com/classifications", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.PATALYZE_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ mode: "text", query: "solid electrolyte", limit: 10 }),
});

const data = await res.json();
console.log(data.total);

Example response#

{
  "results": [
    {
      "symbol": "H01M10/0562",
      "title": "Solid materials for use as electrolytes",
      "depth": 0,
      "score": 0.91
    }
  ],
  "total": 12,
  "offset": 0,
  "limit": 10
}

Body parameters#

Response fields#


Fetch classification#

Returns a single classification, such as H01M10, together with the classes above it.

GET/classifications/H01M10

Example code#

const res = await fetch(
  "https://data.patalyze.com/classifications/H01M10",
  { headers: { Authorization: `Bearer ${process.env.PATALYZE_API_KEY}` } },
);
const classification = await res.json();
console.log(classification);

Example response#

An unknown symbol returns 404.

{
  "symbol": "H01M10",
  "title": "Secondary cells; Manufacture thereof",
  "depth": 1,
  "parent": "H01M",
  "parents": [
    { "symbol": "H", "title": "Electricity", "depth": 4 },
    { "symbol": "H01", "title": "Basic electric elements", "depth": 3 },
    { "symbol": "H01M", "title": "Processes or means for the direct conversion of chemical energy into electrical energy", "depth": 2 }
  ],
  "notes": "",
  "statement": "",
  "glossary": "",
  "synonyms": "",
  "definition": null,
  "images": []
}

Response fields#


Search papers#

Searches scientific papers. For each paper we hold the abstract and the bibliographic data. The body takes the same filters, limit, offset, sort and aggregations as a patent search, with the fields listed below.

POST/papers

Example response#

{
  "results": [
    {
      "id": "W4382300818",
      "title": "Solid electrolyte interphase formation in lithium metal cells",
      "abstract": "We resolve the interphase composition that suppresses dendrite growth.",
      "authors": ["Jane Doe", "A. Khan"],
      "institutions": ["ETH Zurich"],
      "venue": "Nature Energy",
      "topics": ["Battery Materials"],
      "doi": "10.1038/s41560-023-01234-5",
      "publication_date": "2023-06-14",
      "publication_year": 2023,
      "cited_by_count": 142,
      "oa_status": "gold",
      "is_retracted": false
    }
  ],
  "total": 3184,
  "offset": 0,
  "limit": 20
}

Filter fields and operators#

Two groups of operators come up again and again below. The contains family is contains, does not contain, contains any of, contains all of, does not contain any of and does not contain all of. The is family is is, is not, is any of and is not any of. Standards use the same two groups.

Sorting and aggregations#

sort accepts _score, publication_date, publication_year, cited_by_count and fwci (field-weighted citation impact). aggregations takes up to five facets over publication_year, type, language, oa_status, license, source_type, venue, topic, institution and country, in the same shape as on patents.


Fetch paper#

Returns one paper by its id, such as W4382300818. We hold the abstract and the bibliographic data of a paper, never the paper itself. Every paper also has a public page at patalyze.com/paper/{id}.

GET/papers/W4382300818

An unknown id returns 404.


Read papers by id#

Reads up to 100 papers in one request, for when you already have their ids, e.g. the referenced_works of a paper you fetched. The body takes ids and, optionally, the columns you want back. An id we don't hold is simply left out of the response.

POST/papers/columns

Example response#

{
  "papers": [
    {
      "id": "W4382300818",
      "title": "Solid electrolyte interphase formation in lithium metal cells",
      "publication_year": 2023,
      "cited_by_count": 142
    }
  ]
}

Search standards#

Searches technical standards from ETSI (including the 3GPP specifications), IETF, ISO, ITU-T and W3C. Every version of a standard is a result of its own. A Text filter also searches the full text of a standard, so a keyword search covers complete specifications.

POST/standards

Example response#

{
  "results": [
    {
      "doc_id": 5372604879234489040,
      "standard_id": "ietf:RFC 9114",
      "designation": "RFC 9114",
      "organization": "IETF",
      "type": "RFC",
      "status": "published",
      "status_native": "PROPOSED STANDARD",
      "committee": "quic",
      "title": "HTTP/3",
      "abstract": "The QUIC transport protocol has several features that are desirable for HTTP.",
      "publication_date": "2022-06-01",
      "is_latest_in_release": true,
      "page_count": 72,
      "section_count": 41,
      "has_full_text": true,
      "patents": ["US9432486"],
      "patents_id": ["US9432486B2"]
    }
  ],
  "total": 1,
  "offset": 0,
  "limit": 20
}

Filter fields and operators#

Sorting and aggregations#

sort accepts _score, publication_date, effective_date, edition and page_count. aggregations takes up to five facets over publication_year, organization, type, status, series, committee, release and language.

A search result never includes the full text of a standard. You read it with Fetch standard.


Fetch standard#

Returns one standard by its standard_id, which you get from a search, e.g. ietf:RFC 9114 or itu:T-REC-H.265-202407. Percent-encode it in the path, since it contains a colon and sometimes a space.

GET/standards/ietf%3ARFC%209114

Example response#

The example below is shortened. A real response carries every field of a search result as well.

{
  "doc_id": 5372604879234489040,
  "standard_id": "ietf:RFC 9114",
  "designation": "RFC 9114",
  "organization": "IETF",
  "title": "HTTP/3",
  "has_full_text": true,
  "full_text": "HTTP/3 ...",
  "sections": [
    {
      "clause": "4.1",
      "heading": "HTTP Message Framing",
      "depth": 2,
      "body_text": "A client sends an HTTP request on a request stream ...",
      "contains_table": false
    }
  ]
}

On top of what a search returns, the response carries the full_text of the standard and its clauses in sections. Each section has its clause number, heading, depth and body_text. Be aware that the text of a clause with a table may be incomplete, which is what the contains_table flag tells you.

A standard without numbered headings comes back without sections, just with its full_text. For ISO standards we only hold the catalogue entry, so they come back without any text.

Every standard also has a public page, e.g. patalyze.com/standard/ietf/RFC_9114 for ietf:RFC 9114.


Read standards by id#

Reads up to 100 standards in one request, for when you already have their ids. The body takes ids and, optionally, the columns you want back. An id we don't hold is left out of the response.

POST/standards/columns

Pricing#

Every request costs 0,075€, whatever it returns, and is paid from your organization's AI & Data usage.

Rate limits#

Your organization can send up to 100 requests per minute. We reserve the right to block requests to protect our services for other users.

Errors#

A failed request comes back as JSON with a short error code and a message that tells you what went wrong:

{ "error": "forbidden", "message": "No remaining AI & Data usage" }

The status codes you may see:

  • 400: a filter is invalid, for example an operator the field does not accept or a malformed date. The message says which.
  • 401: the bearer token is missing or invalid.
  • 403: your organization is out of AI & Data usage.
  • 404: no patent, paper, standard or classification exists for that id (the fetch endpoints).
  • 422: the request body could not be read, for example because of an unknown filter field.
  • 429: more than 100 requests in a minute. Slow down and retry.
  • 500 or 503: something went wrong on our side. Retry the request after a short wait.