Developer documentation

Patent Intelligence API v1.3

Search patents by technical query, title, parties, classification, or date range. Choose the fields your application receives, paginate structured results, or run AI novelty analysis. Indian patents by default, with worldwide publications where enabled. Four REST endpoints and an MCP server share the same API keys and quotas.


Base URL

https://patentnest.ai

Authentication

All requests authenticate with a bearer token in the Authorization header. API keys use the pn_live_ prefix and are provisioned per client. Do not embed keys in browser or mobile client code — this is a server-to-server API.

Header
Authorization: Bearer pn_live_your_key

A missing, invalid, revoked, or expired key returns 401 with error code INVALID_API_KEY or API_KEY_REVOKED. A suspended client returns 403 with CLIENT_SUSPENDED.



Filters and date ranges

Put search criteria inside filters. All supplied filters combine with AND; values within an array combine with OR. The same filters work in hybrid and structured mode. Text values must contain 1–300 characters after trimming; arrays accept 1–20 values.

FilterTypeMatches
titlestringCase-insensitive literal substring of the patent title.
abstractstringCase-insensitive literal substring of the abstract.
publicationNumberstringPart or all of a publication identifier; case and separators are ignored.
applicationNumberstringPart or all of an application identifier; case and separators are ignored.
applicantsstring[]Any supplied name as a case-insensitive substring of an applicant name.
inventorsstring[]Any supplied name as a case-insensitive substring of an inventor name.
classificationsstring[]Any IPC/CPC prefix, such as H01M. Spaces and separators are ignored.
filingDateFrom / filingDateToYYYY-MM-DDInclusive start and end of the filing-date range. Either bound can be omitted.
publicationDateFrom / publicationDateToYYYY-MM-DDInclusive start and end of the publication-date range. Either bound can be omitted.
grantDateFrom / grantDateToYYYY-MM-DDInclusive range for explicitly recorded IP India grant dates. Missing grant dates do not match.
Filter by title and filing dates; choose returned fields
curl -X POST "https://patentnest.ai/api/v1/patents/search" \
  -H "Authorization: Bearer pn_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "structured",
    "filters": {
      "title": "battery",
      "filingDateFrom": "2020-01-01",
      "filingDateTo": "2025-12-31",
      "classifications": ["H01M"]
    },
    "fields": ["title", "filingDate", "publicationDate", "grantDate", "applicants"],
    "sort": "filingDateDesc",
    "limit": 25,
    "offset": 0
  }'

Use identical From and To dates for an exact date. Dates must be real calendar dates; the From date must be on or before the To date. Missing dates do not match a range. Unknown filters, empty searches, and invalid or reversed dates return 400 INVALID_REQUEST. Text filters treat % and _ as literal characters.

The grant date, sometimes called the sanction date, is grantDate. It is returned only when explicitly recorded in stored IP India metadata; otherwise it is null. Publication dates and grant kind codes do not supply a grant date. Grant-date filters therefore cover only records with that information.

Search by recorded grant date
{
  "mode": "structured",
  "filters": {
    "title": "battery",
    "grantDateFrom": "2024-01-01",
    "grantDateTo": "2024-12-31"
  },
  "fields": ["title", "filingDate", "grantDate"],
  "sort": "grantDateDesc",
  "limit": 25
}

Choose response fields

Omit fields to receive the full public record. To request specific fields, send a nonempty array of top-level names from the patent record reference. For example, ["title", "filingDate", "grantDate"] returns those values alongside publicationNumber and source, which are always included for identity and attribution.

Selected search result (illustrative)
{
  "publicationNumber": "IN202211045678A",
  "title": "THERMAL MANAGEMENT SYSTEM FOR ELECTRIC VEHICLE BATTERY PACK",
  "filingDate": "2022-08-15",
  "grantDate": null,
  "source": {
    "name": "IP India Patent Journal",
    "document": "patent_journal_07_2023.pdf",
    "page": 142,
    "license": null,
    "attribution": null
  }
}

Select whole objects with source or relevance; names such as source.name are not accepted as field selectors. Relevance is available only for hybrid search results. Unknown field names return 400 INVALID_REQUEST. Field selection changes the patent records, while search coverage, pagination and response metadata retain their normal shape.

