Skip to content

patent-dev/uspto-odp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

USPTO Open Data Portal (ODP) Go Client

Go Reference License: MIT

A complete Go client library for the USPTO Open Data Portal API, Office Action APIs, and TSDR (Trademark Status & Document Retrieval).

Getting Started

API Keys

ODP API Key (Patent, PTAB, Petition, Bulk Data, Office Action):

TSDR API Key (Trademark Status & Document Retrieval):

Installation

go get github.com/patent-dev/uspto-odp

Quick Start

config := odp.DefaultConfig()
config.APIKey = "your-api-key"
client, err := odp.NewClient(config)
ctx := context.Background()

results, err := client.SearchPatents(ctx, "artificial intelligence", 0, 10)
fmt.Printf("Found %d patents\n", *results.Count)

API Methods - Complete Coverage (53 wrapper methods)

All USPTO ODP API endpoints are fully implemented and tested, plus Office Action and TSDR APIs.

Patent Application API (13 endpoints)

// Core Patent Data
SearchPatents(ctx, query string, offset, limit int32) (*PatentDataResponse, error)
GetPatent(ctx, patentNumber string) (*PatentDataResponse, error)  // Accepts any patent number format
GetPatentMetaData(ctx, applicationNumber string) (interface{}, error)

// Patent Details
GetPatentAdjustment(ctx, applicationNumber string) (*AdjustmentResponse, error)
GetPatentContinuity(ctx, applicationNumber string) (*ContinuityResponse, error)
GetPatentDocuments(ctx, applicationNumber string) (*DocumentBag, error)
GetPatentAssignment(ctx, applicationNumber string) (*AssignmentResponse, error)
GetPatentAssociatedDocuments(ctx, applicationNumber string) (any, error)
GetPatentAttorney(ctx, applicationNumber string) (any, error)
GetPatentForeignPriority(ctx, applicationNumber string) (any, error)
GetPatentTransactions(ctx, applicationNumber string) (*TransactionsResponse, error)

// Downloads & Utilities
SearchPatentsDownload(ctx, req PatentDownloadRequest) ([]byte, error)
GetStatusCodes(ctx) (*StatusCodeSearchResponse, error)

Bulk Data API (3 endpoints)

SearchBulkProducts(ctx, query string, offset, limit int) (*BdssResponseBag, error)
GetBulkProduct(ctx, productID string) (*BdssResponseProductBag, error)

// File download methods (use FileDownloadURI directly):
DownloadBulkFile(ctx, fileDownloadURI string, w io.Writer) error
DownloadBulkFileWithProgress(ctx, fileDownloadURI string, w io.Writer,
    progress func(bytesComplete, bytesTotal int64)) error

Petition API (3 endpoints)

SearchPetitions(ctx, query string, offset, limit int32) (*PetitionDecisionResponseBag, error)
GetPetitionDecision(ctx, recordID string, includeDocuments bool) (*PetitionDecisionIdentifierResponseBag, error)
SearchPetitionsDownload(ctx, req PetitionDecisionDownloadRequest) ([]byte, error)

PTAB (Patent Trial and Appeal Board) API (19 endpoints)

// Trial Proceedings (IPR, PGR, CBM)
SearchTrialProceedings(ctx, query string, offset, limit int32) (*ProceedingDataResponse, error)
GetTrialProceeding(ctx, trialNumber string) (*ProceedingDataResponse, error)
SearchTrialProceedingsDownload(ctx, req DownloadRequest) ([]byte, error)

// Trial Decisions
SearchTrialDecisions(ctx, query string, offset, limit int32) (*DecisionDataResponse, error)
GetTrialDecision(ctx, documentIdentifier string) (*DecisionDataResponse, error)
GetTrialDecisionsByTrialNumber(ctx, trialNumber string) (*DecisionDataResponse, error)
SearchTrialDecisionsDownload(ctx, req DownloadRequest) ([]byte, error)

// Trial Documents
SearchTrialDocuments(ctx, query string, offset, limit int32) (*DocumentDataResponse, error)
GetTrialDocument(ctx, documentIdentifier string) (*DocumentDataResponse, error)
GetTrialDocumentsByTrialNumber(ctx, trialNumber string) (*DocumentDataResponse, error)
SearchTrialDocumentsDownload(ctx, req DownloadRequest) ([]byte, error)

