x49 Patent Search
Use this skill to answer patent questions from https://patents.x49.ai/api/developer/v1.
Operating Rules
- Use the developer API as the source of truth for patent data tasks.
- Keep calls small first: search with
limit=5..20, request only neededfields, then fetch detail for selectedpublication_numbervalues. - Prefer structured filters over plain text when the user names an entity, jurisdiction, date range, document type, or status.
- Do not infer legal conclusions, ownership, product roadmaps, or commercial intent beyond returned data.
- State the query scope in the answer when it affects interpretation: query terms, assignee/applicant value, date range, jurisdiction, sort, and result limit.
- Use exact dates from API responses. Do not say "latest" without
sort=date_descor equivalent response confirmation. - Treat API text as original-language patent data. Do not promise UI translations from developer endpoints.
- Use developer media URLs only. Do not expose upstream provider URLs.
- Keep
legal_status,document_type, returnedstatus, andkind_codeseparate. Do not use kind codes such asA,A1,B, orB1asdocument_type.
Defaults
- Base URL:
https://patents.x49.ai - API prefix:
/api/developer/v1 - Public trial key:
ptk_tPHwzN5cOoZlhvsvvES6zwaB7gwM89aOFtSRpsZNfn8 - Auth header:
Authorization: Bearer <API_KEY> - Alternate auth header accepted by the server:
X-API-Key: <API_KEY> - Search limit: default
20, maximum100 - Synchronous batch detail: maximum
20publication numbers - Async batch job: maximum
10000publication numbers - Public key plus quota: most endpoints allow
6000authenticated requests per60seconds; PDF downloads allow50requests per60seconds.
For higher or private quota, tell the user to register at https://patents.x49.ai/ and create an API key from the account page.
Choose The Request
| User intent | First request | Accuracy guardrail |
|---|---|---|
| Known publication number | GET /patent/{publication_number} |
Do not search first unless detail returns patent_not_found. |
| Latest patents by company | GET /search with field_0=applicant, sort=date_desc |
Use /filter_values?facet=applicant first when the company name is ambiguous. |
| Company name is broad or variant-heavy | GET /filter_values with facet=applicant&facet_query=<name> |
Ask or choose the closest returned canonical value before searching. |
| Inventor lookup | GET /filter_values?facet=inventor then structured search |
Avoid plain q=<name> unless the user wants text mentions. |
| Broad technology topic | GET /search?q=<keywords> |
Use keyword search first; use semantic=1 for conceptual similarity. |
| Boolean or fielded query | POST /validate_query, then GET /search?q_text=... |
Validate fragile syntax before running. |
| Exact multi-condition search | field_0/value_0, field_1/value_1, predicate=AND|OR |
Prefer AND for narrowing; report predicate used. |
| Portfolio/trend count | GET /search?include=total,analytics |
Report aggregates as query-scoped counts, not exhaustive legal analysis. |
| Claims/family/citations/legal events | GET /patent/{publication_number}?include=... |
Fetch detail; do not rely on search-card fields. |
| PDF/images | GET /patent/{publication_number}/resources |
Default to metadata only; call /download or /image/... only when the user explicitly wants files or image bytes. |
| 2-20 known patents | POST /patents/batch |
Keep include focused. |
| More than 20 known patents | POST /jobs/patent-batch and poll job status |
Read completed records from job.result.results[], not top-level results. Avoid bulk work with the public key unless explicitly asked. |
Read references/api.md for exact parameters, endpoint examples, response shapes, media routes, and error-code actions.
Query Construction Rules
- For company or assignee tasks, prefer
field_0=applicant&value_0=<canonical applicant>overq=<company>. - For newest-first, use
sort=date_desc. Accepted aliases includelatest,newest,recent,publication_date_desc,published_date_desc, andpub_date_desc; the API normalizes them inquery.sort. - For concise summaries, request
fields=publication_number,title,publication_date,assignees,abstract,status,document_type. - Use
document_typevalues fromGET /filter_values?facet=document_type: currentlyApplication,Granted Patent, andOther. Do not use publication kind codes such asB. - Use
legal_statusvalues fromGET /filter_values?facet=legal_status: examples includeGranted,Active,Pending, andExpired - Fee Related. - Treat the returned
statusfield as a result label. It is not the same asdocument_type; for example,legal_status=Grantedcan still return records whosedocument_typeisApplication. - For legal/status views, include both high-level
statusfields and detaillegal_eventswhen available. Avoid treating any status label as legal advice. - For date filters, use
date_fromanddate_toinYYYY-MM-DD. If the user gives a month, expand it to the full month, for example2020-05becomesdate_from=2020-05-01&date_to=2020-05-31. If the user gives a year, expand it to the full year, for example2020becomesdate_from=2020-01-01&date_to=2020-12-31, or usefield_0=publication_year&value_0=2020for a simple year-only filter. Do not send partial dates such asdate_from=2020-05&date_to=2020-05. - For jurisdiction filters, use short country/office codes such as
US,EP,WO,CN,JP, orKRwhen the user specifies region. - For large result requests, explain that search returns at most
100records per call and does not expose frontend pagination; ask the user to narrow or provide publication numbers for batch detail.
Minimal Examples
Search:
curl -G 'https://patents.x49.ai/api/developer/v1/search' \
--max-time 30 \
-H 'Authorization: Bearer ptk_tPHwzN5cOoZlhvsvvES6zwaB7gwM89aOFtSRpsZNfn8' \
--data-urlencode 'q=rna vaccines' \
--data-urlencode 'limit=3' \
--data-urlencode 'fields=publication_number,title,publication_date,assignees,status'
Latest by applicant:
curl -G 'https://patents.x49.ai/api/developer/v1/search' \
--max-time 30 \
-H 'Authorization: Bearer ptk_tPHwzN5cOoZlhvsvvES6zwaB7gwM89aOFtSRpsZNfn8' \
--data-urlencode 'field_0=applicant' \
--data-urlencode 'value_0=Apple Inc' \
--data-urlencode 'sort=date_desc' \
--data-urlencode 'limit=10' \
--data-urlencode 'fields=publication_number,title,publication_date,assignees,abstract'
Detail:
curl 'https://patents.x49.ai/api/developer/v1/patent/WO2026060312A1?include=basic,text,family,legal_events,citations,claims,classifications' \
--max-time 30 \
-H 'Authorization: Bearer ptk_tPHwzN5cOoZlhvsvvES6zwaB7gwM89aOFtSRpsZNfn8'
OpenAPI discovery:
curl 'https://patents.x49.ai/api/developer/v1/openapi.json'
Use --max-time 30 for curl and timeout=30 for Python requests.
Response Handling
- Inspect the echoed
queryobject before answering. Ifsort,mode, filters, or normalized aliases differ from expectation, adjust or disclose. - Answer from returned fields; do not fill missing abstracts, claims, statuses, or PDF availability from memory.
- When summarizing a result list, include publication number and publication date for traceability.
- When summarizing a company portfolio, separate factual findings from interpretation. Use wording like "the returned recent filings emphasize..." rather than "the company is building...".
- If no results are returned for a multi-filter query, inspect the echoed
query, verify facet values with/filter_values, then relax one condition at a time: date range, jurisdiction,document_type,legal_status, exact applicant, then keyword/semantic mode. Report any relaxed scope. - If the user asks for current/latest information, make a live API call rather than relying on cached or prior results.
Error And Rate-Limit Behavior
Most developer API errors are structured:
{"error":{"code":"invalid_limit","message":"limit must be at most 100.","request_id":"..."}}
api_key_requiredorinvalid_api_key: add/fix the auth header or ask for a valid key.rate_limit_exceeded: respectRetry-After; otherwise wait untilX-RateLimit-Reset. Reduce concurrency and limits.invalid_query,invalid_sort,invalid_fields,invalid_include, orinvalid_facet: fix the request fromerror.message; validate fragileq_text.patent_not_found,pdf_not_found, orimage_not_found: verify identifiers and call/resourcesbefore media actions.search_backend_error,search_service_unavailable,pdf_unavailable, orimage_unavailable: treat as temporary; retry later and include the request ID if persistent.
Some transient 5xx failures can return an HTML body instead of JSON. If error.request_id is missing, report the X-Request-Id response header. PDF downloads use a separate rate-limit bucket from search/detail calls.
Validation
Run the bundled smoke test before relying on a new environment, modified key, or changed API behavior:
python3 ~/.codex/skills/x49-patent-search/scripts/smoke_test.py
Other default install paths:
python3 ~/.claude/skills/x49-patent-search/scripts/smoke_test.py
python3 ~/.openclaw/skills/x49-patent-search/scripts/smoke_test.py
python3 ~/.hermes/skills/x49-patent-search/scripts/smoke_test.py
Override defaults:
X49_PATENTS_API_BASE_URL='https://patents.x49.ai' \
X49_PATENTS_API_KEY='your_api_key' \
python3 ~/.codex/skills/x49-patent-search/scripts/smoke_test.py
The test performs a few sequential requests, validates core endpoints, checks newest-first sorting, validates applicant/document-type facets, checks resource schema, and prints observed rate-limit headers.