Selected fields on a direct lookup
curl "https://patentnest.ai/api/v1/patents/IN202211045678A?fields=title,filingDate,grantDate" \
  -H "Authorization: Bearer pn_live_your_key"

Pagination and sorting

Set mode: "structured" to retrieve individual publications without family deduplication or an embedding service. An optional query matches a literal substring in title or abstract. limit accepts 1–50 records per page (default 20); offset accepts 0–10,000 (default 0).

Structured sorting accepts publicationDateDesc (default), filingDateDesc, grantDateDesc, or titleAsc. Missing dates sort last, with publication number breaking ties. Hybrid search returns a ranked shortlist with sort: "relevance" and offset: 0; it has no pagination object.

Structured response pagination (abbreviated)
{
  "data": {
    "query": "",
    "mode": "structured",
    "count": 25,
    "results": [
      {
        "publicationNumber": "IN202211045678A",
        "title": "THERMAL MANAGEMENT SYSTEM FOR ELECTRIC VEHICLE BATTERY PACK",
        "filingDate": "2022-08-15",
        "publicationDate": "2023-02-17",
        "grantDate": null,
        "applicants": [{ "name": "XYZ Technologies Pvt Ltd", "address": "Bengaluru, India", "sequence": 1 }],
        "source": {
          "name": "IP India Patent Journal",
          "document": "patent_journal_07_2023.pdf",
          "page": 142,
          "license": null,
          "attribution": null
        }
      }
    ],
    "coverage": {
      "corpus": "indian-patent-journal",
      "jurisdictions": ["IN"],
      "searchMode": "structured",
      "embeddingModel": null
    },
    "pagination": {
      "offset": 0,
      "limit": 25,
      "hasMore": true,
      "nextOffset": 25
    }
  },
  "meta": { "requestId": "a1b2c3d4-e5f6-7890", "durationMs": 120 }
}

For the next request, keep the same filters, fields, limit and sort, and set offset to pagination.nextOffset. Stop when it is null: either the results have ended or the 10,000 offset cap has been reached. hasMore can still be true at that cap; narrow the filters to retrieve a smaller result set. count is the number on this page, not a total match count. New imports can shift results between pages.

A broad structured search that exceeds the time budget returns 503 PATENT_SEARCH_UNAVAILABLE. Narrow the filters before retrying. Grant-date filters and sorting depend on recorded metadata, so combining them with a title, classification, or filing-date constraint can help keep the search selective.


Worldwide coverage

Send jurisdictions to search beyond India. Worldwide records come from Google Patents Public Data and cover publications from 2000 onward across the major offices, including US, EP, WO, CN, JP, and KR. Any request that includes IN (or *) also searches the IP India journal corpus, so the newest Indian publications are never missed.

Example request
curl -X POST "https://patentnest.ai/api/v1/patents/search" \
  -H "Authorization: Bearer pn_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "battery thermal management for electric vehicles",
    "limit": 10,
    "jurisdictions": ["CN", "EP"]
  }'
Example response (abbreviated)
{
  "data": {
    "query": "battery thermal management for electric vehicles",
    "count": 10,
    "results": [
      {
        "publicationNumber": "CN-114123456-B",
        "kind": "B",
        "country": "CN",
        "familyId": "71234567",
        "title": "Thermal management system for a power battery pack",
        "abstract": "The invention discloses a liquid-cooling plate arrangement...",
        "publicationDate": "2023-06-02",
        "source": {
          "name": "Google Patents Public Data",
          "document": null,
          "page": null,
          "license": "CC-BY-4.0",
          "attribution": "Contains data from Google Patents Public Data by IFI CLAIMS Patent Services and Google, used under CC BY 4.0."
        },
        "relevance": {
          "score": 0.84,
          "semanticScore": 0.88,
          "textScore": null,
          "matchedFields": ["semantic"],
          "matchedViaFamilyMember": "US-11234567-B2"
        }
      }
    ],
    "coverage": {
      "corpus": "worldwide",
      "jurisdiction": null,
      "jurisdictions": ["CN", "EP"],
      "searchMode": "hybrid-semantic-text",
      "sources": [
        {
          "corpus": "google-patents-public-data",
          "jurisdiction": "*",
          "semanticUnit": "patent-family",
          "license": "CC-BY-4.0",
          "attribution": "Contains data from Google Patents Public Data by IFI CLAIMS Patent Services and Google, used under CC BY 4.0."
        }
      ],
      "limitations": ["Worldwide records cover publications from 2000 onward..."]
    }
  },
  "meta": { "requestId": "e5f6a7b8-c9d0-1234", "durationMs": 4210 }
}

