Requests and responses
Base URL and authentication
Section titled “Base URL and authentication”https://belfort-data-api.vercel.appEvery route is a GET. Send your key in the X-API-Key header on every route except /v1/status, which needs none:
curl -H "X-API-Key: $BELFORT_API_KEY" https://belfort-data-api.vercel.app/v1/companies/MSFTNaming a company
Section titled “Naming a company”Company routes take an {id} in the path. It can be:
- a ticker, in any case.
BRK.BandBRK-Breach the same company. - a CIK, the SEC’s company number, with or without leading zeros.
A filer with no ticker still works by CIK. A ticker reaches exactly one CIK; for the few companies that reorganized under a new CIK, see Company.
The response envelope
Section titled “The response envelope”Every successful answer has the same two parts:
{ "data": "...", "meta": { "snapshot_id": "...", "as_of": "...", "next_cursor": null }}datais the answer: one object, or a list.meta.snapshot_idnames the load of data that answered you.meta.as_ofis when the source data was published. Quote it with any figure you use.meta.next_cursoris the key to the next page, ornullon the last page and on routes that don’t page.
Values are as filed. A blank in a filing is null, never 0.
Errors
Section titled “Errors”Errors come back as { "error": { "code": "...", "message": "..." } }. The message says what to fix.
| HTTP | code |
What happened |
|---|---|---|
| 400 | bad_request |
The request is malformed, or has a query parameter the route doesn’t take. |
| 401 | unauthorized |
The key is missing, unknown or revoked. |
| 404 | not_found |
No company matches this ticker or CIK. |
| 429 | rate_limited |
Your key is over its per-minute limit. Wait the seconds in Retry-After. |
| 500 | internal |
Something failed on our side. |
| 503 | internal |
The database can’t be reached, or this dataset isn’t loaded yet. Wait the seconds in Retry-After. |
Unknown query parameters are refused on purpose, so a typo like frequncy=annual fails loudly instead of quietly returning everything.
Rate limits
Section titled “Rate limits”Each key has a per-minute limit. The limit is counted by each server instance on its own, so it isn’t a hard global cap: a 429 means the instance you reached is over your limit, and another instance may still answer. Please treat your agreed limit as the rate you send. Usage is counted across all instances.
Paging
Section titled “Paging”Routes that return long lists page them. Pass limit to set the page size and, for the next page, pass meta.next_cursor back as cursor with the same filters. Stop when next_cursor is null.
curl -H "X-API-Key: $BELFORT_API_KEY" \ "https://belfort-data-api.vercel.app/v1/companies/AAPL/statements?statement=IS&limit=4"
# then, with the cursor from that answer:curl -H "X-API-Key: $BELFORT_API_KEY" \ "https://belfort-data-api.vercel.app/v1/companies/AAPL/statements?statement=IS&limit=4&cursor=NEXT_CURSOR"A page can hold fewer items than limit even when more remain, so always follow next_cursor rather than counting items. A cursor only works with the filters it was issued for.
| Route | limit |
Default | Pages with cursor |
|---|---|---|---|
/v1/companies/{id}/statements |
1–20 | 4 | Yes |
/v1/companies/{id}/financials |
1–100 | 40 | Yes |
/v1/companies/{id}/segments |
1–50 | 20 | Yes |
/v1/companies/{id}/holders |
1–100 | 25 | Yes |
/v1/companies/{id}/insider-trades |
1–50 | 20 | Yes |
/v1/companies/{id}/form13f |
1–50 | 20 | Yes |
/v1/companies/{id}/filings |
1–50 | 20 | Yes |
/v1/companies/{id}/earnings-releases |
1–100 | 20 | Yes |
/v1/companies/{id}/ownership |
1–100 | 20 | No |
Earnings releases also take from and to, inclusive filed-date bounds in YYYY-MM-DD form.
/v1/status, /v1/companies/{id}, /v1/companies/{id}/metrics and /v1/macro/{series} return everything in one answer.
Freshness
Section titled “Freshness”/v1/status reports, for each dataset, when its source was published (as_of), when we loaded it (loaded_at) and its age in hours. A dataset that isn’t loaded yet reads null, and its route answers 503 until it is. How often each source updates is on Where the data comes from.