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 document...")
160 print(json.dumps(document_to_download.to_dict(), indent=2))
161 downloaded_path = client.download_document(
162 document_format=document_to_download.document_formats[0],
163 destination_path=DEST_PATH,
164 overwrite=True,
165 )
166 print(f"Downloaded document to: {downloaded_path}")
167 else:
168 print(
169 "No downloadable formats available for the first document or document identifier missing."
170 )
171 else:
172 print("No documents listed for this application.")
173
174 # Example: Download publication XML (grant or pgpub)
175 print("\nChecking for publication files (grant/pgpub XML)...")
176 if patent_wrapper_detail.grant_document_meta_data:
177 grant_metadata = patent_wrapper_detail.grant_document_meta_data
178 print(f"Grant document available: {grant_metadata.xml_file_name}")
179 print(f" Product: {grant_metadata.product_identifier}")
180 print(f" Created: {grant_metadata.file_create_date_time}")
181
182 # Download grant XML to downloads folder with auto-generated filename
183 print("\nDownloading grant XML...")
184 grant_path = client.download_publication(
185 printed_metadata=grant_metadata,
186 destination_path=DEST_PATH,
187 overwrite=True,
188 )
189 print(f"Downloaded grant XML to: {grant_path}")
190
191 if patent_wrapper_detail.pgpub_document_meta_data:
192 pgpub_metadata = patent_wrapper_detail.pgpub_document_meta_data
193 print(f"\nPre-grant publication available: {pgpub_metadata.xml_file_name}")
194
195 # Download with custom filename
196 pgpub_path = client.download_publication(
197 printed_metadata=pgpub_metadata,
198 file_name="my_pgpub.xml",
199 destination_path=DEST_PATH,
200 overwrite=True,
201 )
202 print(f"Downloaded pgpub XML to: {pgpub_path}")
203
204 if patent_wrapper_detail.assignment_bag:
205 print("\nAssignments:")
206 for assignment in patent_wrapper_detail.assignment_bag:
207 for assignee in assignment.assignee_bag:
208 print(
209 f" - {assignee.assignee_name_text} (Recorded: {assignment.assignment_recorded_date})"
210 )
211 print(f" Conveyance: {assignment.conveyance_text}")
212 else:
213 print(f"Could not retrieve details for application {app_no_to_fetch}")
214
215except Exception as e:
216 print(f"Error retrieving or processing patent application {app_no_to_fetch}: {e}")
217
218# Search for a specific patent by patent number (using search_applications)
219target_patent_number = "10000000"
220try:
221 print(f"\nSearching for patent US {target_patent_number} B2...")
222 patent_search_response = client.search_applications(
223 patent_number_q=target_patent_number, limit=1
224 )
225
226 if (
227 patent_search_response.count > 0
228 and patent_search_response.patent_file_wrapper_data_bag
229 ):
230 found_patent_wrapper = patent_search_response.patent_file_wrapper_data_bag[0]
231 if (
232 found_patent_wrapper.application_meta_data
233 and found_patent_wrapper.application_meta_data.patent_number
234 ):
235 print(
236 f"Retrieved patent: US {found_patent_wrapper.application_meta_data.patent_number}"
237 )
238 else:
239 print(
240 f"Retrieved patent application: {found_patent_wrapper.application_number_text}"
241 )
242
243 if found_patent_wrapper.patent_term_adjustment_data:
244 pta = found_patent_wrapper.patent_term_adjustment_data
245 print(f"Patent Term Adjustment: {pta.adjustment_total_quantity} days")
246 if pta.a_delay_quantity is not None:
247 print(f" A Delay: {pta.a_delay_quantity} days")
248 if pta.b_delay_quantity is not None:
249 print(f" B Delay: {pta.b_delay_quantity} days")
250 if pta.c_delay_quantity is not None:
251 print(f" C Delay: {pta.c_delay_quantity} days")
252 if pta.applicant_day_delay_quantity is not None:
253 print(f" Applicant Delay: {pta.applicant_day_delay_quantity} days")
254
255 # Example of getting continuity data (assuming it's part of the wrapper)
256 continuity_data = ApplicationContinuityData.from_wrapper(
257 wrapper=found_patent_wrapper
258 )
259 if continuity_data.parent_continuity_bag:
260 print("\nParent Applications:")
261 for p_continuity in continuity_data.parent_continuity_bag:
262 print(f" - App No: {p_continuity.parent_application_number_text}")
263 print(
264 f" Type: {p_continuity.claim_parentage_type_code_description_text}"
265 )
266 print(f" Filing Date: {p_continuity.parent_application_filing_date}")
267
268 if continuity_data.child_continuity_bag:
269 print("\nChild Applications:")
270 for c_continuity in continuity_data.child_continuity_bag:
271 print(f" - App No: {c_continuity.child_application_number_text}")
272 print(
273 f" Type: {c_continuity.claim_parentage_type_code_description_text}"
274 )
275 print(f" Filing Date: {c_continuity.child_application_filing_date}")
276 else:
277 print(f"No patents found with patent number: {target_patent_number}")
278
279except Exception as e:
280 print(f"Error retrieving patent by number {target_patent_number}: {e}")
281
282# Example of POST search for applications
283try:
284 print("\nAttempting POST search for applications with 'AI' in title...")
285 post_search_body = {
286 "q": "applicationMetaData.inventionTitle:AI",
287 "pagination": {"offset": 0, "limit": 2},
288 }
289 post_response = client.search_applications(post_body=post_search_body)
290 print(
291 f"Found {post_response.count} applications via POST search (showing up to 2)."
292 )
293 for patent_wrapper in post_response.patent_file_wrapper_data_bag:
294 if patent_wrapper.application_meta_data:
295 print(
296 f" - App No: {patent_wrapper.application_number_text}, Title: {patent_wrapper.application_meta_data.invention_title}"
297 )
298except Exception as e:
299 print(f"Error with POST search: {e}")
300
301
302# Example of getting status codes
303try:
304 print("\nGetting first 5 status codes...")
305 status_code_response = client.get_status_codes(params={"limit": 5})
306 print(
307 f"Retrieved {len(status_code_response.status_code_bag)} status codes (out of {status_code_response.count} total)."
308 )
309 for code_obj in status_code_response.status_code_bag:
310 print(f" - Code: {code_obj.code}, Description: {code_obj.description}")
311except Exception as e:
312 print(f"Error getting status codes: {e}")