Hybrid search groups worldwide results by patent family. You get one record per family, from an office you asked for. When the match was made on a family member from another office, relevance.matchedViaFamilyMember names that publication. Structured search returns individual publications without family deduplication.

What worldwide records contain. Outside the United States, records carry the title and an English abstract (machine-translated where the original is not English). Claims are available for US publications only, so feature mapping against other offices works from the title and abstract. Worldwide data refreshes quarterly, so the newest publications can lag by up to three months.

Attribution. Worldwide records are licensed CC BY 4.0. When you display or redistribute them, reproduce the record's source.attribution text.

If worldwide coverage is not enabled for the API, requests for other jurisdictions return 403 with JURISDICTION_NOT_AVAILABLE.


GET

/api/v1/patents/{'{publicationNumber}'}

Fetch a single patent record by publication number. Case and separators are normalized automatically — IN/2028/2005/A, in20282005a, and IN-2028-2005-A all resolve to the same document. A number without a kind code, such as US10123456, resolves to its granted publication when there is one. Worldwide publication numbers resolve where worldwide coverage is enabled.

Select lookup fields with ?fields=title,filingDate,grantDate. Identity (publicationNumber) and source attribution remain included. MCPget_patent accepts the same selection as a fields array.

Example request
curl "https://patentnest.ai/api/v1/patents/IN202211045678A" \
  -H "Authorization: Bearer pn_live_your_key"
Example response (abbreviated)
{
  "data": {
    "publicationNumber": "IN202211045678A",
    "applicationNumber": "202211045678",
    "kind": "A",
    "country": "IN",
    "title": "THERMAL MANAGEMENT SYSTEM FOR ELECTRIC VEHICLE BATTERY PACK",
    "abstract": "A battery thermal management system comprising...",
    "applicants": [
      { "name": "XYZ Technologies Pvt Ltd", "address": "Bengaluru, India", "sequence": 1 }
    ],
    "inventors": ["Rajesh Kumar", "Priya Sharma"],
    "classifications": ["H01M10/613", "H01M10/6568"],
    "filingDate": "2022-08-15",
    "publicationDate": "2023-02-17",
    "grantDate": null,
    "numberOfPages": 24,
    "numberOfClaims": 12,
    "extractionConfidence": 0.95,
    "source": {
      "name": "IP India Patent Journal",
      "document": "patent_journal_07_2023.pdf",
      "page": 142,
      "license": null,
      "attribution": null
    }
  },
  "meta": { "requestId": "b2c3d4e5-f6a7-8901", "durationMs": 48 }
}

Returns 404 with error code PATENT_NOT_FOUND if the number does not match any patent you have access to.


POST

/api/v1/analysis/features

AI analysis of a plain-English invention disclosure. Runs the same normalization stage as the PatentNest novelty pipeline and returns atomic technical features with per-feature detail, novelty-focus candidates, a search query built for patent retrieval, CPC/IPC classification hints, and confidence values.

This endpoint performs a full LLM analysis and typically responds in 10–30 seconds. Plan client timeouts accordingly. It draws on a separate daily analysis budget (see Rate limits).

Request body

FieldTypeRequiredDescription
titlestringNoInvention title, up to 300 characters.
descriptionstringYesPlain-English disclosure, 40–20,000 characters.
Example request
curl -X POST "https://patentnest.ai/api/v1/analysis/features" \
  -H "Authorization: Bearer pn_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Solar-powered cold-chain container",
    "description": "A shipping container with phase-change thermal storage panels charged by roof-mounted photovoltaic cells. A controller predicts door-opening events from a delivery schedule and pre-cools the buffer zone before each stop to hold the payload temperature within two degrees."
  }'
