Documentation

REST API

24 endpoints over prior-art retrieval, patent space, and §112 claim analysis. JSON in, JSON out, one bearer token.

Base URL

https://mcp.antecedint.com/api/v1

No key yet? Sign in and one is issued immediately, or read the three-step start first. Examples below assume these two variables.

export BASE="https://mcp.antecedint.com/api/v1"
export ANTECEDINT_API_KEY="ak_live_..."

Sign in and your key is issued on the spot.

Sign in

All endpoints

The whole surface. Free endpoints cost nothing against your quota beyond the request itself.

EndpointDoesCost
POST /prior-artSearch 10.5M US patents for prior art against a claimMetered
POST /prior-art/claimsFetch claim text and abstracts for specific applicationsMetered
GET /patent-map/patent/:appNumPatent position and its nearest semantic neighboursMetered
GET /patent-map/patent/:appNum/citationsCited prior art resolved to patent-space positionsMetered
POST /patent-map/locateLocate free text or an application in patent spaceMetered
GET /patent-map/whitespaceRanked gaps in patent spaceFree
GET /patent-map/pointsSampled background point cloudMetered
POST /claim-validation/antecedent-basisCheck a draft claim set for antecedent-basis defectsFree
GET /claim-validation/antecedent-basis/:appNumCheck the filed claims of an applicationMetered
POST /claim-validation/supportMap claim terms to their specification supportMetered
GET /claim-validation/support/:appNumSupport map for a filed application and its parentsMetered
POST /warmupStart the inference hub ahead of a searchFree
GET /warmupWhether the inference hub is warmFree
GET /patent-intel/cpc/:codeCPC symbol with its art-unit distribution and childrenMetered
GET /patent-intel/classification/:numberCPC classification for a publication or application numberMetered
GET /patent-intel/art-unit/:artUnitArt-unit profile, statistics and examiner rosterMetered
GET /patent-intel/examinersSearch examiners by name or art unitMetered
GET /patent-intel/examiner/:examinerExaminer statistics and behavioural profileMetered
GET /guidance/mpep/:sectionIdOne MPEP section with its rules and required examiner actionsMetered
GET /guidance/epo/:sectionIdOne EPO Guidelines section with its rules and citationsMetered
GET /guidance/form-paragraph/:codeOne office-action form paragraph, with its statute and MPEP sectionMetered
GET /guidance/form-paragraphsForm paragraphs filtered by rejection type or MPEP sectionMetered
GET /guidance/graph/:nodeIdOne-hop cross-references into and out of a guidance sectionMetered
GET /guidance/design-code/:codeOne USPTO design search codeMetered

Patent space

Positions, neighbours, citations and gaps in one shared coordinate frame.

Patent position and its nearest semantic neighbours

MeteredCached MCP tool get_patent_neighborhood

One call frames a patent's neighbourhood, which is the payload behind the display-mode embed: { self, neighbors[], count }.

self is null when the application has no vector in the index, which happens for pre-corpus, design, and plant applications. The application can still be absent entirely, and that answers 404 rather than a null self.

Neighbour order is cosine similarity in the embedding space, not 3D distance. Semantically closest comes first; the coordinates are for laying them out, not for re-deriving the ranking. Distance in the projection and rank in the list disagree often enough that sorting by one and labelling it the other will mislead.

Path parameters

NameTypeDescription
appNum reqstring, ^\d{7,12}$US application number, digits only.

Query parameters

NameTypeDescription
topK integer, 1–100Number of neighbours to return. Defaults to 20.

Responses

200{ appNum, self, neighbors[], count, timestamp }. Each neighbour is a point plus score, the cosine similarity.
400VALIDATION_ERRORappNum is not 7-12 digits, or topK is outside 1-100.
404NOT_INDEXEDNo vector is indexed for this application.
502UPSTREAM_ERRORThe vector index could not be reached.
Request
curl -sS "$BASE/patent-map/patent/16123456?topK=5" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "appNum": "16123456",
  "self": {
    "appNum": "16123456",
    "x": 4.771,
    "y": -1.02,
    "z": 2.503,
    "section": "H",
    "artUnit": "1727",
    "filingDate": "2019-05-14"
  },
  "neighbors": [
    {
      "appNum": "16412088",
      "x": 4.802,
      "y": -1.114,
      "z": 2.397,
      "section": "H",
      "artUnit": "1725",
      "filingDate": "2019-08-02",
      "score": 0.9012
    }
  ],
  "count": 5,
  "timestamp": "2026-08-14T09:12:44.108Z"
}

Cited prior art resolved to patent-space positions

MeteredCached MCP tool get_patent_citations

The application's cited prior art, resolved to map positions. Each point carries examiner: true when the reference came from the examiner rather than from the applicant's IDS, which is the distinction that matters: examiner citations are what was actually applied against the application.

Examiner-cited references lead the list and are never dropped. Applicant citations fill the remainder up to 150 references total, so a 400-reference IDS cannot balloon the response.

Pass year, the citing application's filing year, when you know it. It narrows the underlying lookup and makes the call measurably cheaper.

References with no vector in the index are counted in notIndexed and omitted from points. Positions on this API are always exact index coordinates; nothing is placed approximately to fill a gap.

Path parameters

NameTypeDescription
appNum reqstring, ^\d{7,12}$US application number, digits only.

Query parameters

