# Flowleap Uspto

> Search USPTO Open Data Portal records with Lucene queries you write yourself, fetch granted patents, applications, continuity chains, and file-wrapper data (prosecution transactions, assignments, foreign priority, PTA, attorney of record), and list IFW documents and read office actions as OCR-extracted text. Trigger when an agent needs US application/prosecution metadata, grant lookups, continuity (parent/child) chains, office-action text, chain of title, or USPTO-specific searches.

- Skill: `flowleap-ai/flowleap-uspto` (Agent Skill)
- Install (CLI): `npx skillmds@latest add flowleap-ai/flowleap-uspto`
- Raw SKILL.md: https://api.skillmd.com/api/skills/flowleap-ai/flowleap-uspto/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: flowleap-ai (https://skillmd.com/u/flowleap-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/flowleap-ai/flowleap-uspto

---


# FlowLeap USPTO (Open Data Portal)

Auth and global flags: see `flowleap-shared`.

## Search

`uspto search` runs the `search_patents` tool (`provider: uspto`) on the Tools
facade — the single agent surface for patent data. ODP uses Lucene syntax over
application metadata (get the grammar via
`flowleap --json tools run get_search_syntax provider=uspto`):

```bash
flowleap --json uspto search --query 'applicationMetaData.inventionTitle:"machine learning"' --limit 5
```

The JSON payload is `{ count, patentFileWrapperDataBag }` — `count` is the
total ODP matched, the bag holds the returned records.

**ODP is title + metadata only — there is no abstract/claims full-text.** The
only free-text field is `applicationMetaData.inventionTitle`. A distinguishing
feature that lives in the abstract (e.g. "UV-C sterilization" on an earbud
charging case titled only "CHARGING CASE FOR EARBUDS") cannot be matched, so
never AND an abstract-only qualifier onto an ODP search. For a recall pass,
search the **core device noun** in the title (with singular/plural variants)
and triage abstracts afterwards with `flowleap ops abstract <number>`:

```bash
flowleap --json uspto search --query 'applicationMetaData.inventionTitle:earbuds AND applicationMetaData.inventionTitle:"charging case"' --limit 25
```

**Zero-recall fallback.** If a search returns nothing, the CLI does not hand
back a silent empty set: when the query carries a `cpcClassificationBag:`
constraint it strips that filter and retries once (a mis-guessed CPC class is a
common cause of zero recall), then, if still empty, prints guidance to broaden
to a title search. Watch stderr for these notes.

**Zero recall is not a key gate.** An empty result set, a truncated payload, or
a 5xx keeps the normal recovery path above. The US office is gated only when a
command you actually ran returned an explicit gate **code** — the CLI's
`providerKeysHint.code` (`provider_keys_required` / `provider_keys_invalid` /
`trial_budget_exhausted`), raised from the backend codes `data_keys_required`,
`patent_provider_key_invalid`, `trial_data_budget_exhausted` (each carrying
`provider: "uspto"`) or `odp_api_key_missing`. Match the code, never the message text: backend wording
is freely editable, so a reword can neither invent nor erase a gate. A gate is a
user-action stop: do not substitute web-scraped US data for it, deliver the
other office's results in full, name the gap as a missing-key gap, and ask for
the free key at the end. See `flowleap-keys`.

## Search with a full request body

`uspto search` accepts a complete ODP request body via `--body` (inline JSON,
or `-` for stdin) or `--body-file` — use this when you need `fields` or
`enrich` alongside the query. `--query` and `--body`/`--body-file` are
mutually exclusive.

The body is translated onto the tool's snake_case parameters (`q` → `query`,
`rangeFilters` → `range_filters`, `pagination` flattened to `limit`/`offset`)
and every other field is forwarded verbatim — the tool schema is the only
validator, so a field a newer backend understands is never dropped by an older
CLI. An unknown field comes back as `INVALID_INPUT` with an `issues[]` list,
which tells you the name is wrong; it is not a CLI limitation.

```bash
flowleap --json uspto search --body '{"q":"applicationMetaData.inventionTitle:\"machine learning\"","pagination":{"limit":5}}'
flowleap --json uspto search --body-file query.json
```