// Appeal Decisions
SearchAppealDecisions(ctx, query string, offset, limit int32) (*AppealDecisionDataResponse, error)
GetAppealDecision(ctx, documentIdentifier string) (*AppealDecisionDataResponse, error)
GetAppealDecisionsByAppealNumber(ctx, appealNumber string) (*AppealDecisionDataResponse, error)
SearchAppealDecisionsDownload(ctx, req DownloadRequest) ([]byte, error)

// Interference Decisions
SearchInterferenceDecisions(ctx, query string, offset, limit int32) (*InterferenceDecisionDataResponse, error)
GetInterferenceDecision(ctx, documentIdentifier string) (*InterferenceDecisionDataResponse, error)
GetInterferenceDecisionsByNumber(ctx, interferenceNumber string) (*InterferenceDecisionDataResponse, error)
SearchInterferenceDecisionsDownload(ctx, req PatentDownloadRequest) ([]byte, error)

Office Action APIs (8 endpoints)

These use the DSAPI pattern (form-encoded POST with Lucene/Solr queries). Same API key as the main ODP API.

// Office Action Text Retrieval
SearchOfficeActions(ctx, criteria string, start, rows int32) (*DSAPIResponse, error)
GetOfficeActionFields(ctx) (*DSAPIFieldsResponse, error)

// Office Action Citations (Forms PTO-892 & PTO-1449)
SearchOfficeActionCitations(ctx, criteria string, start, rows int32) (*DSAPIResponse, error)
GetOfficeActionCitationFields(ctx) (*DSAPIFieldsResponse, error)

// Office Action Rejections (101, 102, 103, 112, DP)
SearchOfficeActionRejections(ctx, criteria string, start, rows int32) (*DSAPIResponse, error)
GetOfficeActionRejectionFields(ctx) (*DSAPIFieldsResponse, error)

// Enriched Citations (AI/ML extracted from office actions)
SearchEnrichedCitations(ctx, criteria string, start, rows int32) (*DSAPIResponse, error)
GetEnrichedCitationFields(ctx) (*DSAPIFieldsResponse, error)

Office Action APIs use Lucene query syntax:

// Search by patent application number
result, err := client.SearchOfficeActionRejections(ctx, "patentApplicationNumber:12190351", 0, 10)

// Search with boolean operators
result, err := client.SearchOfficeActions(ctx, "hasRej103:1 AND groupArtUnitNumber:1713", 0, 10)

// Get available fields
fields, err := client.GetOfficeActionRejectionFields(ctx)
fmt.Printf("Searchable fields: %v\n", fields.Fields)

TSDR (Trademark Status & Document Retrieval) API

Separate server (tsdrapi.uspto.gov) and API key. Requires TSDRAPIKey in config.

config := odp.DefaultConfig()
config.APIKey = "your-odp-key"
config.TSDRAPIKey = "your-tsdr-key"  // from https://account.uspto.gov/profile/api-manager
client, err := odp.NewClient(config)

// Get trademark case status (raw XML response)
xmlResp, err := client.GetTrademarkStatus(ctx, "97123456")

// Get trademark case status (JSON via content negotiation)
status, err := client.GetTrademarkStatusJSON(ctx, "97123456")
fmt.Printf("Trademarks: %d\n", len(status.Trademarks))

// Get document list (XML)
docs, err := client.GetTrademarkDocumentsXML(ctx, "97123456")

// Get info about a specific document (XML) - docID format: {TypeCode}{YYYYMMDD}
info, err := client.GetTrademarkDocumentInfo(ctx, "97123456", "NOA20230322")

// Download a document as PDF
var buf bytes.Buffer
client.DownloadTrademarkDocument(ctx, "97123456", "NOA20230322", &buf)

// Get last update time
update, err := client.GetTrademarkLastUpdate(ctx, "97123456")

// Multi-status lookup
result, err := client.GetTrademarkMultiStatus(ctx, "sn", []string{"97123456", "97654321"})

Patent Full Text & Advanced Features

Patent Number Normalization

The library handles various patent number formats and automatically resolves them to application numbers:

// GetPatent accepts any patent number format
doc, err := client.GetPatent(ctx, "US 11,646,472 B2")  // Grant number
doc, err := client.GetPatent(ctx, "17/248,024")        // Application number
doc, err := client.GetPatent(ctx, "US20250087686A1")   // Publication number

// For other methods, resolve to application number first
appNumber, err := client.ResolvePatentNumber(ctx, "US 11,646,472 B2")
// appNumber = "17248024" (the actual application number)