NameTypeDescription
year integer, 1970–2035Filing year of the citing application. Optional, and makes the lookup faster when supplied.

Responses

200{ appNum, points[], count, citedTotal, notIndexed, timestamp }. Each point carries examiner and title alongside the coordinates.
400VALIDATION_ERRORappNum is not 7-12 digits, or year is implausible.
502UPSTREAM_ERRORThe citation service or vector index could not be reached.
Request
curl -sS "$BASE/patent-map/patent/16123456/citations?year=2019" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.

Locate free text or an application in patent space

Metered MCP tool locate_in_patent_space

Semantic search into the space. Free text is embedded and matched against the index; given an appNum instead, the application's own abstract and first claim are joined as abstract [SEP] claim1 and used as the query, which reproduces the document representation Index-1 was built from and retrieves better than anything typed by hand.

Alongside the nearest patents it returns landing, a rank-weighted centroid of the top 8 hits. That is where the query sits in the space and the anchor a camera should fly to. It is not a patent and has no application number.

This is the one endpoint on the patent-map router that spends an embedding-hub encode per call, so it is the one that does not answer from cache.

Body

NameTypeDescription
query string, 8–4000 charsFree-text technical description. Supply either this or appNum; query wins when both are present.
appNum string, ^\d{7,12}$Locate an application by its stored vector. The application itself is excluded from neighbors.
topK integer, 1–100Number of nearest patents to return. Defaults to 20.

Responses

200{ landing: {x,y,z}, self?, neighbors[], count, located_by, timestamp }. located_by is stored_vector (the index holds the application: landing is its stored point, returned as self, and neighbour scores are against the document vector), re_encoded_text (it does not: the text was encoded as a query, scores top out near 0.87 and landing is a centroid; a note says so), or query_text.
400VALIDATION_ERRORNeither query nor appNum was supplied, or one of them failed its length or format rule.
404NOT_FOUNDNo text could be found for the application, or no indexed match carried map coordinates.
502UPSTREAM_ERRORThe embedding hub or vector index could not be reached.
503MAP_COORDINATES_UNAVAILABLEThe vector index this deployment is configured against does not store UMAP coordinates, so nothing can be placed in patent space. Prior-art search is unaffected.
Request
curl -sS "$BASE/patent-map/locate" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"query":"phase-change material for battery thermal management","topK":10}'
Load your key above to run this.
Response (abridged)
{
  "landing": { "x": 4.812, "y": -1.093, "z": 2.446 },
  "neighbors": [
    {
      "appNum": "16412088",
      "x": 4.771,
      "y": -1.02,
      "z": 2.503,
      "section": "H",
      "artUnit": "1727",
      "filingDate": "2019-05-14",
      "score": 0.8814
    }
  ],
  "count": 10,
  "timestamp": "2026-08-14T09:12:44.108Z"
}

Ranked gaps in patent space

FreeCached MCP tool find_whitespace

The analysed whitespace atlas: gaps in patent space, ranked by opportunity, descending. Built for the inventor-facing question of where the open ground is.

Each void carries an id, a position in the same coordinate frame as every other endpoint on this router, a radius, an opportunity score from 0 to 1, a CPC section, the bordering CPC codes with their fractions and titles, a temporal profile giving the median filing year of the surrounding art and a hot flag, a generated summary of what is missing there, the nearest bordering patents as exemplars, and the assignees active nearby.

The atlas is a precomputed artifact, rebuilt on its own schedule rather than on request, and cached for 30 minutes once loaded. Two calls a minute apart return the same voids.

Query parameters

NameTypeDescription
limit integer, 1–500Maximum voids to return. Defaults to 100.
section string, ^[A-HY]$Restrict to one CPC section letter.
minOpportunity number, 0–1Drop voids scoring below this. Defaults to 0.

Responses

200{ voids[], count, total, timestamp }. total counts everything matching the filters; count is how many limit allowed through.
400VALIDATION_ERRORlimit, section, or minOpportunity is out of range.
404NOT_FOUNDThe whitespace atlas has not been built.
502UPSTREAM_ERRORThe atlas could not be read from storage.
Request
curl -sS "$BASE/patent-map/whitespace?section=G&minOpportunity=0.6&limit=20" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.

Sampled background point cloud

MeteredCached

A sampled background cloud for context rendering, up to 50,000 points per request.

The sample pages the index in stored order. It is stable across calls, and it is not random: the first 10,000 points are the same 10,000 points every time, and they are not a representative sample of the corpus. Filter server-side with section and artUnit rather than over-fetching and filtering client-side, because the scan stops at a fixed budget regardless of how many points survive your filter.

That budget is roughly 150,000 scanned vectors. A filter narrow enough to exhaust it before collecting limit points returns what it found with truncated: true. Treat that flag as a signal to narrow differently rather than to retry, since the scan is deterministic and a retry returns the same partial sample.

Query parameters

NameTypeDescription
limit integer, 100–50000Points to return. Defaults to 10000.
section string, ^[A-HY]$Restrict to one CPC section letter.
artUnit string, ^\d{1,4}$Restrict to an art-unit prefix.

Responses

200{ points[], count, truncated, timestamp }
400VALIDATION_ERRORlimit, section, or artUnit is out of range.
502UPSTREAM_ERRORThe vector index could not be reached.
Request
curl -sS "$BASE/patent-map/points?limit=5000&section=H" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.

