Developers
Construct Data API
Subscribe to a Construct Data product, generate an API key, and pull daily-refresh factor data as signed-URL parquet. REST, Bearer-authed, no SDK required.
Getting started
- 1
Subscribe to a product at /lab/data — each subscription entitles your key to that product's data.
- 2
Generate an API key on your account page. The full key is shown once — store it securely.
- 3
Make your first request — the manifest endpoint is the cheapest check that your key + subscription work:
curl -H "Authorization: Bearer $NUMINOR_KEY" \
https://api.numinor.io/v1/constructs/sam-amplifier/manifestAuthentication
Send your key as a Bearer token on every request. One key works across all of your subscribed products (entitlements resolve from your active subscriptions). Sandbox-tier keys do not grant raw REST export — that's an API-tier feature.
Authorization: Bearer nm_live_…Core concepts
- Point-in-time delay
- The API tier serves current data; the in-Sandbox tier is delayed 30 days. Every row is explicit about its point-in-time so backtests are leak-free.
- Signed URLs
- Data endpoints return a short-lived signed S3 URL (≈4h). Download the parquet directly from S3 — that transfer is not metered or rate-limited.
- Parquet format
- All files are Apache Parquet. Read them with pyarrow, DuckDB, or polars — no server-side query endpoint needed for the common case.
- Rate limit
- Up to 1000 requests per minute per key. Over the limit returns 429 with a Retry-After header.
Endpoint reference
Base URL: https://api.numinor.io/v1
/constructs/{sku}/manifestData freshness, coverage window, and signed-URL TTL for a product.
| Parameter | In | Description |
|---|---|---|
| sku* | path | Product slug, e.g. sam-amplifier. |
curl -H "Authorization: Bearer $NUMINOR_KEY" \
https://api.numinor.io/v1/constructs/sam-amplifier/manifestResponse example
{
"sku": "sam-amplifier-construct-v1",
"tier": "api",
"status": "green",
"latest_trade_date": "2026-06-18",
"signed_url_ttl_seconds": 14400,
"historical_coverage": {
"start": "2016-01-04",
"end": "2026-06-18"
}
}/constructs/{sku}/day/{date}A signed URL to one trading day's partition.
| Parameter | In | Description |
|---|---|---|
| sku* | path | Product slug, e.g. sam-amplifier. |
| date* | path | Trading day as YYYYMMDD or YYYY-MM-DD. |
# get a signed URL for one trading day, then download the parquet
curl -H "Authorization: Bearer $NUMINOR_KEY" \
https://api.numinor.io/v1/constructs/sam-amplifier/day/20260515Response example
{
"url": "https://numinor-construct-data.s3.ap-northeast-2.amazonaws.com/…&X-Amz-Signature=…",
"trade_date": "2026-05-15",
"expires_in": 14400,
"format": "parquet"
}/constructs/{sku}/rangeSigned URLs for every published trading day in an inclusive date range.
| Parameter | In | Description |
|---|---|---|
| sku* | path | Product slug, e.g. sam-amplifier. |
| start* | query | Range start (inclusive), YYYYMMDD. |
| end* | query | Range end (inclusive), YYYYMMDD. |
curl -H "Authorization: Bearer $NUMINOR_KEY" \
"https://api.numinor.io/v1/constructs/sam-amplifier/range?start=20260501&end=20260531"Response example
{
"sku": "sam-amplifier-construct-v1",
"tier": "api",
"count": 21,
"days": [
{
"trade_date": "2026-05-06",
"url": "https://…signed…"
}
],
"format": "parquet"
}/constructs/{sku}/historicalA signed URL to the full historical bulk file (2016 → latest).
| Parameter | In | Description |
|---|---|---|
| sku* | path | Product slug, e.g. sam-amplifier. |
curl -H "Authorization: Bearer $NUMINOR_KEY" \
https://api.numinor.io/v1/constructs/sam-amplifier/historicalResponse example
{
"url": "https://…signed-bulk-file…",
"expires_in": 14400,
"format": "parquet"
}/constructs/{sku}/queryInline filtered query — on the roadmap (returns 501 today).
| Parameter | In | Description |
|---|---|---|
| sku* | path | Product slug, e.g. sam-amplifier. |
# roadmap — returns 501 today
curl -X POST -H "Authorization: Bearer $NUMINOR_KEY" \
https://api.numinor.io/v1/constructs/sam-amplifier/queryResponse example
{
"ok": false,
"error": "not_implemented",
"detail": "Roadmap — fetch signed URLs via /day or /range and read the parquet locally."
}Errors
| Status | Error | Meaning |
|---|---|---|
| 401 | missing_bearer_token · invalid_api_key | Missing or invalid API key. |
| 403 | not_subscribed · rest_requires_api_tier | Your key has no API-tier subscription for this product (or only Sandbox tier). |
| 404 | unknown_construct · no_partition | Unknown product, or no published partition for that date. |
| 400 | bad_date · bad_range · missing_params | Malformed date or range, or missing query parameters. |
| 413 | range_too_large | Range spans too many days — use the historical bulk file instead. |
| 429 | rate_limited | Rate limit exceeded (1000/min). Honor the Retry-After header. |
| 501 | not_implemented | Endpoint is on the roadmap and not implemented yet. |
Products
Ready to build? View pricing, then generate a key.