// Low-level normalization (formatting only, doesn't resolve)
pn, err := odp.NormalizePatentNumber("US 11,646,472 B2")
fmt.Println(pn.Type)                  // PatentNumberTypeGrant
fmt.Println(pn.Normalized)            // "11646472" (normalized, not application number!)
fmt.Println(pn.FormatAsGrant())       // "11,646,472"

Note: Grant and publication numbers are not the same as application numbers. The library uses the search API to resolve grant/publication numbers to their corresponding application numbers.

Supported formats:

  • Applications: 17248024, 17/248,024, US 17/248,024
  • Grants: 11646472, 11,646,472, US 11,646,472 B2
  • Publications: 20250087686, US20250087686A1

Note: 8-digit numbers (like 11646472) are ambiguous - they could be either grant or application numbers. Use formatting (commas, kind codes) to disambiguate.

XML Full Text Retrieval

Parse full patent text (ICE DTD 4.6/4.7):

doc, err := client.GetPatentXML(ctx, "US 11,646,472 B2")

title := doc.GetTitle()
abstract := doc.GetAbstract().ExtractAbstractText()
claims := doc.GetClaims().ExtractAllClaimsTextFormatted()
description := doc.GetDescription().ExtractDescriptionText()

Advanced usage:

// Get XML URL and type
xmlURL, docType, err := client.GetXMLURLForApplication(ctx, "17248024")

// Download with type hint
doc, err := client.DownloadXMLWithType(ctx, xmlURL, docType)

// Parse raw XML
data := []byte(/* XML content */)
doc, err = odp.ParseGrantXML(data)  // or ParseApplicationXML

Bulk File Downloads

product, err := client.GetBulkProduct(ctx, "PTGRXML")
files := *product.BulkDataProductBag[0].ProductFileBag.FileDataBag

for _, file := range files {
    if file.FileName != nil && strings.Contains(*file.FileName, "ipg250923.zip") {
        if file.FileDownloadURI != nil {
            err := client.DownloadBulkFileWithProgress(ctx, *file.FileDownloadURI, outputFile,
                func(bytesComplete, bytesTotal int64) {
                    percent := float64(bytesComplete) * 100 / float64(bytesTotal)
                    fmt.Printf("\rProgress: %.1f%%", percent)
                })
        }
        break
    }
}

Configuration

config := &odp.Config{
    BaseURL:    "https://api.uspto.gov", // Default
    APIKey:     "your-api-key",
    UserAgent:  "YourApp/1.0",
    MaxRetries: 3,                       // Retry failed requests
    RetryDelay: 1,                       // Seconds between retries
    Timeout:    30,                      // Request timeout in seconds

    // TSDR (optional - separate server and API key)
    TSDRAPIKey: "your-tsdr-key",         // From https://account.uspto.gov/profile/api-manager
    TSDRBaseURL: "https://tsdrapi.uspto.gov", // Default
}

client, err := odp.NewClient(config)

Package Structure

├── client.go              # Main client implementation (package odp)
├── office_action.go       # Office Action API wrappers (DSAPI pattern)
├── tsdr.go                # TSDR (Trademark) API wrappers
├── types.go               # Typed response structs (continuity, assignment, adjustment, transactions)
├── patent_number.go       # Patent number normalization
├── xml.go                 # XML full text parsing (ICE DTD 4.6/4.7)
├── *_test.go              # Unit tests, integration tests
├── generated/             # Auto-generated OpenAPI code
│   ├── client_gen.go      # ODP client (package generated)
│   ├── types_gen.go       # ODP types (package generated)
│   ├── oa/                # Office Action DSAPI (package oa)
│   │   ├── client_gen.go
│   │   └── types_gen.go
│   └── tsdr/              # TSDR Trademark (package tsdr)
│       ├── client_gen.go
│       └── types_gen.go
├── cmd/gen/               # Code generation tool (pure Go)
│   └── main.go            # Bundles swagger files and applies fixes
├── demo/                  # Usage examples with saved responses
├── swagger/               # Official USPTO OpenAPI specs (DO NOT EDIT)
│   ├── swagger.yaml       # Main ODP API specification
│   ├── odp-common-base.yaml # Shared type definitions
│   ├── trial-*.yaml       # PTAB API specifications
│   ├── oa-*.yaml          # Office Action DSAPI specifications
│   └── tsdr-swagger.json  # TSDR API specification
├── swagger_fixed.yaml     # Processed ODP spec (auto-generated)
├── swagger_oa_fixed.yaml  # Processed OA spec (auto-generated)
├── swagger_tsdr_fixed.json# Processed TSDR spec (auto-generated)
└── dtd/                   # ICE DTD documentation

