Patent Data Examples

  1"""
  2Example usage of the uspto_api module for patent data
  3
  4This example demonstrates how to use the PatentDataClient to interact with the USPTO Patent Data API.
  5It shows how to retrieve patent applications, search for patents by various criteria, and access
  6detailed patent information including inventors, applicants, assignments, and more.
  7"""
  8
  9import json  # For pretty printing dict
 10import os
 11
 12from pyUSPTO.clients.patent_data import PatentDataClient
 13from pyUSPTO.config import USPTOConfig
 14from pyUSPTO.models.patent_data import ApplicationContinuityData
 15
 16# --- Initialization ---
 17# Choose one method to initialize the client.
 18# For this example, Method 1 is active. Replace "YOUR_API_KEY_HERE" with your actual key.
 19
 20# Method 1: Initialize the client with direct API key
 21print("Method 1: Initialize with direct API key")
 22api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
 23if api_key == "YOUR_API_KEY_HERE":
 24    raise ValueError(
 25        "WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
 26    )
 27client = PatentDataClient(api_key=api_key)
 28
 29# Method 2: Initialize the client with USPTOConfig (alternative)
 30# print("\nMethod 2: Initialize with USPTOConfig")
 31# config_obj = USPTOConfig(
 32#     api_key="YOUR_API_KEY_HERE",  # Replace with your actual API key
 33#     # bulk_data_base_url="https://api.uspto.gov/api/v1/datasets", # Optional, uses default if not set
 34#     # patent_data_base_url="https://api.uspto.gov/api/v1/patent", # Optional, uses default if not set
 35# )
 36# client = PatentDataClient(config=config_obj)
 37
 38# Method 3: Initialize the client with environment variables (recommended for production)
 39# print("\nMethod 3: Initialize with environment variables")
 40# # Ensure USPTO_API_KEY is set in your environment
 41# # os.environ["USPTO_API_KEY"] = "YOUR_API_KEY_HERE" # Example, should be set outside
 42# try:
 43#     config_from_env = USPTOConfig.from_env()
 44#     client = PatentDataClient(config=config_from_env)
 45# except ValueError as e:
 46#     print(f"Error initializing from environment: {e}")
 47#     print("Please ensure USPTO_API_KEY environment variable is set.")
 48#     # Fallback to method 1 for the rest of the script if env var not set for example purposes
 49#     if 'client' not in locals(): # If client wasn't set due to error
 50#         api_key_fallback = "YOUR_API_KEY_HERE_FALLBACK"
 51#         print(f"Falling back to placeholder API key for example: {api_key_fallback}")
 52#         client = PatentDataClient(api_key=api_key_fallback)
 53
 54
 55print("\nBeginning API requests with configured client:")
 56
 57# Get some patent applications (default is 25)
 58try:
 59    print("\nAttempting to get some patent applications (default search)...")
 60    # Calling with no specific query, relying on API defaults or client defaults (e.g., limit)
 61    response = client.search_applications(limit=5)  # Example: get 5 results
 62    print(
 63        f"Found {response.count} total patent applications matching default/broad criteria."
 64    )
 65    print(
 66        f"Displaying first {len(response.patent_file_wrapper_data_bag)} applications from response:"
 67    )
 68
 69    for patent_wrapper in response.patent_file_wrapper_data_bag:
 70        app_meta = patent_wrapper.application_meta_data
 71        if app_meta:
 72            print(f"\n  Application: {patent_wrapper.application_number_text}")
 73            print(f"  Title: {app_meta.invention_title}")
 74            print(f"  Status: {app_meta.application_status_description_text}")
 75            print(f"  Filing Date: {app_meta.filing_date}")
 76
 77            if app_meta.patent_number:
 78                print(f"  Patent Number: {app_meta.patent_number}")
 79                print(f"  Grant Date: {app_meta.grant_date}")
 80
 81            if app_meta.inventor_bag:
 82                print("  Inventors:")
 83                for inventor in app_meta.inventor_bag:
 84                    name_parts = [
 85                        part
 86                        for part in [inventor.first_name, inventor.last_name]
 87                        if part
 88                    ]
 89                    print(f"    - {' '.join(name_parts).strip()}")
 90                    if inventor.correspondence_address_bag:
 91                        address = inventor.correspondence_address_bag[0]
 92                        if address.city_name and address.geographic_region_code:
 93                            print(
 94                                f"      ({address.city_name}, {address.geographic_region_code})"
 95                            )
 96
 97            if app_meta.applicant_bag:
 98                print("  Applicants:")
 99                for applicant in app_meta.applicant_bag:
100                    print(f"    - {applicant.applicant_name_text}")
101        print("-" * 20)
102
103    # Example of using the to_csv method from PatentDataResponse
104    if response.count > 0:
105        print("\nGenerating CSV for the current response (first few rows shown):")
106        csv_data = response.to_csv()
107        # Print first 3 lines of CSV (header + 2 data rows if available)
108        print("\n".join(csv_data.splitlines()[:3]))
109        # You could save this csv_data to a file:
110        # with open("patent_search_results.csv", "w", newline="", encoding="utf-8") as f:
111        # f.write(csv_data)
112        # print("\nFull CSV data saved to patent_search_results.csv (example).")
113
114
115except Exception as e:
116    print(f"Error getting patent applications: {e}")
117
118# Search for patents by inventor name using convenience _q parameter
119try:
120    print("\nSearching for patents with 'Smith' as inventor...")
121    # Changed from search_patents to search_applications with inventor_name_q
122    inventor_search_response = client.search_applications(
123        inventor_name_q="Smith", limit=2
124    )
125    print(
126        f"Found {inventor_search_response.count} patents with 'Smith' as inventor (showing up to 2)."
127    )
128    for patent_wrapper in inventor_search_response.patent_file_wrapper_data_bag:
129        if patent_wrapper.application_meta_data:
130            print(
131                f"  - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
132            )
133except Exception as e:
134    print(f"Error searching by inventor: {e}")
135
136
137# Search for patents filed in a date range using convenience _q parameters
138try:
139    print("\nSearching for patents filed in 2020...")
140    date_search_response = client.search_applications(
141        filing_date_from_q="2020-01-01", filing_date_to_q="2020-12-31", limit=2
142    )
143    print(
144        f"Found {date_search_response.count} patents filed in 2020 (showing up to 2)."
145    )
146    for patent_wrapper in date_search_response.patent_file_wrapper_data_bag:
147        if patent_wrapper.application_meta_data:
148            print(
149                f"  - App No: {patent_wrapper.application_number_text}, Filing Date: {patent_wrapper.application_meta_data.filing_date}"
150            )
151except Exception as e:
152    print(f"Error searching by date range: {e}")
153
154# Get a specific patent by application number
155app_no_to_fetch = "18045436"  # Known application number, ensure it's valid
156try:
157    print(f"\nAttempting to retrieve patent application: {app_no_to_fetch}")
158    patent_wrapper_detail = client.get_application_by_number(
159        application_number=app_no_to_fetch
160    )
161    if patent_wrapper_detail:
162        print(
163            f"Successfully retrieved: {patent_wrapper_detail.application_number_text}"
164        )
165        if patent_wrapper_detail.application_meta_data:
166            print(
167                f"Title: {patent_wrapper_detail.application_meta_data.invention_title}"
168            )
169
170        print("\nRetrieving document information...")
171        documents_bag = client.get_application_documents(
172            application_number=app_no_to_fetch
173        )
174        print(f"Found {len(documents_bag)} documents for application {app_no_to_fetch}")
175
176        if documents_bag.documents:
177            document_to_download = documents_bag.documents[0]  # Example: first document
178            print(f"\nFirst document details:")
179            print(f"  Document ID: {document_to_download.document_identifier}")
180            print(
181                f"  Document Type: {document_to_download.document_code} - {document_to_download.document_code_description_text}"
182            )
183            print(f"  Date: {document_to_download.official_date}")
184            print(f"  Direction: {document_to_download.direction_category}")
185
186            if (
187                document_to_download.document_formats
188                and document_to_download.document_identifier
189            ):
190                print("\nAttempting to download first document...")
191                download_path = "./download-example"
192                print(document_to_download.to_dict())
193                downloaded_path = client.download_document(
194                    document_format=document_to_download.document_formats[0],
195                    destination_path=download_path,
196                    overwrite=True,
197                )
198                print(f"Downloaded document to: {downloaded_path}")
199            else:
200                print(
201                    "No downloadable formats available for the first document or document identifier missing."
202                )
203        else:
204            print("No documents listed for this application.")
205
206        # Example: Download publication XML (grant or pgpub)
207        print("\nChecking for publication files (grant/pgpub XML)...")
208        if patent_wrapper_detail.grant_document_meta_data:
209            grant_metadata = patent_wrapper_detail.grant_document_meta_data
210            print(f"Grant document available: {grant_metadata.xml_file_name}")
211            print(f"  Product: {grant_metadata.product_identifier}")
212            print(f"  Created: {grant_metadata.file_create_date_time}")
213
214            # Download grant XML to downloads folder with auto-generated filename
215            print("\nDownloading grant XML...")
216            grant_path = client.download_publication(
217                printed_metadata=grant_metadata,
218                destination_path="./download-example",
219                overwrite=True,
220            )
221            print(f"Downloaded grant XML to: {grant_path}")
222
223        if patent_wrapper_detail.pgpub_document_meta_data:
224            pgpub_metadata = patent_wrapper_detail.pgpub_document_meta_data
225            print(f"\nPre-grant publication available: {pgpub_metadata.xml_file_name}")
226
227            # Download with custom filename
228            pgpub_path = client.download_publication(
229                printed_metadata=pgpub_metadata,
230                file_name="my_pgpub.xml",
231                destination_path="./download-example",
232                overwrite=True,
233            )
234            print(f"Downloaded pgpub XML to: {pgpub_path}")
235
236        if patent_wrapper_detail.assignment_bag:
237            print("\nAssignments:")
238            for assignment in patent_wrapper_detail.assignment_bag:
239                for assignee in assignment.assignee_bag:
240                    print(
241                        f"  - {assignee.assignee_name_text} (Recorded: {assignment.assignment_recorded_date})"
242                    )
243                    print(f"    Conveyance: {assignment.conveyance_text}")
244    else:
245        print(f"Could not retrieve details for application {app_no_to_fetch}")
246
247except Exception as e:
248    print(f"Error retrieving or processing patent application {app_no_to_fetch}: {e}")
249
250# Search for a specific patent by patent number (using search_applications)
251target_patent_number = "10000000"
252try:
253    print(f"\nSearching for patent US {target_patent_number} B2...")
254    patent_search_response = client.search_applications(
255        patent_number_q=target_patent_number, limit=1
256    )
257
258    if (
259        patent_search_response.count > 0
260        and patent_search_response.patent_file_wrapper_data_bag
261    ):
262        found_patent_wrapper = patent_search_response.patent_file_wrapper_data_bag[0]
263        if (
264            found_patent_wrapper.application_meta_data
265            and found_patent_wrapper.application_meta_data.patent_number
266        ):
267            print(
268                f"Retrieved patent: US {found_patent_wrapper.application_meta_data.patent_number}"
269            )
270        else:
271            print(
272                f"Retrieved patent application: {found_patent_wrapper.application_number_text}"
273            )
274
275        if found_patent_wrapper.patent_term_adjustment_data:
276            pta = found_patent_wrapper.patent_term_adjustment_data
277            print(f"Patent Term Adjustment: {pta.adjustment_total_quantity} days")
278            if pta.a_delay_quantity is not None:
279                print(f"  A Delay: {pta.a_delay_quantity} days")
280            if pta.b_delay_quantity is not None:
281                print(f"  B Delay: {pta.b_delay_quantity} days")
282            if pta.c_delay_quantity is not None:
283                print(f"  C Delay: {pta.c_delay_quantity} days")
284            if pta.applicant_day_delay_quantity is not None:
285                print(f"  Applicant Delay: {pta.applicant_day_delay_quantity} days")
286
287        # Example of getting continuity data (assuming it's part of the wrapper)
288        continuity_data = ApplicationContinuityData.from_wrapper(
289            wrapper=found_patent_wrapper
290        )
291        if continuity_data.parent_continuity_bag:
292            print("\nParent Applications:")
293            for p_continuity in continuity_data.parent_continuity_bag:
294                print(f"  - App No: {p_continuity.parent_application_number_text}")
295                print(
296                    f"    Type: {p_continuity.claim_parentage_type_code_description_text}"
297                )
298                print(f"    Filing Date: {p_continuity.parent_application_filing_date}")
299
300        if continuity_data.child_continuity_bag:
301            print("\nChild Applications:")
302            for c_continuity in continuity_data.child_continuity_bag:
303                print(f"  - App No: {c_continuity.child_application_number_text}")
304                print(
305                    f"    Type: {c_continuity.claim_parentage_type_code_description_text}"
306                )
307                print(f"    Filing Date: {c_continuity.child_application_filing_date}")
308    else:
309        print(f"No patents found with patent number: {target_patent_number}")
310
311except Exception as e:
312    print(f"Error retrieving patent by number {target_patent_number}: {e}")
313
314# Example of POST search for applications
315try:
316    print("\nAttempting POST search for applications with 'AI' in title...")
317    post_search_body = {
318        "q": "applicationMetaData.inventionTitle:AI",
319        "pagination": {"offset": 0, "limit": 2},
320    }
321    post_response = client.search_applications(post_body=post_search_body)
322    print(
323        f"Found {post_response.count} applications via POST search (showing up to 2)."
324    )
325    for patent_wrapper in post_response.patent_file_wrapper_data_bag:
326        if patent_wrapper.application_meta_data:
327            print(
328                f"  - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
329            )
330except Exception as e:
331    print(f"Error with POST search: {e}")
332
333
334# Example of getting status codes
335try:
336    print("\nGetting first 5 status codes...")
337    status_code_response = client.get_status_codes(params={"limit": 5})
338    print(
339        f"Retrieved {len(status_code_response.status_code_bag)} status codes (out of {status_code_response.count} total)."
340    )
341    for code_obj in status_code_response.status_code_bag:
342        print(f"  - Code: {code_obj.code}, Description: {code_obj.description}")
343except Exception as e:
344    print(f"Error getting status codes: {e}")