// 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
Get started: Create a free account to receive your API key. No credit card required for the Free plan.

// quickstart

Quickstart

Get your first API response in under two minutes.

1

Get your API key

Sign up for a free account — no credit card required. Your API key is shown immediately in the dashboard.

2

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"
3

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"
4

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
}
5

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.

Pythonpip install form4api
JavaScriptnpm 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.

PlanRequests / dayRequests / minute
Free1,00020
Pro50,000200
Business250,000500
EnterpriseUnlimited2,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"
  }
}
HTTPCodeDescription
401MISSING_API_KEYNo X-Api-Key header was sent.
401INVALID_API_KEYThe API key exists but is invalid or revoked.
402PLAN_REQUIREDThe endpoint requires a higher plan (e.g. Signals requires Business).
404NOT_FOUNDThe requested resource (ticker, CIK, accession number, subscription ID) does not exist.
429RATE_LIMIT_EXCEEDEDPer-minute burst limit reached. Check the Retry-After header for seconds to wait.
429DAILY_LIMIT_EXCEEDEDDaily request cap reached. Resets at midnight UTC.
400INVALID_REQUESTRequest body is missing required fields (e.g. webhook url or eventTypes).
400INVALID_EVENT_TYPEAn unrecognised event type was supplied. Valid: TransactionFiled, ClusterBuy, ClusterSell.
400INSECURE_URLWebhook URL must use HTTPS.
400PRIVATE_ADDRESSWebhook URL resolves to a private or loopback address.
400UNRESOLVABLE_HOSTWebhook URL hostname could not be resolved via DNS.
400INVALID_RANGEThe 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.

GET/v1/transactions
NameTypeRequiredDescription
tickerstringFilter by stock ticker symbol (e.g. AAPL, MSFT).
codestringFilter 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.
fromstringStart date filter (ISO 8601, e.g. 2026-01-01). Filters by transactionDate.
tostringEnd date filter (ISO 8601).
per_pagenumberNumber of results to return. Default: 20, max: 500.
pagenumberPage 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.

GET/v1/filings/recent

Returns the most recent Form 4 filings across all companies.

NameTypeRequiredDescription
tickerstringFilter by company ticker (e.g. AAPL).
per_pagenumberNumber 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
  }
]
GET/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.

GET/v1/insiders

Search insiders by name. Returns a paginated list.

NameTypeRequiredDescription
namestringPartial name match (case-insensitive). E.g. "cook" matches "Cook Timothy D".
per_pagenumberNumber of results per page. Default: 20, max: 100.
pagenumberPage 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
  }
]
GET/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
}
GET/v1/insiders/{cik}/transactions

Returns all Form 4 transactions filed by this insider, newest first. Supports date range filtering and pagination.

NameTypeRequiredDescription
fromstringStart date (ISO 8601, e.g. 2026-01-01). Filters by transactionDate.
tostringEnd date (ISO 8601).
pagenumberPage number. Default: 1.
per_pagenumberResults 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.

GET/v1/companies/{ticker}

Returns the SEC profile for a company.

NameTypeRequiredDescription
tickerstringrequiredThe 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
}
GET/v1/companies/{ticker}/insiders

Returns all insiders who have filed Form 4 for this company, with their CIK and most recent transaction date.

NameTypeRequiredDescription
tickerstringrequiredThe 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.

Available on Business and Enterprise plans only. Free and Pro keys receive a 402 PLAN_REQUIRED error.
GET/v1/signals
NameTypeRequiredDescription
tickerstringFilter by company ticker (e.g. NVDA).
cluster_buybooleanIf true, return only signals where a cluster buy is active.
cluster_sellbooleanIf true, return only signals where a cluster sell is active.
pagenumberPage number. Default: 1.
per_pagenumberResults 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.

POST/v1/webhooks

Create a new webhook subscription. The signing secret is returned once — store it immediately.

Request body

NameTypeRequiredDescription
urlstringrequiredHTTPS endpoint that will receive webhook payloads. Must be publicly reachable.
eventTypesstring[]requiredArray of event types to subscribe to. Valid values: TransactionFiled, ClusterBuy, ClusterSell.

Response

NameTypeRequiredDescription
subscriptionIdnumberUnique subscription ID. Use this to delete the webhook.
secretstringSigning secret — shown once only. Store it securely to verify X-Insider-Signature.
urlstringThe endpoint URL.
eventTypesstring[]Subscribed event types.
warningstringReminder 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"]
  }'
GET/v1/webhooks

List 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
  }
]
DELETE/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
GET/v1/webhooks/events

Returns 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.

POST/v1/billing/checkout
ParamInValues
planqueryPro | 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_..."
}
POST/v1/billing/portal

Creates 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/..."
}
Alternatively, upgrade from the dashboard without touching the API.

// 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).