Example response (abbreviated)
{
  "data": {
    "features": [
      "phase-change thermal storage panels in a shipping container",
      "roof-mounted photovoltaic cells charging thermal storage",
      "controller that predicts door-opening events from delivery schedule",
      "pre-cooling of a buffer zone before each scheduled stop",
      "maintaining payload temperature within two-degree tolerance"
    ],
    "featureDetails": [
      {
        "feature": "phase-change thermal storage panels in a shipping container",
        "featureType": "core_technical",
        "disclosureSupport": "Directly stated: 'phase-change thermal storage panels'",
        "technicalRole": "Primary energy storage mechanism for cold-chain maintenance",
        "sourceExcerpt": "A shipping container with phase-change thermal storage panels",
        "confidence": 0.95
      }
    ],
    "noveltyFocus": [
      "controller that predicts door-opening events from delivery schedule",
      "pre-cooling of a buffer zone before each scheduled stop"
    ],
    "suggestedSearchQuery": "solar powered cold chain container phase change thermal storage photovoltaic predictive pre-cooling delivery schedule",
    "inventionTypes": ["apparatus", "system"],
    "classificationHints": {
      "cpc": ["F25D11/003", "B65D88/748", "H02S40/44"],
      "ipc": ["F25D11/00", "B65D88/74", "H02S40/44"]
    },
    "confidence": 0.88,
    "warnings": []
  },
  "meta": { "requestId": "c3d4e5f6-a7b8-9012", "durationMs": 14320 }
}

Feature types: core_technical (the technical mechanism), novelty_candidate (most likely to distinguish over prior art), implementation (how it is built), generic_weak (too broad to be distinctive). Use feature type and confidence to decide which features are worth mapping against prior art.

Suggested search query: retrieval-optimized phrasing built from the disclosure. Use it as the query parameter in the search endpoint. You can also use your own query — the suggestion is a strong starting point, not mandatory.


POST

/api/v1/analysis/feature-mapping

Element-wise novelty evidence. Each submitted feature is classified as present, partial, absent, or unknown against one patent record, with a verbatim quote and the field it came from (title, abstract, or claims).

Typical flow: extract features → search with the suggested query → map features against shortlisted publication numbers. This is the endpoint that produces the actual evidence for a novelty assessment.

Request body

FieldTypeRequiredDescription
featuresstring[]Yes1–12 features, each 3–300 characters.
publicationNumberstringYesPublication number of the patent to map against.
Example request
curl -X POST "https://patentnest.ai/api/v1/analysis/feature-mapping" \
  -H "Authorization: Bearer pn_live_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "features": [
      "phase-change thermal storage panels in a shipping container",
      "roof-mounted photovoltaic cells charging thermal storage",
      "controller that predicts door-opening events from delivery schedule"
    ],
    "publicationNumber": "IN202211045678A"
  }'
Example response (abbreviated)
{
  "data": {
    "publicationNumber": "IN202211045678A",
    "title": "THERMAL MANAGEMENT SYSTEM FOR ELECTRIC VEHICLE BATTERY PACK",
    "coverage": { "present": 1, "partial": 1, "absent": 1, "unknown": 0 },
    "featureFindings": [
      {
        "feature": "phase-change thermal storage panels in a shipping container",
        "status": "present",
        "evidence": {
          "quote": "a phase-change material encapsulated within thermally conductive panels arranged along the interior walls of the container",
          "field": "claims"
        },
        "confidence": 0.92,
        "reason": "Claim 1 describes phase-change thermal storage panels within a container structure."
      },
      {
        "feature": "roof-mounted photovoltaic cells charging thermal storage",
        "status": "partial",
        "evidence": {
          "quote": "an external energy source connected to the thermal regulation circuit",
          "field": "abstract"
        },
        "confidence": 0.65,
        "reason": "The patent mentions an external energy source but does not specify photovoltaic cells or roof mounting."
      },
      {
        "feature": "controller that predicts door-opening events from delivery schedule",
        "status": "absent",
        "evidence": null,
        "confidence": 0.88,
        "reason": "No mention of predictive control, door-opening events, or delivery schedule integration."
      }
    ],
    "evidenceBasis": { "title": true, "abstract": true, "claims": true },
    "qualityFlags": {
      "lowEvidence": false,
      "ambiguousAbstracts": false,
      "languageMismatch": false
    }
  },
  "meta": { "requestId": "d4e5f6a7-b8c9-0123", "durationMs": 18540 }
}