§112 claim validation

Antecedent basis and claim-term support, for drafts and for filed applications.

Check a draft claim set for antecedent-basis defects

Check a claim set for §112(b) antecedent-basis defects. Finds definite recitations ("the widget", "said widget") with no earlier indefinite recitation in the same claim or in a claim it depends from, plus double inclusions, plural and singular mismatches, and improper dependencies.

Implicit antecedent basis under MPEP 2173.05(e) is suppressed, so "the outer surface of the housing" is not flagged when the housing was properly introduced. Pass includeSuppressed to see what the suppression rules removed and which rule removed each one, which is how you audit the checker rather than trust it.

Findings are graded. high means no plausible antecedent exists anywhere in the set; low means one probably exists under different wording and a human should look.

Deterministic, no LLM, no network, and sub-millisecond per claim, so a draft editor can call it on every keystroke.

Body

NameTypeDescription
claims reqobject[], max 300The claim set, in order. Each entry is { number?, text }; a bare string is accepted in place of an object, and a missing number is filled from the array position.
claims[].text reqstring, 10+ charsClaim text without the leading number.
claims[].number integer, 1 and upClaim number.
minSeverity string, one of high, medium, lowLowest severity to report. Defaults to low.
includeSuppressed booleanAlso return the candidates the implicit-basis rules suppressed, each with the rule that killed it. Defaults to false.

Responses

200{ available: true, source: "request", issues[], claims[], dependencies[], stats }. issues[] is the flat list of every defect found; each entry of claims[] also carries its own issues[]. stats holds issueCount, bySeverity and byType. An empty issues[] means the claim set is clean, and is the only thing that means that.
400No claim in claims[] carried usable text, or minSeverity was not one of high, medium, low. The body is { error } with no code field. An unrecognised minSeverity is refused rather than defaulted, because silently returning the unfiltered list looks like a filtered one.
500The check itself failed.
Request
curl -sS "$BASE/claim-validation/antecedent-basis" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"claims":[{"number":1,"text":"A device comprising a housing."},
  {"number":2,"text":"The device of claim 1, wherein the lid is hinged."}]}'
Load your key above to run this.
Response (abridged)
{
  "available": true,
  "source": "request",
  "claims": [
    {
      "number": 2,
      "isIndependent": false,
      "dependsOn": [1],
      "introducedTerms": [],
      "issues": [
        {
          "claimNumber": 2,
          "term": "lid",
          "display": "the lid",
          "type": "no-antecedent-basis",
          "severity": "high",
          "start": 34,
          "end": 41,
          "snippet": "The device of claim 1, wherein the lid is hinged."
        }
      ]
    }
  ],
  "stats": {
    "claimCount": 2,
    "independentCount": 1,
    "issueCount": 1,
    "claimsWithIssues": 1,
    "bySeverity": { "high": 1, "medium": 0, "low": 0 },
    "byType": { "no-antecedent-basis": 1 }
  }
}

Check the filed claims of an application

MeteredCached MCP tool check_antecedent_basis

The same check as POST /antecedent-basis, run over the claims already on file for an application rather than over claims you supply.

An application whose claims are not in the warehouse answers 200 with { available: false, reason: "no-claims" }, not 404. The distinction is deliberate: the application exists and the request was well formed, we just have nothing to check. Branch on available before reading issues.

Path parameters

NameTypeDescription
appNum reqstring, ^\d{7,8}$US application number, digits only.

Query parameters

NameTypeDescription
minSeverity string, one of high, medium, lowLowest severity to report. Defaults to low.
includeSuppressed booleanSend 1 to include suppressed candidates with the rule that removed each.

Responses

200{ appNum, available: true, source: "warehouse", issues[], claims[], dependencies[], stats }, shaped exactly as the POST above, or { appNum, available: false, reason: "no-claims" } when nothing is on file.
400appNum is not a 7-8 digit US application number, or minSeverity was not one of high, medium, low.
502The claim pull from the warehouse failed.
Request
curl -sS "$BASE/claim-validation/antecedent-basis/16123456?minSeverity=high" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.

Map claim terms to their specification support

Metered MCP tool map_claim_support

Map every claim term to the specification passages that give it meaning, with exact locations: section, paragraph number, and character offsets.

Each term is graded by how the spec supports it, not merely whether the word appears. A term can be formally defined, defined by the claim itself, scoped by enumeration, mapped to an embodiment, characterized functionally, merely described, or UNDESCRIBED. That last grade is the §112(a) written-description signal worth acting on.

claims[] is always required on this endpoint. Use GET /support/:appNum when you want the filed claims analyzed instead of your own.

Supply sections and the analysis runs against your own specification text and touches no network, which is what makes this usable on an unfiled draft. Supply appNum without sections and the filed specification is pulled for you. Supplying appNum with includeParents walks the continuity chain and checks each parent specification too, so a term supported here but in no ancestor is surfaced as new matter that cannot claim the parent's filing date. The walk needs appNum; it cannot run on text alone.

Body

