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