{"id":37154234,"url":"https://github.com/patent-dev/uspto-odp","last_synced_at":"2026-01-14T18:11:06.519Z","repository":{"id":316308076,"uuid":"1062510372","full_name":"patent-dev/uspto-odp","owner":"patent-dev","description":"A complete Go client library for the USPTO Open Data Portal API.","archived":false,"fork":false,"pushed_at":"2025-10-28T23:14:53.000Z","size":468,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-29T01:12:22.116Z","etag":null,"topics":["api","patent","patent-data","patent-data-api"],"latest_commit_sha":null,"homepage":"https://patent.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/patent-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-23T10:56:48.000Z","updated_at":"2025-10-28T23:13:03.000Z","dependencies_parsed_at":"2025-09-23T22:11:52.060Z","dependency_job_id":"f1a0edb8-0833-4e87-921e-6ea2bec7b5bb","html_url":"https://github.com/patent-dev/uspto-odp","commit_stats":null,"previous_names":["patent-dev/uspto-odp"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/patent-dev/uspto-odp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patent-dev%2Fuspto-odp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patent-dev%2Fuspto-odp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patent-dev%2Fuspto-odp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patent-dev%2Fuspto-odp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patent-dev","download_url":"https://codeload.github.com/patent-dev/uspto-odp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patent-dev%2Fuspto-odp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28429822,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T16:38:47.836Z","status":"ssl_error","status_checked_at":"2026-01-14T16:34:59.695Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","patent","patent-data","patent-data-api"],"created_at":"2026-01-14T18:11:05.663Z","updated_at":"2026-01-14T18:11:06.506Z","avatar_url":"https://github.com/patent-dev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# USPTO Open Data Portal (ODP) Go Client\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/patent-dev/uspto-odp.svg)](https://pkg.go.dev/github.com/patent-dev/uspto-odp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nA complete Go client library for the USPTO Open Data Portal API.\n\n## Getting Started\n\n### API Key Required\n\nYou need an API key to use the USPTO ODP API:\n- **Details**: https://data.uspto.gov/apis/getting-started\n- **Note**: Video verification is required during registration\n- **Rate limits**: Check the documentation for current rate limits and usage guidelines\n\n## Installation\n\n```bash\ngo get github.com/patent-dev/uspto-odp\n```\n\n## Quick Start\n\n```go\nconfig := odp.DefaultConfig()\nconfig.APIKey = \"your-api-key\"\nclient, err := odp.NewClient(config)\nctx := context.Background()\n\nresults, err := client.SearchPatents(ctx, \"artificial intelligence\", 0, 10)\nfmt.Printf(\"Found %d patents\\n\", *results.Count)\n```\n\n## API Methods - Complete Coverage (38 endpoints)\n\nAll 38 USPTO ODP API endpoints are fully implemented and tested.\n\n### Patent Application API (13 endpoints)\n\n```go\n// Core Patent Data\nSearchPatents(ctx, query string, offset, limit int32) (*PatentDataResponse, error)\nGetPatent(ctx, patentNumber string) (*PatentDataResponse, error)  // Accepts any patent number format\nGetPatentMetaData(ctx, applicationNumber string) (interface{}, error)\n\n// Patent Details\nGetPatentAdjustment(ctx, applicationNumber string) (interface{}, error)\nGetPatentContinuity(ctx, applicationNumber string) (interface{}, error)\nGetPatentDocuments(ctx, applicationNumber string) (*DocumentBag, error)\nGetPatentAssignment(ctx, applicationNumber string) (interface{}, error)\nGetPatentAssociatedDocuments(ctx, applicationNumber string) (interface{}, error)\nGetPatentAttorney(ctx, applicationNumber string) (interface{}, error)\nGetPatentForeignPriority(ctx, applicationNumber string) (interface{}, error)\nGetPatentTransactions(ctx, applicationNumber string) (interface{}, error)\n\n// Downloads \u0026 Utilities\nSearchPatentsDownload(ctx, req PatentDownloadRequest) ([]byte, error)\nGetStatusCodes(ctx) (*StatusCodeSearchResponse, error)\n```\n\n### Bulk Data API (3 endpoints)\n\n```go\nSearchBulkProducts(ctx, query string, offset, limit int) (*BdssResponseBag, error)\nGetBulkProduct(ctx, productID string) (*BdssResponseProductBag, error)\n\n// File download methods (use FileDownloadURI directly):\nDownloadBulkFile(ctx, fileDownloadURI string, w io.Writer) error\nDownloadBulkFileWithProgress(ctx, fileDownloadURI string, w io.Writer,\n    progress func(bytesComplete, bytesTotal int64)) error\n```\n\n### Petition API (3 endpoints)\n\n```go\nSearchPetitions(ctx, query string, offset, limit int32) (*PetitionDecisionResponseBag, error)\nGetPetitionDecision(ctx, recordID string, includeDocuments bool) (*PetitionDecisionIdentifierResponseBag, error)\nSearchPetitionsDownload(ctx, req PetitionDecisionDownloadRequest) ([]byte, error)\n```\n\n### PTAB (Patent Trial and Appeal Board) API (19 endpoints)\n\n```go\n// Trial Proceedings (IPR, PGR, CBM)\nSearchTrialProceedings(ctx, query string, offset, limit int32) (*ProceedingDataResponse, error)\nGetTrialProceeding(ctx, trialNumber string) (*ProceedingDataResponse, error)\nSearchTrialProceedingsDownload(ctx, req DownloadRequest) ([]byte, error)\n\n// Trial Decisions\nSearchTrialDecisions(ctx, query string, offset, limit int32) (*DecisionDataResponse, error)\nGetTrialDecision(ctx, documentIdentifier string) (*DecisionDataResponse, error)\nGetTrialDecisionsByTrialNumber(ctx, trialNumber string) (*DecisionDataResponse, error)\nSearchTrialDecisionsDownload(ctx, req DownloadRequest) ([]byte, error)\n\n// Trial Documents\nSearchTrialDocuments(ctx, query string, offset, limit int32) (*DocumentDataResponse, error)\nGetTrialDocument(ctx, documentIdentifier string) (*DocumentDataResponse, error)\nGetTrialDocumentsByTrialNumber(ctx, trialNumber string) (*DocumentDataResponse, error)\nSearchTrialDocumentsDownload(ctx, req DownloadRequest) ([]byte, error)\n\n// Appeal Decisions\nSearchAppealDecisions(ctx, query string, offset, limit int32) (*AppealDecisionDataResponse, error)\nGetAppealDecision(ctx, documentIdentifier string) (*AppealDecisionDataResponse, error)\nGetAppealDecisionsByAppealNumber(ctx, appealNumber string) (*AppealDecisionDataResponse, error)\nSearchAppealDecisionsDownload(ctx, req DownloadRequest) ([]byte, error)\n\n// Interference Decisions\nSearchInterferenceDecisions(ctx, query string, offset, limit int32) (*InterferenceDecisionDataResponse, error)\nGetInterferenceDecision(ctx, documentIdentifier string) (*InterferenceDecisionDataResponse, error)\nGetInterferenceDecisionsByNumber(ctx, interferenceNumber string) (*InterferenceDecisionDataResponse, error)\nSearchInterferenceDecisionsDownload(ctx, req PatentDownloadRequest) ([]byte, error)\n```\n\n## Patent Full Text \u0026 Advanced Features\n\n### Patent Number Normalization\n\nThe library handles various patent number formats and automatically resolves them to application numbers:\n\n```go\n// GetPatent accepts any patent number format\ndoc, err := client.GetPatent(ctx, \"US 11,646,472 B2\")  // Grant number\ndoc, err := client.GetPatent(ctx, \"17/248,024\")        // Application number\ndoc, err := client.GetPatent(ctx, \"US20250087686A1\")   // Publication number\n\n// For other methods, resolve to application number first\nappNumber, err := client.ResolvePatentNumber(ctx, \"US 11,646,472 B2\")\n// appNumber = \"17248024\" (the actual application number)\n\n// Low-level normalization (formatting only, doesn't resolve)\npn, err := odp.NormalizePatentNumber(\"US 11,646,472 B2\")\nfmt.Println(pn.Type)                  // PatentNumberTypeGrant\nfmt.Println(pn.Normalized)            // \"11646472\" (normalized, not application number!)\nfmt.Println(pn.FormatAsGrant())       // \"11,646,472\"\n```\n\n**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.\n\nSupported formats:\n- Applications: `17248024`, `17/248,024`, `US 17/248,024`\n- Grants: `11646472`, `11,646,472`, `US 11,646,472 B2`\n- Publications: `20250087686`, `US20250087686A1`\n\n**Note:** 8-digit numbers (like `11646472`) are ambiguous - they could be either grant or application numbers. Use formatting (commas, kind codes) to disambiguate.\n\n### XML Full Text Retrieval\n\nParse full patent text (ICE DTD 4.6/4.7):\n\n```go\ndoc, err := client.GetPatentXML(ctx, \"US 11,646,472 B2\")\n\ntitle := doc.GetTitle()\nabstract := doc.GetAbstract().ExtractAbstractText()\nclaims := doc.GetClaims().ExtractAllClaimsTextFormatted()\ndescription := doc.GetDescription().ExtractDescriptionText()\n```\n\nAdvanced usage:\n\n```go\n// Get XML URL and type\nxmlURL, docType, err := client.GetXMLURLForApplication(ctx, \"17248024\")\n\n// Download with type hint\ndoc, err := client.DownloadXMLWithType(ctx, xmlURL, docType)\n\n// Parse raw XML\ndata := []byte(/* XML content */)\ndoc, err = odp.ParseGrantXML(data)  // or ParseApplicationXML\n```\n\n## Bulk File Downloads\n\n```go\nproduct, err := client.GetBulkProduct(ctx, \"PTGRXML\")\nfiles := *product.BulkDataProductBag[0].ProductFileBag.FileDataBag\n\nfor _, file := range files {\n    if file.FileName != nil \u0026\u0026 strings.Contains(*file.FileName, \"ipg250923.zip\") {\n        if file.FileDownloadURI != nil {\n            err := client.DownloadBulkFileWithProgress(ctx, *file.FileDownloadURI, outputFile,\n                func(bytesComplete, bytesTotal int64) {\n                    percent := float64(bytesComplete) * 100 / float64(bytesTotal)\n                    fmt.Printf(\"\\rProgress: %.1f%%\", percent)\n                })\n        }\n        break\n    }\n}\n```\n\n## Configuration\n\n```go\nconfig := \u0026odp.Config{\n    BaseURL:    \"https://api.uspto.gov\", // Default\n    APIKey:     \"your-api-key\",\n    UserAgent:  \"YourApp/1.0\",\n    MaxRetries: 3,                       // Retry failed requests\n    RetryDelay: 1,                       // Seconds between retries\n    Timeout:    30,                      // Request timeout in seconds\n}\n\nclient, err := odp.NewClient(config)\n```\n\n## Package Structure\n\n```\n├── client.go            # Main client implementation (package odp)\n├── patent_number.go     # Patent number normalization\n├── xml.go               # XML full text parsing (ICE DTD 4.6/4.7)\n├── client_test.go       # Unit tests with mock server\n├── patent_number_test.go# Patent number normalization tests\n├── xml_test.go          # XML parsing tests\n├── integration_test.go  # Integration tests (real API)\n├── generated/           # Auto-generated OpenAPI code\n│   ├── client_gen.go    # Generated client (package generated)\n│   └── types_gen.go     # Generated types (package generated)\n├── cmd/gen/             # Code generation tool (pure Go)\n│   └── main.go          # Bundles swagger files and applies fixes\n├── demo/                # Usage examples with saved responses\n│   └── main.go          # Demo runner for all API services\n├── swagger/             # Official USPTO OpenAPI specs (DO NOT EDIT)\n│   ├── swagger.yaml     # Main API specification\n│   ├── odp-common-base.yaml  # Shared type definitions\n│   └── trial-*.yaml     # PTAB API specifications\n├── swagger_fixed.yaml   # Processed spec with fixes (auto-generated)\n└── dtd/                 # ICE DTD documentation\n    └── README.md        # DTD structure and information\n```\n\n## Implementation\n\nThis library provides a Go client for the USPTO ODP API through a multi-step process:\n\n1. **API Specification**: Started with the official [USPTO ODP Swagger specification](https://data.uspto.gov/swagger/index.html#/)\n2. **Fix Mismatches**: Fixed type mismatches between swagger and actual API responses (see [Swagger Fixes](#swagger-fixes-applied))\n3. **Code Generation**: Generate types and client code using [oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) into `generated/` package\n4. **Idiomatic Wrapper**: Wrap generated code in a clean, idiomatic Go client with retry logic (main `odp` package)\n\n## Testing\n\n### Unit Tests\n\n```bash\ngo test -v\ngo test -v -cover\n```\n\n### Integration Tests\n\nRequires `USPTO_API_KEY` environment variable:\n```bash\n# Set your API key (add to ~/.zshrc for persistence)\nexport USPTO_API_KEY=your-api-key\n\n# Run all integration tests\ngo test -tags=integration -v\n\n# Run specific endpoint test\ngo test -tags=integration -v -run TestIntegrationWithRealAPI/GetStatusCodes\n\n# Test endpoint coverage documentation\ngo test -tags=integration -v -run TestEndpointCoverage\n\n# Test XML parsing with real API data\ngo test -tags=integration -v -run TestXMLParsing\n\n# Test bulk file download (skipped by default due to large file size)\nTEST_BULK_DOWNLOAD=true go test -tags=integration -v -run DownloadBulkFile\n```\n\nIntegration tests require `USPTO_API_KEY` environment variable. Bulk file download test skipped by default (set `TEST_BULK_DOWNLOAD=true` to run).\n\n## Endpoint Coverage\n\nAll 38 USPTO ODP API endpoints are implemented and tested:\n- 13 Patent Application API endpoints\n- 3 Bulk Data API endpoints\n- 3 Petition API endpoints\n- 19 PTAB (Patent Trial and Appeal Board) API endpoints\n\n## Swagger Processing\n\n### Source Files\n\nThe USPTO ODP API specification is distributed as multiple YAML files with `$ref` references between them. The original files are downloaded from [USPTO ODP Swagger](https://data.uspto.gov/swagger/index.html#/) and stored in `swagger/`:\n\n```\nswagger/\n├── swagger.yaml           # Main API spec (Patent, Bulk, Petition endpoints)\n├── odp-common-base.yaml   # Shared type definitions\n├── trial-proceedings.yaml # PTAB trial proceedings\n├── trial-decisions.yaml   # PTAB trial decisions\n├── trial-documents.yaml   # PTAB trial documents\n├── trial-appeal-decisions.yaml  # PTAB appeal decisions\n├── trial-interferences.yaml     # PTAB interference decisions\n└── trial-common.yaml      # Shared PTAB types\n```\n\n**Important:** Do not edit files in `swagger/` - these are the original USPTO specifications.\n\n### Code Generation\n\nThe `cmd/gen` tool (pure Go, no external dependencies) processes these files:\n\n```bash\ngo run ./cmd/gen\n```\n\nThis tool:\n1. **Bundles** all YAML files, resolving `$ref` references between files\n2. **Applies fixes** for mismatches between swagger spec and actual API responses\n3. **Generates** `swagger_fixed.yaml` (processed OpenAPI spec)\n4. **Generates** Go code in `generated/` using oapi-codegen\n\n### Fixes Applied\n\nThe USPTO swagger specification has several mismatches with actual API responses:\n\n**Type Corrections:**\n- `frameNumber`, `reelNumber`: string → integer (API returns numeric values)\n- `documentNumber`: string → integer (PTAB API returns numbers)\n- Error response `code`: integer → string (API returns `\"404\"` not `404`)\n\n**Structure Fixes:**\n- `petitionIssueConsideredTextBag`: array of objects → array of strings\n- `correspondenceAddress`: array → object (Assignment API returns object)\n- `DecisionData.statuteAndRuleBag`, `issueTypeBag`: string → array (PTAB API returns arrays)\n- `GetPatentAssignment.assignmentBag`: single object → array (API returns array of assignments)\n\n**Field Name Fixes:**\n- `InterferenceDecisionRecord.decisionDocumentData` → `documentData` (API uses different field name)\n\n**Format Fixes:**\n- Removed `format: date-time` from datetime fields that return non-RFC3339 formats (e.g., `lastModifiedDateTime` returns `\"2025-11-26T23:58:00\"` without timezone)\n- Removed `format: date` from datetime fields (e.g., `appealLastModifiedDateTime` returns datetime, not date)\n- Removed `format: date` from fields returning non-ISO dates (e.g., `fileReleaseDate` returns `\"2025-09-23 00:57:53\"`)\n\n**Endpoint Fixes:**\n- Removed `/api/v1/patent/applications/text-to-search` (defined in spec but has no operations)\n\n## Version History\n\n### v1.2.0 - PTAB API Complete (2025-11-27)\n- Support for USPTO ODP 3.0 (released 2025-11-21) which added PTAB datasets\n- Added 19 PTAB (Patent Trial and Appeal Board) API endpoints\n- Trial Proceedings, Decisions, Documents, Appeal Decisions, Interference Decisions\n- Pure Go code generation tool (`cmd/gen`) with no external dependencies\n- Multi-file swagger processing (USPTO distributes spec as multiple YAML files)\n- Demo with example saving (request/response pairs for documentation)\n- Fixed API/swagger mismatches for PTAB endpoints\n\n### v1.1.0 - Patent Number Normalization \u0026 XML Parsing\n- Patent number normalization (accepts any format: grant, application, publication)\n- `ResolvePatentNumber()` to convert grant/publication numbers to application numbers\n- XML full text parsing (ICE DTD 4.6/4.7)\n- Refactored demo suite\n\n### v1.0.0 - Initial Release\n- Complete USPTO ODP API client with 19 endpoints\n- Patent Application API (13 endpoints)\n- Bulk Data API (3 endpoints)\n- Petition API (3 endpoints)\n- Retry logic and configurable timeouts\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Credits\n\n**Developed by:**\n- Wolfgang Stark - [patent.dev](https://patent.dev) - [Funktionslust GmbH](https://funktionslust.digital)\n\n## Acknowledgments\n\n- USPTO for providing the Open Data Portal API\n- [oapi-codegen](https://github.com/oapi-codegen/oapi-codegen) for code generation\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatent-dev%2Fuspto-odp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatent-dev%2Fuspto-odp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatent-dev%2Fuspto-odp/lists"}