NameTypeDescription
claims reqobject[], max 300Claim set to analyze, each { number?, text }. Always required here; GET /support/:appNum uses the filed claims instead.
sections object[], max 60Specification sections to ground against, each { type?, name?, text }. Either this or appNum is required.
appNum string, ^\d{7,8}$US application number. Required for the continuity walk, and used to pull the spec when sections is omitted.
includeParents booleanWalk the continuity chain and check each parent specification. Ignored without appNum. Defaults to false.
maxAncestors integer, 0–12Cap on ancestors to check. Defaults to 6.
ocr booleanAllow OCR for image-only filings. Most provisionals are image-only, so the walk usually needs this to read them. Defaults to false.

Responses

200Per-term support grades with locations, plus the ancestor results when the continuity walk ran.
400claims[] was empty, or neither sections[] nor appNum was supplied.
500The analysis failed.
Request
curl -sS "$BASE/claim-validation/support" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"appNum":"16123456","includeParents":true,"ocr":true,
  "claims":[{"number":1,"text":"A battery pack comprising a phase-change layer."}]}'

This one spends real model inference on each call. Run it in the sandbox →

Support map for a filed application and its parents

MeteredCached MCP tool map_claim_support

The support map for an application already on file, using its filed claims and its filed specification. No claim text is supplied by the caller.

The continuity walk runs by default here, which is the opposite of POST /support. Send parents=0 to analyze the application's own specification alone. The walk is what makes this call slow and what makes it worth making: it is where new matter shows up.

OCR is opt-in with ocr=1 and is usually needed for the walk to be meaningful, because most provisionals are image-only scans with no extractable text layer. Without it an unreadable ancestor contributes nothing, and a term it actually supports can be reported as new matter. The flag is also killable server-side: when SPEC_OCR_DISABLED is set, ocr=1 is ignored rather than refused.

Path parameters

NameTypeDescription
appNum reqstring, ^\d{7,8}$US application number, digits only.

Query parameters

NameTypeDescription
parents booleanSend 0 to skip the continuity walk. Defaults to 1.
maxAncestors integer, 0–12Cap on ancestors to check. Defaults to 6.
ocr booleanSend 1 to allow OCR on image-only filings.

Responses

200Per-term support grades with locations, plus per-ancestor results and any new-matter findings when the continuity walk ran.
400appNum is not a 7-8 digit US application number.
502The specification pull or the analysis failed.
Request
curl -sS "$BASE/claim-validation/support/16123456?ocr=1&maxAncestors=4" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.

Warm-up

Start the inference hub before a search needs it, so the cold start is paid off the critical path.

Start the inference hub ahead of a search

FreeCached MCP tool warm_up

Start the inference hub before you need it.

The hub scales to zero, so the first search after an idle period pays ~71s of model loading. Call this a minute or two ahead and that cost is paid off the critical path; the search that follows runs at its warm latency of a few seconds.

The call returns immediately whether or not the hub is ready — it never blocks for the cold start. Poll GET /warmup to watch it become ready, or simply proceed and accept whatever state the hub is in.

Query parameters

NameTypeDescription
rerank booleanAlso load the reranker, which search_prior_art needs when useReranking is set. Adds ~25s to the warm-up and is unnecessary for retrieval alone. Defaults to false.
wait integerSeconds to wait for the models to finish loading before answering, up to 120. The default of 0 returns straight away and leaves the caller to poll. Set this and the call blocks until ready is true or the wait runs out, which is one round trip instead of a polling loop. Defaults to 0.

Responses

200{ ready, warming, models, estimatedReadySeconds, warmWindowSeconds }. ready true means a warm instance exists now; it is not a reservation.
502UPSTREAM_ERRORThe inference hub could not be reached at all.
Request
curl -sS -X POST "$BASE/warmup?rerank=true" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "ready": false,
  "warming": true,
  "models": { "encoder": false, "reranker": false },
  "estimatedReadySeconds": 100,
  "warmWindowSeconds": 900,
  "note": "Cloud Run routes each request independently, so a warm instance makes a fast search likely rather than guaranteed."
}

Whether the inference hub is warm

FreeCached

Whether the inference hub is warm right now.

Read-only: it reports state and starts nothing. Use it to poll after POST /warmup, or to decide whether a search is about to be fast before committing to it.

Responses

200{ ready, models, warmWindowSeconds }. ready reflects the encoder only; check models.reranker if the next call sets useReranking.
502UPSTREAM_ERRORThe inference hub could not be reached at all.
Request
curl -sS "$BASE/warmup" -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "ready": true,
  "models": { "encoder": true, "reranker": false },
  "warmWindowSeconds": 900
}

Prosecution intelligence

CPC scheme and empirical routing, art-unit behaviour, and examiner statistics.

CPC symbol with its art-unit distribution and children

MeteredCached MCP tool lookup_cpc_code

One CPC symbol, resolved three ways at once: what the scheme says it means, which art units actually examine it, and what sits under it.

The art-unit distribution is empirical rather than declared — it is where applications carrying this symbol were really routed, with the modal unit, the per-unit probabilities and the Shannon entropy of the spread. A low entropy means the symbol predicts the art unit; a high one means it does not, which is the more useful answer when deciding whether to argue classification.

children is capped by childLimit, because a subclass can carry thousands of subgroups and a caller asking about C11D wants to know that it has children, not to receive all of them. child_count always reports the true total. The art-unit distribution is capped the same way by distributionLimit: it is sorted by count, unique_art_units is the true total, and a symbol examined by 222 units does not need all 222 listed to show that one of them takes 37%.

Path parameters

