Your first request: /status and the identity envelope
With a key in an environment variable (see setup) and the
X-API-KEY header described in auth, this
chapter walks through the two simplest endpoints in the API end to
end, line by line, so that by the end of it you have a mental model
of the request/response loop you will use for everything else.
The simplest endpoint: GET /api/v1/status
The GET /api/v1/status endpoint is the API's liveness check. It
takes no parameters, returns a tiny JSON envelope, and crucially does
not require authentication. It is the single best probe for
"is the server even up?".
Wire shape.
GET /api/v1/status HTTP/1.1
Host: dev-datasets-api.algoseek.com
Response.
{
"status": "OK",
"version": "0.2.0"
}
Live capture: HTTP 200 • 319.4 ms • 33 bytes • X-Request-ID: fe45aeca-5ca4-4429-aa0d-f4a27f2a1d17
The endpoint is appropriate for kubernetes liveness probes, ALB target group health checks, and pre-flight checks before a long-running ingestion job. Because it is unauthenticated, you can probe it from anywhere without arranging an outbound IP whitelist entry.
The first authenticated endpoint: GET /api/v1/account/my
Now we send a request that requires the key. The GET /api/v1/account/my
endpoint returns the identity envelope — who owns this key, what
account they belong to, what their support email is, what IP subnets
their key is allowed to come from.
import os, sys, json
import requests
API_KEY = os.environ.get("ALGOSEEK_API_KEY", "").strip()
if not API_KEY:
sys.exit("ALGOSEEK_API_KEY not set")
url = "https://dev-datasets-api.algoseek.com/api/v1/account/my"
with requests.Session() as session:
session.headers["X-API-KEY"] = API_KEY
resp = session.get(url, timeout=30)
resp.raise_for_status()
ctype = resp.headers.get("content-type", "")
if ctype.startswith("application/json"):
print(json.dumps(resp.json(), indent=2))
else:
print(f"Unexpected content-type {ctype}; raw:\n{resp.text}")
And the equivalent cURL.
curl -s "https://dev-datasets-api.algoseek.com/api/v1/account/my" \
-H "X-API-KEY: $ALGOSEEK_API_KEY" | jq .
Response.
{
"identity_id": 89,
"name": "Algoseek Prod (REST API)",
"max_active_api_keys": 15,
"ip_subnets": []
}
Live capture: HTTP 200 • 424.7 ms • 93 bytes • X-Request-ID: e8db27db-890f-436e-a04f-44223c40b165
The identity envelope is the lowest-cost call you can make to verify
end-to-end auth (key valid, IP allowed, account active). It is also
the source of truth for the IP allow-list — if you are running in a
CI environment whose egress IP rotates, comparing the resolver's
current outbound IP against this list at startup is a much cheaper
diagnostic than debugging a mysterious 403 on a data
endpoint mid-pipeline.
Three more identity-tier endpoints
There are three more identity-tier calls that you will use repeatedly. None of them count meaningfully against quota, all of them are safe to call at process startup, and together they tell you everything about your account's posture before you make any data call.
Quotas: GET /api/v1/account/my/quotas
{
"quotas_usage": {
"month": {
"requests": 546,
"data_scanned": 3139447119,
"data_returned": 842277070
},
"minute": {
"requests": 1,
"data_scanned": 502,
"data_returned": 256
}
},
"quotas_limit": {
"month": {
"requests": 1000,
"data_scanned": 100000000000,
"data_returned": 10000000000
},
"minute": {
"requests": 10,
"data_scanned": 10000000000,
"data_returned": 1000000000
}
}
}
The response has two top-level objects: quotas_usage (what
you have already spent this month and this minute) and
quotas_limit (the maximum). Each object contains:
requests— count of API callsdata_scanned— bytes read by the engine to assemble your responsesdata_returned— bytes actually sent over the wire to you
data_scanned is the proxy for engine cost; for cost
optimisation, push as much filtering as possible into the URL
(column-name filters, TradeDate-bounded ranges) so the engine
scans less. data_returned is the proxy for network cost; use
columns= projection and response_format=csv_gzip
to compress it (see the formats chapter). The minute bucket
is a rolling 60-second sliding window with a lagging server-side counter;
see quotas for the full explanation.
Data access rules: GET /api/v1/account/my/data-access-rules
This is the longest of the identity-tier responses. It returns one
record per dataset your account is entitled to, with the dataset's
dataset_text_id (the URL-friendly identifier), its
dataset_name (human-readable), the date range you are
authorised to query (start_date and end_date),
and the universe of identifiers (typically tickers) you may filter by.
[
{
"dataset_id": "US1054",
"dataset_name": "US Equities Trading Halts",
"dataset_version": "latest",
"start_date": "2024-10-25",
"end_date": null,
"universe_identifiers": []
},
{
"dataset_id": "US5016",
"dataset_name": "US OPRA Options Contracts Security Master",
"dataset_version": "latest",
"start_date": "2007-01-01",
"end_date": null,
"universe_identifiers": []
},
{
"dataset_id": "US5001",
"dataset_name": "OCC Equities Special Settlements",
"dataset_version": "latest",
"start_date": "2017-11-01",
"end_date": null,
"universe_identifiers": []
}
]
... (response truncated for the guide; full file under responses/iam_account_data_access_rules/body.json)
:::caution Gotcha
The mapping between the URL path of a data endpoint
(/api/v1/data/us-equity/eq-daily-ohlc) and the
dataset_text_id that appears in this response is not 1:1.
The same path can route to different underlying datasets depending on
query parameters — for example, adding adjusted=true to
eq-trades routes to the adjusted variant
(eq_trades_adj); adding
aggregation_logic=industry_std to eq-daily-ohlc
routes to eq_daily_ohlc_ind_std. If you receive a
403, cross-reference the URL you used against this rules
list and try the alternative routing parameters.
:::
Catalog: GET /api/v1/meta/datasets
Where GET /api/v1/account/my/data-access-rules tells you what you
have access to, GET /api/v1/meta/datasets tells you what exists
on the server. It is the root of the catalog API
(see the catalog chapter for the rest).
[
{
"dataset_id": "US1033",
"dataset_name": "US Equities Trade and Quote Minute Bar",
"data_group": "Equity",
"vendor": "algoseek"
},
{
"dataset_id": "US1034",
"dataset_name": "US Equities Trade and Quote Extended Minute Bar",
"data_group": "Equity",
"vendor": "algoseek"
},
{
"dataset_id": "US1035",
"dataset_name": "US Equities Trade and Quote Minute Bar Excluding FINRA/TRF Trades",
"data_group": "Equity",
"vendor": "algoseek"
}
]
Treat the catalog as a discovery surface: at startup, fetch the full
list, intersect with GET /api/v1/account/my/data-access-rules, and
present only the datasets your code is both subscribed to and
the server still publishes. This catches both new dataset releases
(which you might want to opt into) and quietly retired datasets (which
will start returning 404 silently if you have hard-coded the
text-id).
End of the warm-up
If you reached this point with all four calls returning 200,
you have done everything that is foundational. The remaining chapters
add new dimensions to a request you already know how to send:
- The dataset catalog (catalog): how to discover what datasets and columns the server publishes.
- Filtering, projection, and pagination (filtering): how to ask for less, in the order you want it, and how to walk a result set larger than one response can hold.
- Response formats (formats): JSON, CSV, and streaming gzip.
- Errors and idempotency (errors): what to do when the server says no.
- Rate limits and quotas (quotas): scheduling, backoff, and quota arithmetic.
After that, the per-endpoint-family chapters walk through one worked example each, and the appendix is the per-endpoint reference.