Evidence statuses: present means the feature is disclosed with a direct, attributable quote. partial means some elements match but others are missing or differ. absent means no evidence for the feature was found. unknown means the available text is insufficient to make a determination — treat it as an absence of evidence, not evidence of absence.

Quality flags: lowEvidence fires when fewer than two text fields were available. ambiguousAbstracts flags when the abstract is too vague to support reliable mapping. languageMismatch flags when the patent text and features appear to be in different languages.


MCP server for AI agents

POST /api/v1/mcp is a Model Context Protocol endpoint (streamable HTTP transport, JSON responses) exposing the same four operations as tools: search_patents, get_patent, extract_invention_features, and map_features_to_patent. Tool calls use the same bearer API keys and count against the same quotas as REST requests.

Compatible with Claude Desktop, Claude Code, Cursor, Windsurf, and any MCP-compatible client. Add this to your MCP configuration:

MCP configuration (Claude Desktop / Claude Code)
{
  "mcpServers": {
    "patentnest": {
      "type": "http",
      "url": "https://patentnest.ai/api/v1/mcp",
      "headers": {
        "Authorization": "Bearer pn_live_your_key"
      }
    }
  }
}

The server supports protocol versions 2025-06-18, 2025-03-26, and 2024-11-05. Sessions are stateless. tools/list returns the tool definitions with full JSON Schema input specifications.

Available tools

ToolDescription
search_patentsHybrid or structured search with filters, selected fields, and structured pagination/sorting. Same arguments as POST /api/v1/patents/search.
get_patentFetch one patent by publication number; optional fields array selects returned fields. Same as GET /api/v1/patents/{publicationNumber}.
extract_invention_featuresAI feature extraction from a disclosure. Same as POST /api/v1/analysis/features.
map_features_to_patentElement-wise evidence mapping. Same as POST /api/v1/analysis/feature-mapping.
MCP filtered-search tool call
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "search_patents",
    "arguments": {
      "mode": "structured",
      "filters": {
        "title": "battery",
        "filingDateFrom": "2020-01-01",
        "filingDateTo": "2025-12-31"
      },
      "fields": ["title", "filingDate", "grantDate"],
      "sort": "filingDateDesc",
      "limit": 25,
      "offset": 0
    }
  }
}

Suggested agent workflow: call extract_invention_features on a disclosure, use the suggestedSearchQuery with search_patents, then call map_features_to_patent against shortlisted publication numbers. All quotes are verbatim from the patent record; treat unknown statuses as insufficient evidence, not as proof of novelty.


Rate limits and quotas

Every response includes rate-limit headers. Exceeding any limit returns 429 with a Retry-After header (seconds).

HeaderDescription
RateLimit-LimitPer-minute request limit.
RateLimit-RemainingRequests remaining in the current minute.
RateLimit-ResetUnix timestamp when the minute window resets.
X-RateLimit-Daily-LimitDaily request limit.
X-RateLimit-Daily-RemainingRequests remaining today (UTC).
X-RateLimit-Monthly-LimitMonthly request limit.
X-RateLimit-Monthly-RemainingRequests remaining this month (UTC).
X-RateLimit-Analysis-LimitDaily AI analysis credit limit (analysis endpoints only).
X-RateLimit-Analysis-RemainingAnalysis credits remaining today.
X-Request-IDUnique request identifier. Include in support requests.

The two /api/v1/analysis endpoints draw on a separate daily analysis budget. An analysis credit is charged only when a validated request reaches the model, so requests rejected with 400 or 404 never cost a credit. When the analysis budget is exhausted, these endpoints return 429 with error code ANALYSIS_QUOTA_EXCEEDED; search and lookup remain available.

Default limits are per client. Contact us if you need higher throughput — limits are configurable per client.


Error responses

All errors return a JSON body with a stable code, a human-readable message, and a requestId. Use the code for programmatic handling; the message may change between versions.

