PTAB Appeals Example

  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)