NameTypeDescription
code reqstring, ^[A-HY][0-9A-Z/]{0,18}$CPC symbol, e.g. C11D or C11D7/261.

Query parameters

NameTypeDescription
childLimit integer, 0–500How many child symbols to return. Defaults to 50.
distributionLimit integer, 0–500How many art units to list in art_units.distribution, largest first. Defaults to 20.

Responses

200{ code, scheme, art_units, children[], child_count }. scheme is null for a symbol with routing data but no scheme entry; art_units is null for a symbol nothing has been routed under.
400VALIDATION_ERRORcode is not a CPC symbol, or a limit is outside 0-500.
404NOT_FOUNDNeither the scheme nor the routing data knows this symbol.
503CORPUS_UNAVAILABLEThe corpus database is not configured or not reachable.
Request
curl -sS "$BASE/patent-intel/cpc/C11D?childLimit=5" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "code": "C11D",
  "scheme": {
    "code": "C11D",
    "title": "DETERGENT COMPOSITIONS",
    "level": "subclass",
    "parent": "C11"
  },
  "art_units": {
    "level": "subclass",
    "total_count": 14476,
    "unique_art_units": 222,
    "top_art_unit": "1761",
    "top_art_unit_probability": 0.3689,
    "entropy": 4.3798,
    "distribution": [
      { "au": "1761", "count": 5227, "probability": 0.36893 }
    ]
  },
  "children": [
    { "code": "C11D1/00", "title": "Detergent compositions", "level": "group" }
  ],
  "child_count": 132
}

CPC classification for a publication or application number

MeteredCached MCP tool get_patent_classification

The CPC assignment on one published application or granted patent, as the USPTO Master Classification File records it.

The number is tried as a publication number first and an application number second, so a caller holding either can ask without saying which it has. The main symbol is resolved against the scheme, so the answer carries a title and not only a code.

inventive_cpcs are the symbols covering what is claimed; additional_cpcs cover subject matter disclosed but not claimed. Callers building a search from this usually want the inventive set alone.

Path parameters

NameTypeDescription
number reqstring, ^\d{7,12}$Publication or US application number, digits only.

Responses

200{ publication_number, application_number, main_cpc, main_cpc_title, inventive_cpcs[], additional_cpcs[], ... }.
400VALIDATION_ERRORnumber is not 7-12 digits.
404NOT_FOUNDNo classification record for this number.
503CORPUS_UNAVAILABLEThe corpus database is not configured or not reachable.
Request
curl -sS "$BASE/patent-intel/classification/20010000001" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "publication_number": "20010000001",
  "application_number": "09725796",
  "kind_code": "A1",
  "main_cpc": "C11D7/261",
  "main_cpc_title": "Organic compounds containing oxygen",
  "inventive_cpcs": ["C11D7/261", "C11D7/24"],
  "additional_cpcs": ["C11D7/267", "C11D7/28"]
}

Art-unit profile, statistics and examiner roster

MeteredCached MCP tool get_art_unit_profile

One art unit: what it examines and how it behaves.

Assembled from the four collections that describe a unit — the statistics, the descriptive record, the generated enrichment and the examiner roster — so a caller makes one request rather than four.

statistics carries allowance and rejection behaviour, timing, interview receptiveness, RCE tolerance and estimated cost, averaged across the unit's examiners. Read statistics.data_quality before relying on any of it: it reports how many applications and office actions the averages rest on, and the volume, recency and completeness scores behind them. Units with thin data carry the same field names and much weaker numbers.

The roster's application numbers are not returned. One unit carries tens of thousands of them, which is most of a 209 KB document and no use in a profile. The model-written description is not returned whole either: on 1725 it was 9,887 characters, 56% of the response, and it filed "bibs for hairdressers' rooms" under a materials unit. generated_context says the same in a paragraph, so description is served as its opening and its length.

examiner_count is the length of the roster served. Where the stored statistics counted a different roster (1725 lists 28 examiners against a stored 27), the stored figure appears as examiner_count_in_statistics so the disagreement is visible rather than resolved silently.

Path parameters

NameTypeDescription
artUnit reqstring, ^\d{3,4}$USPTO art unit, e.g. 2872.

Responses

200{ art_unit, technology_center, title, generated_context, description, keywords[], cpc_codes, examiners[], examiner_count, statistics }. cpc_codes summarises rather than lists: a total, counts by CPC section, and the 25 commonest subclasses. The raw list runs to 24,135 symbols for a single unit and two unrelated units share 57% of it, so it described the corpus more than the unit and made this response 383 KB. statistics is null for a unit that has a descriptive record but no computed statistics; inside it, claims_analysis.independentClaimsStats.avgIndependentClaims is null with a note where the stored value tracked the total claim count.
400VALIDATION_ERRORartUnit is not 3-4 digits.
404NOT_FOUNDNo collection holds this art unit.
503CORPUS_UNAVAILABLEThe corpus database is not configured or not reachable.
Request
curl -sS "$BASE/patent-intel/art-unit/2872" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "art_unit": "2872",
  "technology_center": "2800",
  "title": "Optics: Measuring and Testing",
  "examiner_count": 63,
  "cpc_codes": ["G01B", "G02B"],
  "examiners": ["GREY CHRISTOPHER P", "YOUNG HUGH P"],
  "statistics": {
    "portfolio": { "total_ctnf_issued_avg": 902.86 },
    "interview_metrics": { "interview_success_rate": 65.89 },
    "data_quality": {
      "total_applications_analyzed": 53392,
      "office_actions_analyzed": 132188,
      "completeness_score": 5.54
    }
  }
}