Error response format
{
  "error": {
    "code": "INVALID_REQUEST",
    "message": "query must contain between 2 and 2,000 characters.",
    "requestId": "a1b2c3d4-e5f6-7890"
  }
}
HTTPCodeDescription
400INVALID_REQUESTMissing or invalid request parameters.
401INVALID_API_KEYMissing, malformed, or unrecognized API key.
401API_KEY_REVOKEDThe API key has been revoked.
401API_KEY_EXPIREDThe API key has expired.
403CLIENT_SUSPENDEDThe API client account is suspended.
403JURISDICTION_NOT_AVAILABLEThe requested jurisdictions are not enabled for this API.
404PATENT_NOT_FOUNDNo patent matched the publication number.
404UNKNOWN_TOOLMCP tool name not recognized.
413PAYLOAD_TOO_LARGERequest body exceeds 256 KB.
429RATE_LIMIT_EXCEEDEDPer-minute request limit exceeded.
429DAILY_LIMIT_EXCEEDEDDaily request limit exceeded.
429MONTHLY_LIMIT_EXCEEDEDMonthly request limit exceeded.
429ANALYSIS_QUOTA_EXCEEDEDDaily AI analysis credit limit exceeded.
503SERVICE_UNAVAILABLEThe patent API is not currently enabled.
503SEMANTIC_SEARCH_UNAVAILABLEVector search or embedding service is down.
503PATENT_SEARCH_UNAVAILABLEStructured search failed or exceeded its time budget. Retry with narrower filters.
503CORPUS_NOT_READYEmbedding coverage below minimum threshold.
503ANALYSIS_UNAVAILABLEAI analysis endpoints are not enabled.
500INTERNAL_ERRORUnexpected server error. Include requestId in support requests.

Patent record fields

The full public record includes the fields below. Use fields to request a subset. publicationNumber and source remain included. Hybrid results additionally contain relevance; structured results and direct lookups do not. Dates and other unavailable values can be null.

FieldTypeDescription
publicationNumberstringCanonical publication number (e.g. IN202211045678A, US-10123456-B2).
applicationNumberstring | nullRaw application number as filed.
kindstring | nullKind code (A, B, etc.).
countrystringTwo-letter patent office code (IN, US, EP, WO, ...).
familyIdstring | nullDOCDB patent family identifier, where known.
titlestringFull patent title.
abstractstring | nullPatent abstract text.
applicantsobject[]Array of { name, address, sequence }.
inventorsstring[]Inventor names as published.
classificationsstring[]IPC and CPC classification codes.
filingDatestring | nullISO 8601 date (YYYY-MM-DD), where available.
grantDatestring | nullExplicit grant date from stored IP India metadata (YYYY-MM-DD). Null when unavailable.
publicationDatestring | nullISO 8601 publication date.
numberOfPagesinteger | nullPage count of the patent document.
numberOfClaimsinteger | nullNumber of claims.
extractionConfidencenumber | nullMachine extraction confidence score (0–1).
source.namestringIP India Patent Journal, or Google Patents Public Data.
source.documentstring | nullOriginal Journal PDF filename (IP India records).
source.pageinteger | nullPage number in the source PDF (IP India records).
source.licensestring | nullLicence of the record data (CC-BY-4.0 for worldwide records).
source.attributionstring | nullAttribution to reproduce when displaying the record.
relevance.scorenumber | nullComposite relevance score (hybrid search only).
relevance.semanticScorenumber | nullSemantic similarity score (hybrid search only).
relevance.textScorenumber | nullText match score (hybrid search only).
relevance.matchedFieldsstring[]Fields that contributed to the match (hybrid search only).
relevance.matchedViaFamilyMemberstring | nullFamily member the match was made on, when not this record (hybrid search only).

Confidentiality

Submitted invention disclosures are processed to produce the API response and are not retained or used to train models. Request logs store request metadata (endpoint, status code, duration, query hashes) — never the disclosure text. Request bodies are capped at 256 KB.

API keys should be treated as secrets. Rotate keys if compromised — contact us or use the admin panel to revoke and reissue.


Quick start

  1. Request API access — we'll provision a client and send your key.
  2. Call POST /api/v1/analysis/features with your invention disclosure.
  3. Use the suggestedSearchQuery to call POST /api/v1/patents/search.
  4. Call POST /api/v1/analysis/feature-mapping for each shortlisted patent.
  5. Read the evidence: status, verbatim quote, source field, confidence.

The OpenAPI 3.1 spec can be imported into Postman, Swagger UI, or any code generator to scaffold client code automatically.