EdgarKit API
A clean, real-time JSON API for SEC EDGAR Form 3, 4, and 5 insider trading filings. Stop scraping SEC's HTML. Stop parsing XML. Start building.
https://api.edgarkit.comVersion: v1 (path prefix
/v1)Format: JSON
Auth: Bearer token in
Authorization header
What's in the data
- Form 3 — initial statement of beneficial ownership (when an insider relationship begins)
- Form 4 — changes in ownership (the main one — buys, sells, grants, options exercises)
- Form 4/A — amendments to a previously filed Form 4
- Form 5 — annual statement of changes (catches anything missed during the year)
How fresh is it
EdgarKit polls SEC EDGAR every 30 seconds. End-to-end latency from SEC publishing a filing to it being queryable through our API is 30 to 60 seconds. Webhooks fire within that same window.
How far back
The API contains historical filings going back approximately 2 years from the date you read this. Older history can be added on request — reach out.
Quickstart
- Get an API key — Sign up at edgarkit.com. Instant. No credit card needed.
-
Make your first request
curl "https://api.edgarkit.com/v1/companies/NVDA/filings?limit=5" \ -H "Authorization: Bearer $EDGARKIT_KEY" - Optionally register a webhook — Get pinged the moment a filing matches your filters. See Webhook setup.
Try it now
No API key needed. Enter a ticker symbol below and run a live query against the EdgarKit API.
Authentication
All API requests require a bearer token in the Authorization header.
Authorization: Bearer ek_live_xxxxxxxxxxxxxxxxxxxxxxxx
Key safety
- Treat your key like a password. Never commit it to source control.
- Use environment variables:
process.env.EDGARKIT_KEYin Node,os.getenv('EDGARKIT_KEY')in Python. - If your key leaks, rotate it from the dashboard. Old keys are immediately invalidated.
Key prefixes
ek_live_— production trafficek_test_— sandbox (coming soon)
Rate limits
Rate limits are enforced per API key. Limits depend on your plan.
| Plan | Requests/min | Requests/month | Webhooks |
|---|---|---|---|
| Free | 10 | 1,000 | — |
| Basic ($19/mo) | 60 | 25,000 | 1 endpoint |
| Pro ($79/mo) | 300 | 250,000 | 10 endpoints |
Response headers
Every response includes:
X-RateLimit-Limit— your plan's per-minute limitX-RateLimit-Remaining— calls left in the current minuteX-RateLimit-Reset— Unix timestamp when the window resets
When you hit the limit
You'll get a 429 Too Many Requests with a Retry-After header (in seconds). Back off and retry.
Errors
EdgarKit returns standard HTTP status codes plus a JSON body with an error code and message.
{
"error": {
"code": "not_found",
"message": "No filing with accession 0001234567-26-000001"
}
}
| HTTP | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Bad query params or body |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | Feature requires a higher plan |
| 404 | not_found | The resource doesn't exist |
| 429 | rate_limit_exceeded | Slow down |
| 500 | internal_error | Our bug. Email support@edgarkit.com |
List filings
/v1/filingsList recent filings across all companies. Supports filtering and pagination.
Query parameters
form_type | string | Filter by form type: 3, 4, 4/A, or 5 |
issuer_cik | integer | Filter by issuing company's CIK |
reporter_cik | integer | Filter by reporting insider's CIK |
transaction_code | string | Filter by transaction code (S, P, A, etc.) |
filed_after | date | YYYY-MM-DD, inclusive (start of day UTC) |
filed_before | date | YYYY-MM-DD, inclusive (end of day UTC) |
limit | integer | Max 100, default 25 |
offset | integer | For pagination |
Example
curl "https://api.edgarkit.com/v1/filings?form_type=4&transaction_code=S&limit=10" \
-H "Authorization: Bearer $EDGARKIT_KEY"
Filing detail
/v1/filings/:accessionGet the full structured filing including every transaction, prices, ownership flags, and footnotes.
Example
curl "https://api.edgarkit.com/v1/filings/0001768670-26-000002" \
-H "Authorization: Bearer $EDGARKIT_KEY"
Company
/v1/companies/:identifierLook up a company by ticker (e.g. NVDA) or CIK (e.g. 1045810). Returns name, CIK, ticker, SIC industry.
Company filings
/v1/companies/:identifier/filingsAll filings for one company. Same query params as List filings.
curl "https://api.edgarkit.com/v1/companies/AAPL/filings?limit=20" \
-H "Authorization: Bearer $EDGARKIT_KEY"
Insider
/v1/insiders/:cikLook up an insider by CIK. Returns name and their full filing history.
Insider filings
/v1/insiders/:cik/filingsAll filings by one insider over time. Great for tracking specific directors or activists.
curl "https://api.edgarkit.com/v1/insiders/1768670/filings" \
-H "Authorization: Bearer $EDGARKIT_KEY"
Webhooks
/v1/webhooksRegister a webhook with filters. EdgarKit will POST to your URL within ~30-60 seconds of SEC publishing a matching filing.
Request body
{
"url": "https://yourapp.com/edgarkit-webhook",
"filter": {
"tickers": ["AAPL", "NVDA"],
"form_types": ["4"],
"transaction_codes": ["S", "P"],
"min_value": 1000000
}
}
See Webhook setup for the full guide.
Webhook setup
Webhooks are how you get pushed notifications when filings match your criteria. Available on Basic and Pro plans.
Register a webhook
curl "https://api.edgarkit.com/v1/webhooks" -X POST \
-H "Authorization: Bearer $EDGARKIT_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/edgarkit-webhook",
"filter": {
"tickers": ["AAPL"],
"transaction_codes": ["S"],
"min_value": 1000000
}
}'
What you receive
When a filing matches, we POST the full filing object plus a signature header. Your endpoint should respond with a 2xx within 10 seconds.
Retry behavior
If your endpoint returns non-2xx or times out, we retry with exponential backoff: 30s, 2m, 10m, 1h, 6h. After 5 failures we mark the delivery as failed and surface it in your dashboard.
Filter fields
tickers— array of ticker symbolsciks— array of CIKs (issuer or reporter)form_types— array, e.g.["4", "4/A"]transaction_codes— array, e.g.["S", "P"]min_value— minimum total transaction value in dollars
Verifying HMAC signatures
Every webhook POST includes X-EdgarKit-Signature and X-EdgarKit-Timestamp headers. Always verify these before trusting the payload.
Node.js
// Express middleware
const crypto = require('crypto');
function verify(req) {
const sig = req.headers['x-edgarkit-signature'];
const ts = req.headers['x-edgarkit-timestamp'];
const body = JSON.stringify(req.body);
const expected = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(ts + '.' + body)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}
Python
import hmac, hashlib, os
def verify(request):
sig = request.headers['X-EdgarKit-Signature']
ts = request.headers['X-EdgarKit-Timestamp']
body = request.body.decode()
expected = hmac.new(
os.environ['WEBHOOK_SECRET'].encode(),
(ts + '.' + body).encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(sig, expected)
Pagination
All list endpoints use limit/offset pagination.
# Page 1: first 100 results
curl "https://api.edgarkit.com/v1/filings?limit=100&offset=0" -H ...
# Page 2: next 100
curl "https://api.edgarkit.com/v1/filings?limit=100&offset=100" -H ...
Responses include a pagination object with limit, offset, and count (rows returned in this page).
Form types explained
| Form | What it is | When filed |
|---|---|---|
3 | Initial statement of beneficial ownership | Within 10 days of becoming an insider |
4 | Statement of changes in beneficial ownership | Within 2 business days of transaction |
4/A | Amendment to a previously filed Form 4 | When correcting an error |
5 | Annual statement of changes | Within 45 days of fiscal year-end |
Transaction codes
The transaction_code field on each transaction tells you what happened. Most common:
| Code | Meaning |
|---|---|
P | Open-market purchase |
S | Open-market sale |
A | Grant or award (e.g. RSU vesting) |
D | Sale back to issuer |
F | Shares withheld for tax |
M | Exercise of derivative (option exercise) |
G | Gift |
X | Exercise of in-the-money derivative |
C | Conversion of derivative |
I | Discretionary transaction |
P (purchase) and S (sale) are usually what people care about. A is mostly noise from RSU vesting.
Node.js example
// npm install undici
import { fetch } from 'undici';
const KEY = process.env.EDGARKIT_KEY;
async function getRecentSales(ticker) {
const res = await fetch(
`https://api.edgarkit.com/v1/companies/${ticker}/filings?limit=10`,
{ headers: { Authorization: `Bearer ${KEY}` } }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}
getRecentSales('NVDA').then(({ data }) => {
data.forEach(f => console.log(f.filed_at, f.reporter.name, f.issuer.ticker));
});
Python example
# pip install requests
import os, requests
KEY = os.environ['EDGARKIT_KEY']
def get_recent_sales(ticker):
r = requests.get(
f'https://api.edgarkit.com/v1/companies/{ticker}/filings',
headers={'Authorization': f'Bearer {KEY}'},
params={'limit': 10},
)
r.raise_for_status()
return r.json()
for f in get_recent_sales('NVDA')['data']:
print(f['filed_at'], f['reporter']['name'], f['issuer']['ticker'])
curl example
export EDGARKIT_KEY=ek_live_xxxxx
# Recent NVDA insider activity
curl "https://api.edgarkit.com/v1/companies/NVDA/filings?limit=10" \
-H "Authorization: Bearer $EDGARKIT_KEY" | jq
# Filing detail
curl "https://api.edgarkit.com/v1/filings/0001768670-26-000002" \
-H "Authorization: Bearer $EDGARKIT_KEY" | jq
Changelog
- 2026-06-11 — Added
/v1/public/feed(no-auth latest filings, IP rate-limited),/v1/health(status + freshness), and/v1/openapi.json(OpenAPI 3.0 spec). - 2026-06-11 — Ingestion poll interval reduced from 5 min to 30 sec. End-to-end webhook latency now ~30-60 sec.
- 2026-06-10 — Added 2 years of historical Form 3/4/5 data via backfill.
- 2026-06-10 — Fixed
filed_beforedate filter to include the full requested day. - 2026-06-09 — Initial release. Form 3/4/5 ingestion, REST API, webhooks with filters, HMAC signing.
Support
Found a bug? Have a feature request? Email support@edgarkit.com.
I read every email and reply personally.