Search examiners by name or art unit

MeteredCached MCP tool find_examiner

Find examiners by surname or art unit.

Matching is anchored: an exact surname, or a prefix of the full name in the USPTO's surname-first form. An unanchored substring search would be a regex over 10,308 documents averaging a megabyte each, which is a collection scan reading 11 GB to answer a lookup. Callers wanting a specific examiner should pass the surname and filter the result.

Query parameters

NameTypeDescription
name string, 2–80 charsSurname, or a prefix of the surname-first full name.
artUnit string, ^\d{3,4}$Restrict to one art unit.
limit integer, 1–100Maximum matches to return. Defaults to 20.

Responses

200{ count, examiners[] }, each { examiner_id, full_name, art_unit, technology_center }. Empty when neither name nor artUnit is given.
400VALIDATION_ERRORA parameter failed validation.
503CORPUS_UNAVAILABLEThe corpus database is not configured or not reachable.
Request
curl -sS "$BASE/patent-intel/examiners?name=SMITH&artUnit=1609" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "count": 1,
  "examiners": [
    {
      "examiner_id": "68a73eaad7496de7109778b7",
      "full_name": "SMITH ADAM M",
      "art_unit": "1609",
      "technology_center": "Technology Center 1600"
    }
  ]
}

Examiner statistics and behavioural profile

MeteredCached MCP tool get_examiner_profile

One examiner's statistics, by examiner id or by USPTO surname-first name.

Both forms are accepted because a caller reading an office action has the name and a caller following an art-unit roster has the id.

The response carries rejection analytics, portfolio counts, interview and RCE behaviour, timing, cost analysis and percentile rankings against the unit and the corps, plus claim_interpretation where a model-written read of how this examiner construes claims exists — it does for 11 examiners, and is null for the rest rather than absent.

Six sections are withheld by default and named in sections_available. Two are cold: behavioral_patterns and rejection_analysis hold per-application detail and are together 10.6 GB of the 11.1 GB collection, the largest single document being 14.2 MB. Four are hot but wide: applications_with_interviews and applications_with_rcex are per-application lists (hundreds of rows each), by_sequence_length and document_code_breakdown are histograms with hundreds of keys. Together they were 83% of a default response. Each is replaced by its count and the include name that brings it back; document_code_breakdown keeps its ten largest codes.

data_quality reports what the numbers rest on, and says what was withheld or relabelled. populations names the five denominators that appear in one response (all applications, analysed, with documents, with office actions, with a filing date). volume.tier replaces an upstream score that was 5 for every examiner. withheld[] lists fields removed because their values were wrong and not recoverable, with what was observed; notes[] lists sections served as null because they were never computed (percentile_rankings, claims_analysis on every examiner sampled), and pairs of fields that disagree.

Path parameters

NameTypeDescription
examiner reqstring, 2–120 charsExaminer id, or USPTO surname-first full name.

Query parameters

NameTypeDescription
include stringComma-separated sections to add: behavioral_patterns, rejection_analysis (cold; megabytes), applications_with_interviews, applications_with_rcex, by_sequence_length, document_code_breakdown (hot; thousands of tokens). Unknown names are ignored.

Responses

200{ examiner_id, full_name, art_unit, technology_center, portfolio, rejection_analytics, interview_metrics, rcex_metrics, timeline_metrics, strategic_insights, data_quality, claim_interpretation, sections_available[], sections_included[], ... }. percentile_rankings and claims_analysis are null where never computed.
400VALIDATION_ERRORexaminer is shorter than 2 characters or longer than 120.
404NOT_FOUNDNo examiner with this id or name.
503CORPUS_UNAVAILABLEThe corpus database is not configured or not reachable.
Request
curl -sS "$BASE/patent-intel/examiner/SMITH%20ADAM%20M" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "examiner_id": "68a883c3d8cb3a33568ff86d",
  "full_name": "HASAN MOHAMMED A",
  "art_unit": "2872",
  "technology_center": "2800",
  "portfolio": { "total_office_actions_issued": 6280 },
  "percentile_rankings": null,
  "data_quality": {
    "total_applications_analyzed": 2711,
    "office_actions_analyzed": 6280,
    "populations": { "total_applications": 2711, "analysed": 2711, "with_documents": 2707, "with_office_actions": 2605, "with_filing_date": 2490, "three_year_cohort": 187 },
    "volume": { "applications_analyzed": 2711, "tier": "large" },
    "notes": ["percentile_rankings: not computed for this examiner (all three ranking tables were empty upstream)."]
  },
  "claim_interpretation": null,
  "sections_available": ["behavioral_patterns", "rejection_analysis", "applications_with_interviews", "applications_with_rcex", "by_sequence_length", "document_code_breakdown"],
  "sections_included": []
}

Examination guidance

The MPEP and the EPO Guidelines, the graph of how their sections cite each other, and the form paragraphs the USPTO pastes into office actions.

One MPEP section with its rules and required examiner actions

MeteredCached MCP tool get_mpep_section

One MPEP section, as an examiner is required to apply it.

Beyond the section text, each record carries keyRules and examinerActions: what the section obliges, separated from the prose that obliges it. That is usually what a caller holding a rejection actually wants, since the argument is about whether the examiner did what the section required.

Section ids carry dots and parentheses and the punctuation is part of the key, so 601.01(c) is passed through exactly as written.

Path parameters

NameTypeDescription
sectionId reqstring, ^[0-9A-Za-z.()\-]{1,40}$MPEP section id, e.g. 2106 or 601.01(c). Dots and parentheses are part of the id.

Responses

200The section, with content, keyRules, examinerActions, legalReferences, technologyDomains and enrichedSummary.
400VALIDATION_ERRORsectionId is not a well-formed MPEP section id.
404NOT_FOUNDNo MPEP section carries that id.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/mpep/2106" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "sectionId": "2106",
  "title": "Patent Subject Matter Eligibility",
  "chapter": "2100",
  "topicCategory": "patentability",
  "keyRules": ["elided"],
  "examinerActions": ["elided"],
  "legalReferences": ["35 U.S.C. 101"]
}

One EPO Guidelines section with its rules and citations

MeteredCached MCP tool get_epo_guideline

One section of the EPO Guidelines for Examination.

Deliberately the same shape as the MPEP route, because the flow that reaches it is the same flow one step later: an applicant with a US rejection usually has a European family member, and an agent that learned one lookup should not have to learn a second.

These records were merged from two source collections that each held half of each section, so a complete document carries both the generated half (keyRules, examinerActions) and the source half (citations, sourceUrl, parentSection, childSections).

Path parameters

NameTypeDescription
sectionId reqstring, ^[0-9A-Za-z.\-]{1,40}$EPO Guidelines section id, e.g. c-iv-2 or g-ii-3.3.

Responses

200The section, with content, keyRules, examinerActions, citations, parentSection, childSections and sourceUrl.
400VALIDATION_ERRORsectionId is not a well-formed EPO section id.
404NOT_FOUNDNo EPO section carries that id.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/epo/g-ii-3.3" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "sectionId": "g-ii-3.3",
  "title": "Programs for computers",
  "part": "G",
  "chapter": "II",
  "keyRules": ["elided"],
  "citations": ["elided"],
  "sourceUrl": "https://www.epo.org/en/legal/guidelines-epc"
}

One office-action form paragraph, with its statute and MPEP section

MeteredCached MCP tool get_form_paragraph

The literal paragraph an examiner pasted into an office action.

This is the sharpest thing in the dataset. A caller holding a rejection has a paragraph number and nothing else, and this turns it into the statute behind it, the MPEP section it rests on, the rejection type it belongs to, and the notes the examiner was given about when to use it. brackets lists the placeholders the examiner had to fill, which is often where the substance of a rejection actually sits.

isAIA and preAIAEquivalent matter for anything filed near the changeover: citing the wrong one is citing law that does not apply to the application.

The paragraph symbol is stripped, so a code copied straight out of a PDF as ¶ 6.11 resolves rather than returning a 404 that reads as "no such paragraph".

Path parameters

NameTypeDescription
code reqstring, ^[¶\s0-9A-Za-z.\-]{1,24}$Form paragraph code, e.g. 6.11 or 7.37.01. A leading is accepted and ignored.

Responses

200The paragraph: title (its heading), template (the text as pasted, placeholders as [1], [2]), brackets, statute, statuteShort, rejectionType, category, isAIA, preAIAEquivalent, mpepSection, examinerNotes, mustFollow (paragraphs that have to appear before this one) and relatedParagraphs. truncated_at_source: true means the stored text ends before the paragraph does; quote it as partial. statute and rejectionType are each null on a majority of rows, and on different rows.
400VALIDATION_ERRORcode is not a well-formed form paragraph code.
404NOT_FOUNDNo form paragraph carries that code.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/form-paragraph/7.34.10" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "code": "7.34.10",
  "title": "Indefinite Claim Language: “Such As”",
  "template": "Regarding claim [1], the phrase “such as” renders the claim indefinite because it is unclear whether the limitations following the phrase are part of the claimed invention. See MPEP § 2173.05(d).",
  "statute": null,
  "rejectionType": "indefiniteness",
  "mpepSection": "2175",
  "examinerNotes": "Examiner Note: This form paragraph must be preceded by form paragraph 7.34.01.",
  "mustFollow": ["7.34.01"]
}

Form paragraphs filtered by rejection type or MPEP section

MeteredCached MCP tool find_form_paragraphs

Every form paragraph an examiner could have reached for.

Given a rejection type, this is the set the examiner chose from, which is what an agent needs to tell "they picked the narrow one" from "this was the only option". Filtering by mpepSection answers the reverse: which paragraphs rest on a section you are already arguing about.

At least one filter is required. An unfiltered call would page through everything to no purpose, so the caller has to say which axis they are on rather than receive the whole table by default.

rejectionType takes either of the two vocabularies the corpus holds. The stored label is a word (obviousness, indefiniteness, means_plus_function) and the stored statute is a citation (35 U.S.C. 103(a), 37 CFR 1.52); each is null on a majority of rows, and on different rows. A query on either is expanded to both, so 112(b) reaches the paragraphs labelled indefiniteness as well as the ones citing the statute, and indefiniteness reaches the same set. filter.matched shows the expansion.

Query parameters

