Ingest · data
Point-in-Time API
Give it a company and a timestamp and it returns the filings that were public at that minute. Every answer repeats which timestamp field it filtered on and lists a certificate for each day it read.
- LIVE
- REST
- JSON
- SSE
Researcher $29 / Power $79 / Desk $499 monthly. The sample routes below take no key.
The artifact
One request, and what came back
SVB Financial Group filed an 8-K on 10 March 2023. This asks for what was public at the end of that day, against the hosted sample route, which needs no key.
$ curl -s "https://api.pit.aqx.llc/v1/sample/news?example=svb&as_of=2023-03-10T23:59:59Z&visible_by=published_at"
{
"request_id": "c4a244b3-60c0-4a77-8b29-b94d5bbb063a",
"corpus_version": "sha256:sample",
"as_of": "2023-03-10T23:59:59Z",
"visible_by": "published_at",
"status": "ok",
"results": [
{
"id": "0001193125-23-067777_719739",
"source_id": "sec.edgar",
"lane": "certified_pit",
"form": "8-K",
"accession": "0001193125-23-067777",
"cik": "719739",
"title": "SVB FINANCIAL GROUP 8-K",
"event_at": null,
"published_at": "2023-03-10T23:59:59Z",
"available_at": null,
"acceptance_at": "2023-03-10T22:23:03Z",
"committed_at": "2026-08-25T09:18:11Z",
"availability_basis": "unknown",
"content_sha256": "8a95862ef3953dd206f1afeb5a0ab19014b57f7f332b764e948f6514fdd2d06a",
"source_locator": "https://www.sec.gov/Archives/edgar/data/719739/000119312523067777/0001193125-23-067777.txt",
"sample": true,
"as_of_visible": true
}
],
"count": 1,
"coverage": {
"touched": [
"identity.ticker/SIVB@2023-03-10",
"sec.edgar/2023-03-10",
"sec.edgar/frontier:2020-02-18..2023-03-10;holes=0",
"us.federal_register.pi/2023-03-10",
"us.federal_register.pi/frontier:2020-02-18..2023-03-10;holes=0"
],
"missing": []
},
"error": null
}
Run on 2026-08-27. request_id and
corpus_version change per call; the row does not.
Move the cut back to 20:00Z on 9 March and the same call answers 200
with count: 0 and the same empty
coverage.missing. The 8-K was not public yet, and we hold
a certificate for that day saying we read it and found nothing.
Ask instead for the strictest clock, available_at, and the
call refuses. No publisher clock records when EDGAR disseminated this
filing, so available_at is null on the row, and a cut on a
null clock is answered as 409 rather than as a count of zero.
$ curl -s "https://api.pit.aqx.llc/v1/sample/news?example=svb&as_of=2023-03-10T23:59:59Z&visible_by=available_at"
{
"status": "coverage_missing",
"results": [],
"count": null,
"coverage": {
"missing": ["availability.sec.edgar/2023-03-10"]
},
"error": {
"code": "coverage_missing",
"message": "This cut touches at least one day we have not certified, so count is null: the answer is unknown, not empty. coverage.missing names the days.",
"param": null
}
}
The failure it prevents
One filing, two clocks, twenty-two hours apart
data/raw/sec/2023-03/2023-03-10/master.idx line 4,543
CIK|Company Name|Form Type|Date Filed|File Name 719739|SVB FINANCIAL GROUP|8-K|20230310|edgar/data/719739/0001193125-23-067777.txt
The only time on that line is 20230310. EDGAR also stamps
the minute it accepted a submission, and for this filing that minute
was 22:23:03Z. A join on the date column hands the 8-K to your
model at midnight UTC, twenty-two hours before EDGAR had it, and
nothing in the date column tells you so.
We put a number on what that gap is worth. One strategy, one basket of twelve Dow issuers, one price series, 88 8-K filings between 2022-11-01 and 2023-03-31, and the clock as the only input that changes: the naive filed-date join returns +5.13%, the same strategy waiting for the nightly EDGAR dump returns −2.02%, and the acceptance receipt returns +0.18%. On 47 of the 64 filings that carry a receipt, the naive arm's entry auction opened before EDGAR had accepted the filing, a mean of 6.05 hours before, so that first curve was never reachable by anyone.
The basket rule, the exclusions and the per-event timing are on benchmarks, and the method is written up in methods.
How it works
Five clocks on the row, three you may cut on
The clock vocabulary
Every row carries event_at, published_at,
available_at, acceptance_at and
committed_at. The visible_by parameter
takes published_at, available_at or
committed_at, and defaults to the first. A row is in the
cut when its named clock is at or before as_of, compared
in UTC and inclusive at both ends. Naming
acceptance_at returns 400 with
invalid_clock, because an acceptance receipt records
when EDGAR took the file rather than when a reader could fetch it.
Null clocks
If the clock you named is null on a row, the cut leaves that row out
and the day turns up in coverage.missing, so you see the
hole instead of a quietly smaller answer.
A certificate per day
coverage.touched lists every source-day the answer rests
on, including the frontier the corpus was read to. A day we have not
certified makes the whole call 409 with count as JSON
null, which is how you tell an uncertified day apart from a day we
read and found empty.
Identity at the instant
Tickers are not stored on the filing row. /v1/mapping
resolves a ticker to a CIK as of the query instant, which is how a
2021 query for FB reaches the company that later renamed itself.
Joining on today's ticker table uses a mapping that did not exist
when the query says it is standing.
Two lanes
Backfilled rows arrive on certified_pit and rows the
live tape observed arrive on forward_first_seen. One
answer carries one lane, so what a publisher asserted stays separable
from what we watched happen.
What the corpus holds
Read from /v1/meta on 2026-08-27: 587,748 queryable rows
across seven public sources, with partitions running from 2008-09-01
to that morning. sec.edgar is 564,518 of them and
us.federal_register.pi is 21,931. The endpoint takes no
key, so this paragraph is checkable from a browser.
Integration
Six lines of Python
The package is pitnews. It is stdlib only, so there is
nothing to resolve, and it reads your key from
PIT_API_KEY when you pass none.
from pitnews import PitClient
client = PitClient() # or PitClient(api_key="pit_live_…")
page = client.query_as_of(
ticker="SIVB",
known_at="2023-03-10T23:59:59Z",
visible_by="published_at",
source="sec.edgar",
)
print(page["count"], page["coverage"]["missing"])
query_as_of returns one page and count is
that page's rows rather than the size of the cut.
fetch_all_as_of follows the cursor for you, and
iter_as_of streams. Passing source narrows
what the answer depends on: without it this cut also rests on CFTC and
OFAC days the corpus does not hold, and the call answers 409 naming
them.
Install from the clone with
pip install ./clients/python until the PyPI release. A Go
client sits in clients/go, and the OpenAPI document is at
/v1/openapi.json.
Related
Upstream and downstream
- Live Feed
- The forward half of the same record. It writes new rows every fifteen minutes and stamps each one with the minute we first saw it.
- Flat Files
- The same rows as parquet partitions, for work that reads the corpus rather than querying it.
- Benchmark Datasets
- A frozen window of these rows with matched control arms, for scoring an agent.
- MCP Server
- The same cuts as tools an agent can call, with
known_aton every question.
Plans and rate limits are on the pricing page. A self-serve key covers work you run for yourself or your employer; if your own users end up holding PIT rows you need a commercial license.