Implementation

This library provides a Go client for the USPTO ODP API through a multi-step process:

  1. API Specification: Started with the official USPTO ODP Swagger specification
  2. Fix Mismatches: Fixed type mismatches between swagger and actual API responses (see Swagger Fixes)
  3. Code Generation: Generate types and client code using oapi-codegen into generated/ package
  4. Idiomatic Wrapper: Wrap generated code in a clean, idiomatic Go client with retry logic (main odp package)

Testing

Unit Tests

go test -v
go test -v -cover

Integration Tests

Requires USPTO_API_KEY and optionally USPTO_TSDR_API_KEY:

# Set your API keys (add to ~/.zshrc for persistence)
export USPTO_API_KEY=your-odp-key
export USPTO_TSDR_API_KEY=your-tsdr-key  # from https://account.uspto.gov/profile/api-manager

# Run all integration tests
go test -tags=integration -v

# Office Action APIs
go test -tags=integration -v -run TestOfficeActionAPIs

# TSDR API
go test -tags=integration -v -run TestTSDRAPIs

# Run specific endpoint test
go test -tags=integration -v -run TestIntegrationWithRealAPI/GetStatusCodes

# Test bulk file download (skipped by default due to large file size)
TEST_BULK_DOWNLOAD=true go test -tags=integration -v -run DownloadBulkFile

Endpoint Coverage

All USPTO ODP API endpoints are implemented and tested:

  • 13 Patent Application API endpoints
  • 3 Bulk Data API endpoints
  • 3 Petition API endpoints
  • 19 PTAB (Patent Trial and Appeal Board) API endpoints
  • 8 Office Action DSAPI endpoints (Text Retrieval, Citations, Rejections, Enriched Citations)
  • 7 TSDR (Trademark Status & Document Retrieval) wrapper methods

Swagger Processing

Source Files

The USPTO ODP API specification is distributed as multiple YAML files with $ref references between them. The original files are downloaded from USPTO ODP Swagger and stored in swagger/:

swagger/
├── swagger.yaml                 # Main ODP API spec (Patent, Bulk, Petition)
├── odp-common-base.yaml         # Shared type definitions
├── trial-proceedings.yaml       # PTAB trial proceedings
├── trial-decisions.yaml         # PTAB trial decisions
├── trial-documents.yaml         # PTAB trial documents
├── trial-appeal-decisions.yaml  # PTAB appeal decisions
├── trial-interferences.yaml     # PTAB interference decisions
├── trial-common.yaml            # Shared PTAB types
├── oa-text-retrieval.yaml       # Office Action Text Retrieval
├── oa-citations.yaml            # Office Action Citations
├── oa-rejections.yaml           # Office Action Rejections
├── oa-enriched-citations.yaml   # Enriched Citations
└── tsdr-swagger.json            # TSDR (Trademark) API

Important: Do not edit files in swagger/ - these are the original USPTO specifications.

Code Generation

The cmd/gen tool (pure Go, no external dependencies) processes these files:

go run ./cmd/gen

This tool:

  1. Bundles ODP + PTAB YAML files, resolving $ref references -> swagger_fixed.yaml -> generated/
  2. Bundles 4 Office Action specs -> swagger_oa_fixed.yaml -> generated/oa/
  3. Copies TSDR spec -> swagger_tsdr_fixed.json -> generated/tsdr/
  4. Applies fixes for mismatches between swagger specs and actual API responses

Fixes Applied

The USPTO swagger specification has several mismatches with actual API responses:

Type Corrections:

  • frameNumber, reelNumber: string -> integer (API returns numeric values)
  • documentNumber: string -> integer (PTAB API returns numbers)
  • Error response code: integer -> string (API returns "404" not 404)

Structure Fixes:

  • petitionIssueConsideredTextBag: array of objects -> array of strings
  • correspondenceAddress: array -> object (Assignment API returns object)
  • DecisionData.statuteAndRuleBag, issueTypeBag: string -> array (PTAB API returns arrays)
  • GetPatentAssignment.assignmentBag: single object -> array (API returns array of assignments)

Field Name Fixes:

  • InterferenceDecisionRecord.decisionDocumentData -> documentData (API uses different field name)

Format Fixes:

  • Removed format: date-time from datetime fields that return non-RFC3339 formats (e.g., lastModifiedDateTime returns "2025-11-26T23:58:00" without timezone)
  • Removed format: date from datetime fields (e.g., appealLastModifiedDateTime returns datetime, not date)
  • Removed format: date from fields returning non-ISO dates (e.g., fileReleaseDate returns "2025-09-23 00:57:53")