NameTypeDescription
rejectionType string, ^[0-9A-Za-z.()_ \-]{1,40}$A statute (102, 103, 112(b), 101, 121, or a CFR rule such as 1.52) or a label (obviousness, anticipation, indefiniteness, enablement, written_description, means_plus_function, abstract_idea, double_patenting, restriction, allowance, drawing_objection). Required unless mpepSection is given.
mpepSection string, ^[0-9A-Za-z.()\-]{1,40}$MPEP section the paragraph rests on, e.g. 706, 707, 2175. Required unless rejectionType is given.
limit integer, 1–100How many paragraphs to return. Defaults to 25.

Responses

200{ results[], count, filter }. filter echoes what was applied and filter.matched what rejectionType expanded to; an unrecognised value returns zero with filter.note listing the vocabulary.
400VALIDATION_ERRORNeither filter was supplied, or one was malformed.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/form-paragraphs?rejectionType=112(b)&limit=5" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "results": ["one form paragraph per entry; elided here"],
  "count": 5,
  "filter": {
    "rejectionType": "112(b)",
    "matched": { "rejectionType": ["indefiniteness"], "statute": "35 U.S.C. 112(b)" }
  }
}

One-hop cross-references into and out of a guidance section

MeteredCached MCP tool get_guidance_graph

What a guidance section points at, and what points at it.

One hop, both directions, because they answer different questions. Forward is what else this rule depends on. Backward is what breaks if you misread it, and it is the direction that is hard to get any other way.

Which graph is read off the node id rather than passed separately: ids are mpep-601.01(c) and epo-c-ix-3, so the prefix routes the query. An id with neither prefix is a 404 rather than a guess, because answering an EPO question with US law is worse than answering nothing.

A hub section is cited by hundreds of others, so the fan-out is capped and truncated says which direction hit the cap. A caller seeing exactly limit edges cannot otherwise tell a hub from a coincidence.

Path parameters

NameTypeDescription
nodeId reqstring, ^(mpep|epo)-[0-9A-Za-z.()\-]{1,40}$Graph node id. The prefix selects the corpus: mpep-2106, epo-c-ix-3.

Query parameters

NameTypeDescription
limit integer, 1–200Maximum edges per direction. Defaults to 50.

Responses

200{ node, corpus, outgoing[], incoming[], truncated, limit }. Each edge is { source, target, weight, type, bidirectional }.
400VALIDATION_ERRORnodeId carries no recognised prefix, or limit is outside 1-200.
404NOT_FOUNDNo graph node carries that id.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/graph/mpep-2106?limit=10" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "node": { "nodeId": "mpep-2106", "inDegree": 214, "outDegree": 63, "isHub": true },
  "corpus": "mpep",
  "outgoing": [{ "source": "mpep-2106", "target": "mpep-2106.04", "weight": 8, "type": "cites" }],
  "incoming": [{ "source": "mpep-2103", "target": "mpep-2106", "weight": 5, "type": "cites" }],
  "truncated": { "outgoing": false, "incoming": true },
  "limit": 10
}

One USPTO design search code

MeteredCached MCP tool get_design_code

One USPTO design search code.

A classification scheme rather than guidance. It sits in this namespace because it travelled with the same passover, not because it belongs beside the MPEP, and it is documented that way rather than filed somewhere tidier that would imply a relationship these records do not have.

Path parameters

NameTypeDescription
code reqstring, ^[0-9]{2}(\.[0-9]{2}){0,3}$Design search code, e.g. 03.19.17.

Responses

200The code, with descriptions[] (every phrasing the USPTO files it under), major and sub.
400VALIDATION_ERRORcode is not a design search code.
404NOT_FOUNDNo design code carries that value.
503CORPUS_UNAVAILABLEThe guidance dataset is not configured or not reachable.
Request
curl -sS "$BASE/guidance/design-code/03.19.17" \
  -H "Authorization: Bearer $ANTECEDINT_API_KEY"
Load your key above to run this.
Response (abridged)
{
  "code": "03.19.17",
  "descriptions": ["Fish symbol used for religious significance", "Ichthys"],
  "major": "03",
  "sub": "03.19"
}

Errors and quotas

Authentication and quota failures happen before a route runs, so they look the same whichever endpoint you called.

StatusCodeCause
401MISSING_API_KEYNo Authorization header.
401INVALID_AUTH_FORMATThe header is not of the form "Bearer <key>".
401KEY_NOT_FOUNDThe key does not exist, is suspended, or is revoked.
401API_KEY_EXPIREDThe key is past its expiry date.
403IP_NOT_WHITELISTEDThe key has an IP allowlist and the request came from outside it.
429USAGE_LIMIT_EXCEEDEDOver the daily or monthly quota. The body reports the limit it enforced and when it resets.
500AUTH_SYSTEM_ERRORKey validation itself failed. Retry.
503The instance is draining for a deploy. Retry.

Quotas default to 1,000 requests a day and 30,000 a month, set per key when it is issued, and counted per key rather than per IP. Two services sharing a key share its budget.

One inconsistency worth knowing

Two envelopes are in use. Prior-art search answers { success, data } and its errors carry no code field. Patent-space and claim-validation routes answer the payload directly; patent-space errors carry a code, claim-validation errors do not.

Branch on the HTTP status rather than on the presence of a field, and treat code as absent unless the table for that endpoint lists one. We would rather say this than pretend the surface is more uniform than it is.