// introduction
Introduction
Form4API provides real-time SEC Form 4 insider trading data via a simple REST API. Every time a corporate insider — director, officer, or 10% owner — buys or sells shares, they must file Form 4 with the SEC within two business days. Form4API parses those filings continuously and surfaces the data through clean, developer-friendly endpoints.
Base URL
https://api.form4api.com// quickstart
Quickstart
Get your first API response in under two minutes.
Get your API key
Sign up for a free account — no credit card required. Your API key is shown immediately in the dashboard.
Make your first request
Fetch the five most recent insider transactions across all companies. Replace YOUR_API_KEY with your actual key.
curl "https://api.form4api.com/v1/transactions?per_page=5" \
-H "X-Api-Key: YOUR_API_KEY"Filter by ticker and transaction type
Narrow results to purchases (P) at Apple. The example also shows how to handle errors in code.
curl "https://api.form4api.com/v1/transactions?ticker=AAPL&transactionCode=P&per_page=10" \
-H "X-Api-Key: YOUR_API_KEY"Paginate through large result sets
Responses are arrays. When a page returns fewer records than per_page, you've reached the end. The maximum page size is 500. The Python SDK exposes a paginate() generator that handles this loop for you.
async function fetchAll(ticker) {
const results = []
let page = 1
while (true) {
const res = await fetch(
`https://api.form4api.com/v1/transactions?ticker=${ticker}&per_page=500&page=${page}`,
{ headers: { 'X-Api-Key': 'YOUR_API_KEY' } }
)
const batch = await res.json()
if (!batch.length) break
results.push(...batch)
if (batch.length < 500) break
page++
}
return results
}Use the async client (Python)
AsyncForm4ApiClient mirrors every method of the sync client — just await each call. Use it with FastAPI, Django Async, or any asyncio-based framework.
import asyncio
from form4api import AsyncForm4ApiClient
async def main():
async with AsyncForm4ApiClient("YOUR_API_KEY") as client:
txns = await client.transactions.list(ticker="AAPL", per_page=5)
for t in txns:
print(t.insider_name, t.shares_amount, "@", t.price_per_share)
asyncio.run(main())// authentication
Authentication
All API requests must include your API key in the X-Api-Key request header. You can find your key in the dashboard.
Keep your API key secret — do not expose it in client-side JavaScript or commit it to source control. Use environment variables or a secrets manager.
curl "https://api.form4api.com/v1/transactions" \
-H "X-Api-Key: YOUR_API_KEY"401 response — invalid or missing key
{
"error": {
"code": "UNAUTHORIZED",
"message": "Missing or invalid X-Api-Key header.",
"requestId": "req_abc123"
}
}SDKs
Official client libraries wrap authentication and request handling for you.
pip install form4apinpm install form4api// rate-limits
Rate Limits
Each API key has two independent limits: a per-minute burst and a daily cap. Both return 429 Too Many Requests with a Retry-After header (seconds) when exceeded.
| Plan | Requests / day | Requests / minute |
|---|---|---|
| Free | 1,000 | 20 |
| Pro | 50,000 | 200 |
| Business | 250,000 | 500 |
| Enterprise | Unlimited | 2,000 |
Per-minute limit exceeded (resets in seconds)
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Resets in 47 seconds.",
"requestId": "0HN9K2P4QR8S1:00000001"
}
}Daily cap exceeded (resets at midnight UTC)
{
"error": {
"code": "DAILY_LIMIT_EXCEEDED",
"message": "Daily request limit reached. Resets at midnight UTC.",
"requestId": "0HN9K2P4QR8S1:00000002"
}
}// errors
Errors
All errors use a consistent JSON envelope. The code field is a machine-readable string you can match on; the requestId can be sent to support to help diagnose issues.
Error envelope
{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid.",
"requestId": "req_7f3a9c"
}
}| HTTP | Code | Description |
|---|---|---|
| 401 | MISSING_API_KEY | No X-Api-Key header was sent. |
| 401 | INVALID_API_KEY | The API key exists but is invalid or revoked. |
| 402 | PLAN_REQUIRED | The endpoint requires a higher plan (e.g. Signals requires Business). |
| 404 | NOT_FOUND | The requested resource (ticker, CIK, accession number, subscription ID) does not exist. |
| 429 | RATE_LIMIT_EXCEEDED | Per-minute burst limit reached. Check the Retry-After header for seconds to wait. |
| 429 | DAILY_LIMIT_EXCEEDED | Daily request cap reached. Resets at midnight UTC. |
| 400 | INVALID_REQUEST | Request body is missing required fields (e.g. webhook url or eventTypes). |
| 400 | INVALID_EVENT_TYPE | An unrecognised event type was supplied. Valid: TransactionFiled, ClusterBuy, ClusterSell. |
| 400 | INSECURE_URL | Webhook URL must use HTTPS. |
| 400 | PRIVATE_ADDRESS | Webhook URL resolves to a private or loopback address. |
| 400 | UNRESOLVABLE_HOST | Webhook URL hostname could not be resolved via DNS. |
| 400 | INVALID_RANGE | The since parameter for webhook events is more than 30 days in the past. |
// transactions
Transactions
Returns individual insider transactions parsed from Form 4 filings. Each record represents a single row in a Form 4 table — one trade by one insider at one price.
/v1/transactions| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | — | Filter by stock ticker symbol (e.g. AAPL, MSFT). |
| code | string | — | Filter by SEC transaction code. Common values: P (open-market purchase), S (open-market sale), A (grant/award), M (option exercise), F (tax withholding on vest/exercise), D (disposition to issuer), C (conversion), J (other acquisition or disposition), G (gift). Full list of 22 codes documented in the Glossary. |
| from | string | — | Start date filter (ISO 8601, e.g. 2026-01-01). Filters by transactionDate. |
| to | string | — | End date filter (ISO 8601). |
| per_page | number | — | Number of results to return. Default: 20, max: 500. |
| page | number | — | Page number for pagination. Default: 1. |
Date filters (from / to) are both inclusive, treated as UTC, and filter on transactionDate. A date-only value (e.g. 2026-01-01) is interpreted as 2026-01-01T00:00:00Z. Results are ordered by transactionDate descending.
curl "https://api.form4api.com/v1/transactions?ticker=AAPL&per_page=5" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"ticker": "AAPL",
"companyName": "Apple Inc.",
"insiderName": "Cook Timothy D",
"insiderCik": "0001214156",
"accessionNumber": "0001140361-26-013190",
"securityTitle": "Common Stock",
"transactionCode": "S",
"sharesAmount": 5087,
"pricePerShare": 251.25,
"sharesOwnedAfter": 3340280,
"directIndirect": "D",
"isDerivative": false,
"transactionDate": "2026-04-02T00:00:00Z",
"periodOfReport": "2026-04-01T00:00:00Z"
}
]directIndirect"D" = directly owned. "I" = indirectly owned (via trust, spouse, or other entity).isDerivativetrue when the security is a derivative (option, warrant, convertible). Derivative transactions report shares underlying the instrument, not shares directly transferred.periodOfReportThe date the Form 4 covers — typically the same as transactionDate, but may differ for deferred or reportable transactions.// filings
Filings
Returns Form 4 filing headers. Use these endpoints when you need filing-level metadata such as the accession number, filed timestamp, and period of report. To get the underlying transactions, use /v1/transactions.
/v1/filings/recentReturns the most recent Form 4 filings across all companies.
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | — | Filter by company ticker (e.g. AAPL). |
| per_page | number | — | Number of results to return. Default: 20, max: 100. |
curl "https://api.form4api.com/v1/filings/recent?per_page=10" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"accessionNumber": "0001140361-26-019658",
"companyTicker": "GYRE",
"companyName": "GYRE THERAPEUTICS, INC.",
"periodOfReport": "2026-05-05T00:00:00Z",
"filedAt": "2026-05-08T02:02:09Z",
"amendmentType": "Original",
"transactionCount": 2
}
]/v1/filings/{accession}Returns a single filing by its SEC accession number, including the full transaction set.
curl "https://api.form4api.com/v1/filings/0001209191-26-034821" \
-H "X-Api-Key: YOUR_API_KEY"Response
{
"accessionNumber": "0001140361-26-017175",
"companyTicker": "AAPL",
"companyName": "Apple Inc.",
"periodOfReport": "2026-04-23T00:00:00Z",
"filedAt": "2026-05-04T07:01:02Z",
"amendmentType": "Original",
"transactionCount": 1
}// insiders
Insiders
Search for individual insiders (directors, officers, 10%+ owners) by name, fetch a single insider profile by CIK, or retrieve their complete trade history.
/v1/insidersSearch insiders by name. Returns a paginated list.
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | — | Partial name match (case-insensitive). E.g. "cook" matches "Cook Timothy D". |
| per_page | number | — | Number of results per page. Default: 20, max: 100. |
| page | number | — | Page number for pagination. Default: 1. |
curl "https://api.form4api.com/v1/insiders?name=cook" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"cik": "0001214128",
"name": "Cook Timothy D",
"isDirector": true,
"isOfficer": true,
"isTenPercentOwner": false,
"officerTitle": "Chief Executive Officer",
"totalFilings": 48
}
]/v1/insiders/{cik}Fetch a single insider profile by their SEC CIK number. The CIK is returned by the list endpoint and by any transaction record.
curl "https://api.form4api.com/v1/insiders/0001214128" \
-H "X-Api-Key: YOUR_API_KEY"Response
{
"cik": "0001214128",
"name": "Cook Timothy D",
"isDirector": true,
"isOfficer": true,
"isTenPercentOwner": false,
"officerTitle": "Chief Executive Officer",
"totalFilings": 48
}/v1/insiders/{cik}/transactionsReturns all Form 4 transactions filed by this insider, newest first. Supports date range filtering and pagination.
| Name | Type | Required | Description |
|---|---|---|---|
| from | string | — | Start date (ISO 8601, e.g. 2026-01-01). Filters by transactionDate. |
| to | string | — | End date (ISO 8601). |
| page | number | — | Page number. Default: 1. |
| per_page | number | — | Results per page. Default: 20, max: 500. |
curl "https://api.form4api.com/v1/insiders/0001214128/transactions?per_page=10" \
-H "X-Api-Key: YOUR_API_KEY"// companies
Companies
Look up a company by ticker to get its SEC profile and the list of registered insiders who have filed Form 4 for that company.
/v1/companies/{ticker}Returns the SEC profile for a company.
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | required | The company ticker symbol (path parameter). |
curl "https://api.form4api.com/v1/companies/AAPL" \
-H "X-Api-Key: YOUR_API_KEY"Response
{
"cik": "0000320193",
"name": "Apple Inc.",
"ticker": "AAPL",
"exchange": "NASDAQ",
"totalFilings": 312,
"activeInsiders": 14
}/v1/companies/{ticker}/insidersReturns all insiders who have filed Form 4 for this company, with their CIK and most recent transaction date.
| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | required | The company ticker symbol (path parameter). |
curl "https://api.form4api.com/v1/companies/AAPL/insiders" \
-H "X-Api-Key: YOUR_API_KEY"// signals
Signals
Signals surface statistically notable insider activity. A cluster buy is triggered when 3 or more distinct insiders at the same company file open-market purchases (code P) within a rolling 5-day window ending on the filing date. A cluster sell follows the same rule for sales (code S). Option exercises, grants, and tax withholdings do not count toward the cluster threshold.
One signal record is stored per company per day and is updated each time a new filing for that company is processed. Signals are ordered by signalDate descending.
402 PLAN_REQUIRED error./v1/signals| Name | Type | Required | Description |
|---|---|---|---|
| ticker | string | — | Filter by company ticker (e.g. NVDA). |
| cluster_buy | boolean | — | If true, return only signals where a cluster buy is active. |
| cluster_sell | boolean | — | If true, return only signals where a cluster sell is active. |
| page | number | — | Page number. Default: 1. |
| per_page | number | — | Results per page. Default: 100, max: 500. |
curl "https://api.form4api.com/v1/signals?cluster_buy=true&per_page=5" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"ticker": "OPCH",
"companyName": "Option Care Health, Inc.",
"signalDate": "2026-05-07T00:00:00Z",
"buySellRatio": 2.47,
"isClusterBuy": true,
"isClusterSell": false,
"insiderCount": 11
}
]buySellRatioTotal shares purchased ÷ total shares sold by all insiders over the past 90 days. Capped at 99 when there are buys but no sells.insiderCountNumber of distinct insiders who filed any transaction for this company in the past 90 days — not just those who contributed to the cluster trigger.signalDateThe date the triggering Form 4 was filed with the SEC, not the transaction date.402 response — plan too low
{
"error": {
"code": "PLAN_REQUIRED",
"message": "This endpoint requires the Business plan or higher. Your current plan is Free.",
"requestId": "req_7f3a9c"
}
}// webhooks
Webhooks
Subscribe to real-time events instead of polling. When a matching event fires, Form4API POSTs a JSON payload to your endpoint within seconds of the SEC publishing the filing. Each delivery is signed with X-Insider-Signature so you can verify it came from us.
/v1/webhooksCreate a new webhook subscription. The signing secret is returned once — store it immediately.
Request body
| Name | Type | Required | Description |
|---|---|---|---|
| url | string | required | HTTPS endpoint that will receive webhook payloads. Must be publicly reachable. |
| eventTypes | string[] | required | Array of event types to subscribe to. Valid values: TransactionFiled, ClusterBuy, ClusterSell. |
Response
| Name | Type | Required | Description |
|---|---|---|---|
| subscriptionId | number | — | Unique subscription ID. Use this to delete the webhook. |
| secret | string | — | Signing secret — shown once only. Store it securely to verify X-Insider-Signature. |
| url | string | — | The endpoint URL. |
| eventTypes | string[] | — | Subscribed event types. |
| warning | string | — | Reminder that the secret will not be returned again. |
curl -X POST "https://api.form4api.com/v1/webhooks" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/webhooks/form4",
"eventTypes": ["TransactionFiled", "ClusterBuy"]
}'/v1/webhooksList all webhook subscriptions for your API key. Secrets are never returned in this response.
curl "https://api.form4api.com/v1/webhooks" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"subscriptionId": 42,
"url": "https://yourapp.com/webhooks/form4",
"eventTypes": ["TransactionFiled", "ClusterBuy"],
"createdAt": "2026-05-01T10:00:00Z",
"isActive": true
}
]/v1/webhooks/{id}Delete a webhook subscription by its numeric ID. Returns 204 No Content on success, or 404 NOT_FOUND if the ID doesn't exist or belongs to a different key.
curl -X DELETE "https://api.form4api.com/v1/webhooks/42" \
-H "X-Api-Key: YOUR_API_KEY"
# Returns 204 No Content on success/v1/webhooks/eventsReturns up to 500 delivery records from the last 24 hours by default. Use the optional since parameter (ISO 8601) to replay from a specific timestamp — up to 30 days back. Useful for catching missed deliveries after a planned outage.
curl "https://api.form4api.com/v1/webhooks/events" \
-H "X-Api-Key: YOUR_API_KEY"
# Replay from a specific point in time (up to 30 days back)
curl "https://api.form4api.com/v1/webhooks/events?since=2026-05-01T00:00:00Z" \
-H "X-Api-Key: YOUR_API_KEY"Response
[
{
"deliveryId": 1042,
"subscriptionId": 7,
"eventType": "TransactionFiled",
"attemptCount": 1,
"deliveredAt": "2026-05-04T14:23:11Z",
"nextRetryAt": null,
"lastStatusCode": 200,
"isDead": false,
"payload": { "filingId": 123, "accessionNumber": "0001140361-26-017175" }
}
]Event payloads
Every webhook POST has a top-level type field and a data object whose shape depends on the event type.
{
"type": "TransactionFiled",
"data": {
"ticker": "AAPL",
"companyName": "Apple Inc.",
"insiderName": "Cook Timothy D",
"transactionCode": "S",
"sharesAmount": 10000,
"pricePerShare": 212.45,
"transactionDate": "2026-04-30T00:00:00Z"
}
}Signature verification
Each request includes an X-Insider-Signature header with the value sha256=<hex> — HMAC-SHA256 of the raw request body signed with your subscription secret. Always verify before processing.
import crypto from 'crypto'
export async function POST(req: Request) {
const body = await req.text()
const sig = req.headers.get('X-Insider-Signature') ?? ''
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET!)
.update(body)
.digest('hex')
if (sig !== expected) {
return new Response('Invalid signature', { status: 401 })
}
const event = JSON.parse(body)
// handle event.type: 'TransactionFiled' | 'ClusterBuy' | 'ClusterSell'
return new Response('ok', { status: 200 })
}// billing
Billing
Programmatically generate a Stripe checkout URL to upgrade your plan. The endpoint requires a valid API key and returns a one-time checkout session URL. Redirect the user to this URL to complete payment.
/v1/billing/checkout| Param | In | Values |
|---|---|---|
| plan | query | Pro | Business | Enterprise |
curl -X POST "https://api.form4api.com/v1/billing/checkout?plan=Pro" \
-H "X-Api-Key: YOUR_API_KEY"Response
{
"checkoutUrl": "https://checkout.stripe.com/c/pay/cs_live_..."
}/v1/billing/portalCreates a Stripe Customer Portal session for managing an existing subscription — cancel, change plan, update payment method. Requires an active paid subscription. Returns a one-time portal URL; redirect the user to it.
curl -X POST "https://api.form4api.com/v1/billing/portal" \
-H "X-Api-Key: YOUR_API_KEY"Response
{
"portalUrl": "https://billing.stripe.com/session/..."
}// glossary
Glossary
Key terms from SEC filings and insider trading data used throughout this API.
- Accession Number
- The SEC's unique identifier for a single filing, formatted as XXXXXXXXXX-YY-ZZZZZZ (e.g. 0001140361-26-013190). The first segment is the filer's CIK, YY is the year, and ZZZZZZ is a sequence number. Use this to fetch a specific filing from the /v1/filings/{accession} endpoint.
- Beneficial Ownership
- Shares that an insider has an economic interest in, even if they are not registered in the insider's name. An insider is considered a beneficial owner of shares held by a spouse, a trust they control, or a company they own more than 50% of.
- CIK
- Central Index Key — the SEC's permanent numeric identifier for every entity that files with the SEC, including individuals and companies. CIKs are always 10 digits, zero-padded (e.g. 0001214156). Use a CIK to look up an insider's full filing history via /v1/insiders/{cik}.
- Cluster Signal
- A ClusterBuy or ClusterSell signal is triggered when three or more insiders at the same company independently file Form 4 transactions in the same direction (all buys or all sells) within a 5-day window. Clusters are considered a stronger signal than a single insider trade because they suggest shared conviction among multiple informed parties.
- Derivative Security
- A security whose value is derived from an underlying asset — typically company stock. Common derivatives reported on Form 4 include stock options, warrants, and convertible notes. When isDerivative is true in a transaction, sharesAmount refers to the number of shares underlying the derivative, not shares directly transferred.
- Direct vs Indirect Ownership
- The directIndirect field indicates how an insider holds shares. "D" (direct) means shares are registered in the insider's own name. "I" (indirect) means shares are held through an intermediary such as a trust, LLC, partnership, or a family member's account.
- Form 4
- The SEC filing required under Section 16 of the Securities Exchange Act of 1934. Corporate insiders — directors, officers, and shareholders owning more than 10% of a company — must file Form 4 within two business days of any change in their beneficial ownership of company securities. Form4API parses every Form 4 filed with the SEC and exposes the data via this API.
- Insider
- For SEC reporting purposes, an insider is any director, officer, or 10%-or-greater shareholder of a public company. These individuals have a heightened duty to disclose their trades because they may have access to material non-public information. Insider trading data is public — only the trades of these registered insiders are reported on Form 4.
- Period of Report
- The date field on a Form 4 indicating when the reported transaction occurred. This is usually identical to transactionDate but can differ for transactions that are grouped or reported after a delay. When the two dates differ, periodOfReport reflects the filing's stated coverage date.
- Section 16
- Section 16 of the Securities Exchange Act requires insiders to report their ownership and any changes to it. Section 16(a) mandates the Form 4 filings this API is built on. Section 16(b) requires insiders to disgorge any "short-swing profits" — gains from buying and selling the same stock within a six-month window.
- Transaction Code
- A single letter on Form 4 indicating the nature of the transaction. The most common codes are: P (open-market purchase), S (open-market sale), A (grant or award), M (exercise or conversion of derivative), F (shares withheld to cover tax on vest/exercise), D (disposition to the issuer). Less common but valid codes include: C (conversion of derivative), J (other acquisition or disposition), G (gift), X (in-the-money derivative exercise), O (out-of-the-money derivative exercise), E (expiration of long derivative), H (expiration of short derivative), I (discretionary transaction), L (small acquisition), U (tender offer disposition), W (acquisition by will or descent), Z (voting trust deposit/withdrawal), V (voluntary exempted disposition), K (equity swap), B (automatic sell to cover taxes), T (Rule 10b5-1 plan transaction).