1"""
2Example usage of the pyUSPTO module for PTAB Appeals API
3
4This example demonstrates how to use the PTABAppealsClient to interact with the USPTO PTAB
5(Patent Trial and Appeal Board) Appeals API. It shows how to search for ex parte appeal
6decisions using various search criteria.
7
8PTAB Appeals include ex parte appeals from patent application examinations to the Board.
9"""
10
11import os
12
13from pyUSPTO import PTABAppealsClient, USPTOConfig
14
15# --- Initialization ---
16# Choose one method to initialize the client.
17# For this example, Method 1 is active. Replace "YOUR_API_KEY_HERE" with your actual key.
18
19# Method 1: Initialize the client with direct API key
20print("Method 1: Initialize with direct API key")
21api_key = os.environ.get("USPTO_API_KEY", "YOUR_API_KEY_HERE")
22if api_key == "YOUR_API_KEY_HERE":
23 raise ValueError(
24 "WARNING: API key is not set. Please replace 'YOUR_API_KEY_HERE' or set USPTO_API_KEY environment variable."
25 )
26client = PTABAppealsClient(api_key=api_key)
27
28# Method 2: Initialize the client with USPTOConfig (alternative)
29# print("\nMethod 2: Initialize with USPTOConfig")
30# config_obj = USPTOConfig(
31# api_key="YOUR_API_KEY_HERE", # Replace with your actual API key
32# ptab_base_url="https://api.uspto.gov", # Optional, uses default if not set
33# )
34# client = PTABAppealsClient(config=config_obj)
35
36# Method 3: Initialize the client with environment variables (recommended for production)
37# print("\nMethod 3: Initialize with environment variables")
38# # Ensure USPTO_API_KEY is set in your environment
39# try:
40# config_from_env = USPTOConfig.from_env()
41# client = PTABAppealsClient(config=config_from_env)
42# except ValueError as e:
43# print(f"Error initializing from environment: {e}")
44# print("Please ensure USPTO_API_KEY environment variable is set.")
45
46print("\nBeginning PTAB Appeals API requests with configured client:")
47
48# =============================================================================
49# 1. Search Appeal Decisions by Technology Center
50# =============================================================================
51
52print("\n" + "=" * 80)
53print("1. Searching for appeal decisions by technology center")
54print("=" * 80)
55
56try:
57 # Search for decisions from Technology Center 3600 (Business Methods/Software)
58 response = client.search_decisions(
59 technology_center_number_q="3600",
60 decision_date_from_q="2023-01-01",
61 decision_date_to_q="2023-12-31",
62 limit=5,
63 )
64
65 print(f"\nFound {response.count} appeal decisions from TC 3600 in 2023")
66 print(f"Displaying first {len(response.patent_appeal_data_bag)} results:")
67
68 for decision in response.patent_appeal_data_bag:
69 print(f"\n Appeal Number: {decision.appeal_number}")
70
71 if decision.appeal_meta_data:
72 meta = decision.appeal_meta_data
73 print(f" Application Type: {meta.application_type_category}")
74 print(f" Filing Date: {meta.appeal_filing_date}")
75
76 if decision.appellant_data:
77 appellant = decision.appellant_data
78 print(f" Application Number: {appellant.application_number_text}")
79 print(f" Technology Center: {appellant.technology_center_number}")
80
81 if appellant.inventor_name:
82 print(f" Inventor: {appellant.inventor_name}")
83
84 if decision.decision_data:
85 dec = decision.decision_data
86 print(f" Decision Type: {dec.decision_type_category}")
87 print(f" Decision Date: {dec.decision_issue_date}")
88
89except Exception as e:
90 print(f"Error searching appeal decisions: {e}")
91
92# =============================================================================
93# 2. Search by Decision Type
94# =============================================================================
95
96print("\n" + "=" * 80)
97print("2. Searching for 'Affirmed' decisions")
98print("=" * 80)
99
100try:
101 # Search for decisions where the examiner was affirmed
102 response = client.search_decisions(
103 decision_type_category_q="Affirmed",
104 decision_date_from_q="2024-01-01",
105 limit=5,
106 )
107
108 print(f"\nFound {response.count} 'Affirmed' decisions since 2024")
109 print(f"Displaying first {len(response.patent_appeal_data_bag)} results:")
110
111 for decision in response.patent_appeal_data_bag:
112 print(f"\n Appeal Number: {decision.appeal_number}")
113
114 if decision.appellant_data:
115 print(f" Application: {decision.appellant_data.application_number_text}")
116 print(f" Inventor: {decision.appellant_data.inventor_name or 'N/A'}")
117
118 if decision.decision_data:
119 print(f" Decision: {decision.decision_data.decision_type_category}")
120 print(f" Date: {decision.decision_data.decision_issue_date}")
121
122except Exception as e:
123 print(f"Error searching by decision type: {e}")
124
125# =============================================================================
126# 3. Search by Application Number
127# =============================================================================
128
129print("\n" + "=" * 80)
130print("3. Searching for decisions by application number pattern")
131print("=" * 80)
132
133try:
134 # Search for decisions related to applications starting with "15/"
135 response = client.search_decisions(
136 application_number_text_q="15/*",
137 decision_date_from_q="2023-01-01",
138 limit=3,
139 )
140
141 print(f"\nFound {response.count} decisions for applications starting with '15/'")
142 print(f"Displaying first {len(response.patent_appeal_data_bag)} results:")
143
144 for decision in response.patent_appeal_data_bag:
145 print(f"\n Appeal Number: {decision.appeal_number}")
146
147 if decision.appellant_data:
148 print(f" Application: {decision.appellant_data.application_number_text}")
149 print(f" TC Number: {decision.appellant_data.technology_center_number}")
150
151 if decision.document_data:
152 doc = decision.document_data
153 print(f" Document Name: {doc.document_name}")
154 if doc.file_download_uri:
155 print(f" Download URL: {doc.file_download_uri}")
156
157except Exception as e:
158 print(f"Error searching by application number: {e}")
159
160# =============================================================================
161# 4. Pagination Example
162# =============================================================================
163
164print("\n" + "=" * 80)
165print("4. Paginating through appeal decisions")
166print("=" * 80)
167
168try:
169 print("\nIterating through first 10 appeal decisions from 2024...")
170 count = 0
171 for decision in client.paginate_decisions(
172 decision_date_from_q="2024-01-01",
173 limit=5, # Fetch 5 per page
174 ):
175 count += 1
176 decision_type = (
177 decision.decision_data.decision_type_category
178 if decision.decision_data
179 else "N/A"
180 )
181 print(f"{count}. {decision.appeal_number} - {decision_type}")
182
183 if count >= 10: # Stop after 10 results for this example
184 break
185
186 print(f"\nDisplayed {count} decisions using pagination")
187
188except Exception as e:
189 print(f"Error paginating decisions: {e}")
190
191# =============================================================================
192# 5. Advanced Search with Multiple Criteria
193# =============================================================================
194
195print("\n" + "=" * 80)
196print("5. Advanced search with multiple criteria")
197print("=" * 80)
198
199try:
200 # Search with multiple convenience parameters
201 response = client.search_decisions(
202 technology_center_number_q="2100", # Electronics
203 decision_type_category_q="Reversed",
204 decision_date_from_q="2023-01-01",
205 decision_date_to_q="2023-12-31",
206 sort="decisionDate desc",
207 limit=3,
208 )
209
210 print(
211 f"\nFound {response.count} 'Reversed' decisions from TC 2100 (Electronics) in 2023"
212 )
213 print(f"Displaying first {len(response.patent_appeal_data_bag)} results:")
214
215 for decision in response.patent_appeal_data_bag:
216 print(f"\n Appeal Number: {decision.appeal_number}")
217
218 if decision.appellant_data:
219 print(f" Application: {decision.appellant_data.application_number_text}")
220
221 if decision.decision_data:
222 print(f" Decision: {decision.decision_data.decision_type_category}")
223 print(f" Date: {decision.decision_data.decision_issue_date}")
224
225except Exception as e:
226 print(f"Error with advanced search: {e}")
227
228# =============================================================================
229# 6. Direct Query String Example
230# =============================================================================
231
232print("\n" + "=" * 80)
233print("6. Using direct query string for complex searches")
234print("=" * 80)
235
236try:
237 # Use a direct query string for more complex searches
238 response = client.search_decisions(
239 query="technologyCenterNumber:3600 AND decisionTypeCategory:(Affirmed OR Reversed)",
240 limit=3,
241 )
242
243 print(f"\nFound {response.count} Affirmed/Reversed decisions from TC 3600")
244 print(f"Displaying first {len(response.patent_appeal_data_bag)} results:")
245
246 for decision in response.patent_appeal_data_bag:
247 print(f"\n Appeal Number: {decision.appeal_number}")
248
249 if decision.decision_data:
250 print(f" Decision: {decision.decision_data.decision_type_category}")
251
252except Exception as e:
253 print(f"Error with direct query: {e}")
254
255# =============================================================================
256# 7. Error Handling Example
257# =============================================================================
258
259print("\n" + "=" * 80)
260print("7. Error handling demonstration")
261print("=" * 80)
262
263try:
264 # Attempt a search that might return no results
265 print("\nAttempting search with unlikely parameters...")
266 response = client.search_decisions(
267 appeal_number_q="INVALID-APPEAL-NUMBER",
268 limit=1,
269 )
270
271 if response.count == 0:
272 print("No results found for the given search criteria")
273 else:
274 print(f"Found {response.count} results")
275
276except Exception as e:
277 print(f"Expected error occurred: {type(e).__name__}: {e}")
278
279print("\n" + "=" * 80)
280print("PTAB Appeals API example completed successfully!")
281print("=" * 80)