Skip to content

Commit 30ce5a9

Browse files
improved error handling + backoff strategy
1 parent 6df77c7 commit 30ce5a9

2 files changed

Lines changed: 33 additions & 37 deletions

File tree

sec_api/index.py

Lines changed: 32 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
exec_comp_api_endpoint = "https://api.sec-api.io/compensation"
1313

1414

15+
def handle_api_error(response):
16+
raise Exception("API error: {} - {}".format(response.status_code, response.text))
17+
18+
1519
class QueryApi:
1620
"""
1721
Base class for Query API
@@ -22,6 +26,8 @@ def __init__(self, api_key):
2226
self.api_endpoint = query_api_endpoint + "?token=" + api_key
2327

2428
def get_filings(self, query):
29+
response = {}
30+
2531
# use backoff strategy to handle "too many requests" error.
2632
for x in range(3):
2733
response = requests.post(self.api_endpoint, json=query)
@@ -31,12 +37,9 @@ def get_filings(self, query):
3137
# wait 500 * (x + 1) milliseconds and try again
3238
time.sleep(0.5 * (x + 1))
3339
else:
34-
raise Exception(
35-
"API error: " + str(response.status_code) + " - " + response.text
36-
)
40+
handle_api_error(response)
3741
else:
38-
# request failed
39-
raise Exception("API error")
42+
handle_api_error(response)
4043

4144

4245
class FullTextSearchApi:
@@ -49,6 +52,8 @@ def __init__(self, api_key):
4952
self.api_endpoint = full_text_search_api_endpoint + "?token=" + api_key
5053

5154
def get_filings(self, query):
55+
response = {}
56+
5257
# use backoff strategy to handle "too many requests" error.
5358
for x in range(3):
5459
response = requests.post(self.api_endpoint, json=query)
@@ -58,12 +63,9 @@ def get_filings(self, query):
5863
# wait 500 * (x + 1) milliseconds and try again
5964
time.sleep(0.5 * (x + 1))
6065
else:
61-
raise Exception(
62-
"API error: " + str(response.status_code) + " - " + response.text
63-
)
66+
handle_api_error(response)
6467
else:
65-
# request failed
66-
raise Exception("API error")
68+
handle_api_error(response)
6769

6870

6971
class RenderApi:
@@ -76,6 +78,7 @@ def __init__(self, api_key):
7678
self.api_endpoint = render_api_endpoint
7779

7880
def get_filing(self, url):
81+
response = {}
7982
filename = re.sub(r"https://www.sec.gov/Archives/edgar/data", "", url)
8083
_url = self.api_endpoint + filename + "?token=" + self.api_key
8184

@@ -88,12 +91,9 @@ def get_filing(self, url):
8891
# wait 500 * (x + 1) milliseconds and try again
8992
time.sleep(0.5 * (x + 1))
9093
else:
91-
raise Exception(
92-
"API error: " + str(response.status_code) + " - " + response.text
93-
)
94+
handle_api_error(response)
9495
else:
95-
# request failed
96-
raise Exception("API error")
96+
handle_api_error(response)
9797

9898

9999
class XbrlApi:
@@ -110,6 +110,7 @@ def xbrl_to_json(self, htm_url="", xbrl_url="", accession_no=""):
110110
raise ValueError("htm_url, xbrl_url or accession_no must be present")
111111

112112
_url = ""
113+
response = {}
113114

114115
if len(htm_url):
115116
_url = self.api_endpoint + "&htm-url=" + htm_url
@@ -123,19 +124,17 @@ def xbrl_to_json(self, htm_url="", xbrl_url="", accession_no=""):
123124
# use backoff strategy to handle "too many requests" error.
124125
for x in range(3):
125126
response = requests.get(_url)
127+
126128
if response.status_code == 200:
127129
data = json.loads(response.text)
128130
return data
129131
elif response.status_code == 429:
130132
# wait 500 * (x + 1) milliseconds and try again
131133
time.sleep(0.5 * (x + 1))
132134
else:
133-
raise Exception(
134-
"API error: " + str(response.status_code) + " - " + response.text
135-
)
135+
handle_api_error(response)
136136
else:
137-
# request failed
138-
raise Exception("API error")
137+
handle_api_error(response)
139138

140139

141140
class ExtractorApi:
@@ -151,6 +150,7 @@ def get_section(self, filing_url="", section="1A", return_type="text"):
151150
if len(filing_url) == 0:
152151
raise ValueError("filing_url must be present")
153152

153+
response = {}
154154
_url = (
155155
self.api_endpoint
156156
+ "&url="
@@ -162,20 +162,18 @@ def get_section(self, filing_url="", section="1A", return_type="text"):
162162
)
163163

164164
# use backoff strategy to handle "too many requests" error.
165-
for x in range(3):
165+
for x in range(5):
166166
response = requests.get(_url)
167+
167168
if response.status_code == 200:
168169
return response.text
169170
elif response.status_code == 429:
170171
# wait 500 * (x + 1) milliseconds and try again
171172
time.sleep(0.5 * (x + 1))
172173
else:
173-
raise Exception(
174-
"API error: " + str(response.status_code) + " - " + response.text
175-
)
174+
handle_api_error(response)
176175
else:
177-
# request failed
178-
raise Exception("API error")
176+
handle_api_error(response)
179177

180178

181179
class MappingApi:
@@ -203,6 +201,7 @@ def resolve(self, parameter="", value=""):
203201
if not parameter.lower() in self.supported_parameters:
204202
raise ValueError("Parameter not supported")
205203

204+
response = {}
206205
_url = (
207206
self.api_endpoint
208207
+ "/"
@@ -216,18 +215,16 @@ def resolve(self, parameter="", value=""):
216215
# use backoff strategy to handle "too many requests" error.
217216
for x in range(3):
218217
response = requests.get(_url)
218+
219219
if response.status_code == 200:
220220
return response.json()
221221
elif response.status_code == 429:
222222
# wait 500 * (x + 1) milliseconds and try again
223223
time.sleep(0.5 * (x + 1))
224224
else:
225-
raise Exception(
226-
"API error: " + str(response.status_code) + " - " + response.text
227-
)
225+
handle_api_error(response)
228226
else:
229-
# request failed
230-
raise Exception("API error")
227+
handle_api_error(response)
231228

232229

233230
class ExecCompApi:
@@ -248,6 +245,8 @@ def get_data(self, parameter=""):
248245
else:
249246
raise Exception("Invalid parameter")
250247

248+
response = {}
249+
251250
# use backoff strategy to handle "too many requests" error.
252251
for x in range(3):
253252
if http_method == "GET":
@@ -269,9 +268,6 @@ def get_data(self, parameter=""):
269268
# wait 500 * (x + 1) milliseconds and try again
270269
time.sleep(0.5 * (x + 1))
271270
else:
272-
raise Exception(
273-
"API error: " + str(response.status_code) + " - " + response.text
274-
)
271+
handle_api_error(response)
275272
else:
276-
# request failed
277-
raise Exception("API error")
273+
handle_api_error(response)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="sec-api",
8-
version="1.0.11",
8+
version="1.0.12",
99
author="SEC API",
1010
author_email="support@sec-api.io",
1111
description="SEC EDGAR Filings API",

0 commit comments

Comments
 (0)