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