## Writing the Lucene query — you write it yourself

There is no server-side query builder. The method from `flowleap-patent`
applies unchanged — ODP differs from CQL in syntax, not in strategy:

1. **Extract the candidate terms first** (list every specific noun phrase;
   justify every omission).
2. **Write the query with at least one discriminating term** — the specific
   subject matter, never just the technology area, and never a CPC class on
   its own. Remember ODP is title + metadata only: the discrimination must be
   a term that plausibly appears in an invention title.
   - Fielded terms: `applicationMetaData.inventionTitle:"charging case"`
   - Boolean `AND`/`OR`/`NOT`, parentheses for grouping, phrases in
     `"double quotes"`
   - The full field grammar comes from
     `flowleap --json tools run get_search_syntax provider=uspto` — read
     field names from it rather than recalling them
3. **Probe the count before trusting any results.** Use `--count-only` (it
   asks ODP for one record and reads the total match count):

```bash
flowleap --json uspto search --query 'applicationMetaData.inventionTitle:"charging case"' --count-only
```

The JSON payload is `{ query, count }`. (Equivalent raw-tool probe:
`flowleap --json tools run search_patents provider=uspto query='…' limit=1`.)

Over ~1,000 hits: add the next discriminating term from your extraction list.
Under 10: broaden — synonyms, singular/plural title variants, drop a filter.
To verify a CPC class before constraining on one, query the official scheme —
`flowleap-patent` has the `flowleap patstat query` recipe; never guess codes.

## Lookups

```bash
flowleap --json uspto grant 11800000              # granted patent by number
flowleap --json uspto application 16123456        # application by number
flowleap --json uspto continuity 16123456         # parent/child chain
```

Tools-facade equivalents: `get_us_grant` (`patent_number=`),
`get_us_application` and `get_continuity` (both `application_number=`). A number
ODP has never ingested answers `patent_not_found` or `application_not_found` —
a real absence, not a transport failure, so do not retry it.

## File wrapper

Targeted projections of the application record — each returns one bag without
the full wrapper:

```bash
flowleap --json uspto transactions 14412875       # prosecution events (filings, OAs, fees)
flowleap --json uspto assignments 14412875        # chain of title (reel/frame, assignees)
flowleap --json uspto foreign-priority 14412875   # foreign priority claims
flowleap --json uspto adjustment 14412875         # official PTA day counts
flowleap --json uspto attorney 14412875           # attorney/agent of record, customer number
```

Tools-facade equivalents: `get_transactions`, `get_assignments`,
`get_foreign_priority`, `get_patent_term_adjustment`, `get_attorney` (all take
`application_number=`).

## Read office actions (IFW documents + OCR)

List the Image File Wrapper documents, then fetch any of them as markdown text.
The backend downloads the PDF from USPTO and OCRs it server-side (most IFW
documents are scanned images with no text layer) — no manual PDF handling.

```bash
# List all documents; filter to office actions by document code
flowleap --json uspto documents 14412875 --code CTNF      # non-final rejections
flowleap --json uspto documents 14412875 --code CTFR      # final rejections
flowleap --json uspto documents 14412875 --direction incoming  # applicant filings

# Read one document as markdown (documentIdentifier from the listing)
flowleap uspto document-text 14412875 K5FCIIKNRXEAPX5 > final-rejection.md
```

Common document codes: `CTNF` non-final rejection, `CTFR` final rejection,
`NOA` notice of allowance, `CLM` claims, `REM` applicant remarks/arguments.
Human/table output prints the markdown itself on stdout (metadata goes to
stderr), so `document-text` pipes cleanly; `--json` wraps it in
`{ pageCount, markdown, model, cached }`.

The listing is filtered server-side and returned compacted —
`{ applicationNumber, total, returned, documents }`, each record keeping its
`downloadOptionBag` alongside a derived `pageCount`.

First read of a long document can take tens of seconds (download + OCR);
results are cached server-side for 7 days. Check `pageCount` in the listing
before pulling very long documents.

Tools-facade equivalents: `get_application_documents`
(`application_number=`, optional `document_code=`/`direction=`) and
`read_application_document` (`application_number=`, `document_id=`).