Endpoint Fixes:

  • Removed /api/v1/patent/applications/text-to-search (defined in spec but has no operations)

Office Action DSAPI Fixes:

  • Removed phantom path parameters (dataset, version declared as in: path but paths are static)
  • Made operationId values unique across bundled specs (all 4 specs used identical IDs)

TSDR Fixes:

  • Fixed protocol-relative server URL (//tsdrapi.uspto.gov/ -> https://tsdrapi.uspto.gov)
  • GetDocumentInfoXml and GetCaseDocsInfoXml endpoints return 406 with Accept: application/json - content negotiation is not supported despite XML/JSON server paths in spec
  • Removed format: date-time and format: date from 64 fields - API returns inconsistent date formats (date-only "2021-11-19" in fields declared as date-time, non-ISO formats elsewhere), causing time.Time parsing failures in generated code

Bugs Fixed by USPTO:

  • trial-appeal-decisions.yaml: appelantData -> appellantData (spelling), realPartyName -> realPartyInInterestName, techCenterNumber -> technologyCenterNumber, requestorData -> thirdPartyRequesterData, documentTypeCategory -> documentTypeDescriptionText, downloadURI -> fileDownloadURI, added decisionData block, added requestIdentifier
  • trial-common.yaml: downloadURI -> fileDownloadURI, statuteAndRuleBag/issueTypeBag string -> array, documentNumber string -> integer, added RegularPetitionerData fields, added appealOutcomeCategory
  • trial-decisions.yaml: now uses full inline schemas instead of allOf refs

Version History

v1.4.0 - Full ODP Coverage (Office Action + TSDR)

  • Office Action APIs: Text Retrieval, Citations, Rejections, Enriched Citations (8 endpoints)
  • TSDR (Trademark Status & Document Retrieval) API (24 endpoints, separate server + key)
  • Updated PTAB swagger specs with USPTO's field name fixes
  • Separate generated packages: generated/oa/, generated/tsdr/
  • DSAPI pattern support (form-encoded POST, Lucene/Solr queries)
  • TSDR content negotiation (JSON via Accept header, XML default)
  • Integration tests for all new APIs

v1.3.0 - Strongly-Typed Response Parsing

  • GetPatentContinuity returns *ContinuityResponse with Parents/Children and relationship types
  • GetPatentAssignment returns *AssignmentResponse with assignors, assignees, reel/frame
  • GetPatentAdjustment returns *AdjustmentResponse with PTA delay breakdown
  • GetPatentTransactions returns *TransactionsResponse with event date/code/description
  • Unit tests with real JSON fixtures and edge cases
  • Enhanced integration tests with typed assertions and fixture update mechanism

v1.2.0 - PTAB API Complete (2025-11-27)

  • Support for USPTO ODP 3.0 (released 2025-11-21) which added PTAB datasets
  • Added 19 PTAB (Patent Trial and Appeal Board) API endpoints
  • Trial Proceedings, Decisions, Documents, Appeal Decisions, Interference Decisions
  • Pure Go code generation tool (cmd/gen) with no external dependencies
  • Multi-file swagger processing (USPTO distributes spec as multiple YAML files)
  • Demo with example saving (request/response pairs for documentation)
  • Fixed API/swagger mismatches for PTAB endpoints

v1.1.0 - Patent Number Normalization & XML Parsing

  • Patent number normalization (accepts any format: grant, application, publication)
  • ResolvePatentNumber() to convert grant/publication numbers to application numbers
  • XML full text parsing (ICE DTD 4.6/4.7)
  • Refactored demo suite

v1.0.0 - Initial Release

  • Complete USPTO ODP API client with 19 endpoints
  • Patent Application API (13 endpoints)
  • Bulk Data API (3 endpoints)
  • Petition API (3 endpoints)
  • Retry logic and configurable timeouts

Related Projects

Part of the patent.dev open-source patent data ecosystem:

  • epo-ops - EPO Open Patent Services client (search, biblio, legal status, family, images)
  • epo-bdds - EPO Bulk Data Distribution Service client
  • dpma-connect-plus - DPMA Connect Plus client (patents, designs, trademarks)

The bulk-file-loader uses these libraries for automated patent data downloads.

License

MIT License - see LICENSE file for details.

Credits

Developed by:

Acknowledgments

  • USPTO for providing the Open Data Portal API
  • oapi-codegen for code generation

About

A complete Go client library for the USPTO Open Data Portal API.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages