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}")