Using an SEC EDGAR API with Python starts with a small, clear request: identify a company, send the query, and inspect what comes back. Once you understand those pieces, you can decide how the filing records fit into a research notebook, an internal dashboard, or another application.
This guide uses SEC Filing Data’s third-party API to query EDGAR-sourced records for Apple. You will configure authentication, make a request, inspect its JSON response, and request another page. You need basic Python familiarity, but no experience with this API.
1. Understand what this SEC EDGAR API returns
SEC Filing Data provides a filing-search service alongside other data capabilities. Its SEC Filings API service page explains the broader product. Here, the goal is to find filing records and understand the request workflow before building anything around them.
Keep the provider distinction clear. SEC Filing Data is not affiliated with or approved by the SEC. The SEC also operates its own public data APIs, which the official SEC API overview says do not require authentication or API keys. The token used in this tutorial belongs to SEC Filing Data.
A filing-search response is a starting point for working with disclosures. Finding a record does not automatically extract revenue, calculate a ratio, or turn a filing into a financial model. Decide first whether your task needs information about filings or information contained inside them.
For this exercise, start with company identification. We will use Apple’s CIK, 320193, as a string throughout. Keeping the identifier in one place makes it easier to compare requests and avoids changing companies halfway through the example.
2. Prepare Python and install Requests
Use a Python 3 environment where you can install packages and run a script. Requests is the only third-party package needed for the examples. The other imports come from Python’s standard library.
Run this command in your terminal:
python -m pip install requests
Using python -m pip helps install the package for the interpreter selected by that command. If you work in a virtual environment, activate it first. In a notebook, make sure its kernel uses the environment where Requests is installed.
Create a file named apple_filings.py. Add the Python blocks below to that file in order. Alternatively, run them in consecutive cells in the same notebook. Later blocks reuse variables and a function introduced in the first block.
Before running the script, you will need network access to the API and a valid token. A successful package installation only prepares the client; it does not establish access to filing data.
3. Obtain and configure your API token
Create or sign into your SEC Filing Data account, ensure API access is active, and generate a key through the account’s key-management interface. The SEC Filing Data API guide describes these onboarding requirements. Store the issued token securely before moving to Python.
Set SEC_FILING_DATA_TOKEN in your terminal using the command for your operating system. Replace YOUR_API_TOKEN with your issued token.
On macOS or Linux, using Bash or Zsh:
export SEC_FILING_DATA_TOKEN="YOUR_API_TOKEN"
On Windows, using PowerShell:
$env:SEC_FILING_DATA_TOKEN = "YOUR_API_TOKEN"
Run the script from the same terminal session so Python inherits the variable. These commands set it for that session. If you use a notebook, launch it from the configured terminal so its kernel can inherit the value.
The example reads that variable rather than placing a credential in the script. This lets you share the code without sharing the token. Keep credentials out of notebook output, screenshots, source control, and logs as well.
For the Query API, the endpoint-specific documentation shows Authorization: AUTH_TOKEN: the token itself is the header value. Its examples do not add Bearer. The request below follows that documented example.
Match authentication, parameters, and response handling to the endpoint you actually call.
4. Query SEC filings with Python
The operation below sends a JSON body to the Query API. The required pair is query_type and query_value; our example selects cik and Apple’s identifier. It starts at offset zero and requests ten records.
import os
import requests
url = "https://api.secfilingdata.com/v1/filings/query"
token = os.environ["SEC_FILING_DATA_TOKEN"]
headers = {
"Authorization": token,
"Content-Type": "application/json",
}
payload = {
"query_type": "cik",
"query_value": "320193",
"from": 0,
"size": 10,
}
def query_filings(body):
response = requests.post(
url, headers=headers, json=body, timeout=30
)
response.raise_for_status()
if response.status_code == 204:
return None
return response.json()
data = query_filings(payload)
print("No results." if data is None else "JSON response received.")
Requests handles JSON encoding through json=body. The timeout prevents the script from waiting indefinitely for network activity; it is a client choice, not a service response-time guarantee. The function keeps the request and response handling together so page two can reuse them.
Supported search types include ticker, companyName, formType, sic, fileNo, and accessNum. Optional controls include from, size up to 100, and sort_order with ASC or DESC. The SEC Query API documentation lists the accepted values and request examples.
This first request keeps the search simple: one company identifier, a starting offset, and a page size. It leaves sorting and additional filters out so you can inspect the basic response first.
Save the file, then run this command from its folder in the terminal where you configured the token:
python apple_filings.py
If the request succeeds with a JSON body, the final line confirms receipt. The next step is to inspect its structure and contents. As you add the later blocks, save and rerun the file to include those steps.
5. Inspect the JSON response before extracting fields
JSON can become a Python dictionary, list, or another value. Start by checking the returned structure before writing field-specific code. This is especially useful when adapting an unfamiliar API to an existing workflow.
import json
if data is None:
print("No response body to inspect.")
else:
print("Top-level type:", type(data).__name__)
if isinstance(data, dict):
print("Top-level keys:", list(data))
elif isinstance(data, list):
print("Top-level list length:", len(data))
print(json.dumps(data, indent=2)[:2000])
This prints the top-level type and a preview capped at 2,000 characters. The cap keeps initial output manageable. It truncates the display, so the preview may end halfway through a JSON value; the complete parsed response remains in data.
The inspection stays schema-neutral because the public reference does not define an explicit response schema. A dictionary’s length counts keys, not filings; examine the values to locate the records before extracting fields.
After inspecting your real response, identify where the records sit and which fields your task requires. Then write a small extraction step against those observed fields. Preserve the original response while developing that step so you can revisit its structure if an assumption proves wrong.
6. Request another page of results
API pagination separates a search into smaller requests. With a requested size of ten, the next page starts at offset ten. Keep the company identifier and page size unchanged so you are continuing the same search.
next_payload = {**payload, "from": 10}
next_data = query_filings(next_payload)
print("No results on page two." if next_data is None
else "Page-two JSON response received.")
Creating a new dictionary preserves the original first-page payload. This makes it easier to reproduce either request while comparing responses. The variable next_data also keeps page two separate from the first response.
Inspect next_data using the same approach as before, then identify the record collection before combining pages. Keep the search values and offsets with your results so you can reproduce the requests.
This example requests page two. Before extending it into an automatic collection loop, confirm the service’s final-page condition and ordering behavior; the public reference does not fully specify them.
7. Handle common request and response problems
Troubleshooting is easier when you identify the stage that failed: local setup, network access, HTTP response, or JSON decoding. Resolve that stage before changing the search itself.
Missing package or environment variable
ModuleNotFoundError for Requests means the running interpreter cannot import the package. Check the interpreter or notebook kernel and install Requests in that environment.
A KeyError naming SEC_FILING_DATA_TOKEN means Python cannot find the configured variable. Set it in the launching environment and rerun. This happens before the API request, so changing the endpoint or search parameters will not fix it.
HTTP errors and no results
Use the documented HTTP status to identify what happened:
| Status | Meaning |
|---|---|
| 200 | Successful request |
| 204 | No results found |
| 400 | Invalid request parameters |
| 401 | Unauthorized or invalid token |
| 500 | Internal server error |
For 400, compare the request values and types with the reference. For 401, check the token, header format, and active API access. Avoid printing the authorization header while debugging. For 500, a later retry may be appropriate; repeatedly changing a valid company identifier is unlikely to help.
raise_for_status() raises an HTTP error for unsuccessful HTTP statuses, but a 204 is successful at the HTTP level. The function therefore checks it separately and returns None without attempting JSON decoding.
Network failures or invalid JSON
A timeout or connection exception means the client could not complete the exchange normally. Check connectivity and retry deliberately. Avoid putting an unlimited retry loop around a failing request.
If JSON decoding fails, the response body could not be parsed as JSON. Review the HTTP status and content type first. Inspect any diagnostic body locally and cautiously, since it may contain account or request details. A valid HTTP exchange and a usable JSON response are separate checks.
8. Decide how to use the returned records next
Once you understand the response, choose a small next task: display selected record details, organize a research queue, or pass confirmed identifiers to another processing step. Build around fields you have verified rather than importing assumptions from another provider’s examples.
Keep any available source references alongside the information you extract. This helps a reader or colleague trace your application’s output back to the underlying disclosure. If your task requires financial values or filing sections, evaluate the appropriate capability separately.
Before moving from evaluation to an application, check permitted use and access conditions. The SEC Filings API pricing and licensing plans distinguish evaluation and internal-use plans from commercial and external publishing rights.
You now have a manageable request workflow: configure access, query Apple, inspect the returned JSON, and request another page. Use those steps as the foundation for your own processing, with the response structure and pagination behavior confirmed before expanding the scope.
