/api/sd/etf/history
GETPartialPARTIAL

Spot ETF history

Daily series of holdings, net assets or net flow for one asset (covered funds summed) or for a single fund. Each point states how many funds it contains.

GET/api/sd/etf/history
Partial coverage. Partial coverage: several large issuers do not offer a public machine-readable disclosure that can be collected from a server. Their funds are listed as unavailable, and totals cover the remaining funds only. Compare `funds_covered` / `funds_total` before comparing totals with other sources.

Request

Query parameters

NameTypeRequiredDefaultAllowed valuesDescription
assetstringRequired—BTC, ETH, SOL, HYPEUnderlying asset, case-insensitive. `coin` is accepted as an alias. Example: BTC
metricstringRequired—holdings, aum, flowSeries to return: holdings (coin), net assets (USD) or net flow (USD). Example: flow
rangestringOptional30d30d, 90d, allLook-back range.
tickerstringOptional——Fund ticker registered for the asset (for example `ARKB`). Default: all covered funds summed. An unregistered ticker returns 404; a registered fund that cannot be collected returns 200 with `series: null`.

Example request

curl -s "https://www.coinboss.com/api/sd/etf/history?asset=BTC&metric=flow"

Response fields

The field table is generated from real responses, so it lists exactly what the endpoint returns. Paths use a[] for array items and {*} for objects keyed by a dynamic name such as a coin or an exchange.

FieldTypeUnitDescription
successboolean—true when the request succeeded. On failure the body is `{ success: false, code, error, request_id }`.
schemastring—Schema id of this response. It changes only when an existing field changes meaning or type.
nownumbermsServer time when the response was built.
assetstring—Underlying asset.
metricstring—Series selected by the `metric` parameter.
rangestring—Look-back range applied.
tickerstring|null—Fund ticker.
unitstring—Unit of the series values: `coin` or `USD`.
funds_totalnumber—Funds registered for the asset.
funds_in_seriesarray—Funds that contribute to the series.
funds_in_series[]string—Funds that contribute to the series.
first_date_by_fundobject—First date available per fund (the key is the ticker). dynamic keys: ARKB,EZBC
first_date_by_fund.{*}string—First date available per fund (the key is the ticker).
pointsnumber—Series points, oldest first.
seriesarray—Daily points, oldest first; `null` when the fund cannot be collected.
series[]object—Daily points, oldest first; `null` when the fund cannot be collected.
series[].datestring—Issuer as-of date of the point.
series[].valuenumber—Value of the selected metric, summed over the funds present on that date.
series[].fundsnumber—One row per registered fund, including funds that cannot be collected. may be absent
coverageobject—What is and is not included in the numbers. Compare this before comparing totals with another source.
coverage.included_exchangesarray—Sources whose fresh data is included.
coverage.included_exchanges[]string—Sources whose fresh data is included.
coverage.unavailablearray—Sources that could not be included, each with a reason. They are never counted as 0.
coverage.unavailable[]object—Sources that could not be included, each with a reason. They are never counted as 0.
coverage.unavailable[].exchangestring—Exchange id (lower case).
coverage.unavailable[].issuerstring—Fund issuer id.
coverage.unavailable[].reasonstring—Machine-readable reason code.
coverage.unavailable[].detailstring—Human-readable explanation of the reason.
coverage.stale_excludedarray—Rows left out because their last update is outside the fresh window. empty in the samples used to generate this table
methodobject—Plain-text statement of the formulas used for this response, one entry per field.
method.valuestring—Formula note for `value`, plain text.
method.fundsstring—Formula note for `funds`, plain text.
method.multi_daystring—Formula note for `multi_day`, plain text.
method.history_startstring—Formula note for `history_start`, plain text.
metaobject—Lineage and freshness of this response.
meta.schemastring—Schema id of this response. It changes only when an existing field changes meaning or type.
meta.sourcearray—Upstream public endpoints the data was collected from.
meta.source[]object—Upstream public endpoints the data was collected from.
meta.source[].exchangestring—Exchange id (lower case).
meta.source[].endpointstring—Public endpoint of the source the collector reads (shown for lineage; clients never call it).
meta.observed_atnumbermsTimestamp given by the source for the data.
meta.received_atnumbermsTime the CoinBoss collector received the data.
meta.fetched_atnumbermsTime this response was assembled.
meta.windowstring—Time window the numbers cover.
meta.qualitystring—FRESH, PARTIAL, STALE, BROKEN or UNAVAILABLE, judged from data timestamps and coverage.
meta.is_staleboolean—True when the data is older than its fresh window.
meta.cache_ttl_snumbersCache lifetime of this response.
meta.fallbackstring—What the endpoint returns when the collector or a source fails.

Generated 2026-11-11 23:00 UTC from 3 real responses.

Example response

/api/sd/etf/history?asset=BTC&metric=flow · Real response captured 2026-11-13 03:58:17 UTC. Long arrays and maps are shortened for display: series had 21 items; meta.source had 5 items; first_date_by_fund had 5 items; coverage.unavailable had 7 items.

  • {
    • "success": true,
    • "schema": "coinboss.sd.etf/1",
    • "now": 1794542297946,
    • "asset": "BTC",
    • "metric": "flow",
    • "range": "30d",
    • "ticker": null,
    • "unit": "USD",
    • "funds_total": 12,
    • "funds_in_series": [
      • "ARKB",
      • "BITB",
      • "BTCO",
      • "EZBC",
      • "HODL"
      ],
    • "first_date_by_fund": {
      • "ARKB": "2026-10-14",
      • "BITB": "2026-11-11"
      },
    • "points": 21,
    • "series": [
      • { … 3 },
      • { … 3 }
      ],
    • "coverage": {
      • "included_exchanges": [ … 5 ],
      • "unavailable": [ … 2 ],
      • "stale_excluded": []
      },
    • "method": {
      • "value": "own method, per fund between two consecutive issuer as-of rows: shares_x_nav = (shares_out[t] - shares_out[t-1]) x NAV[t], dated t; aum_nav_ratio_t1 (issuer pub…",
      • "funds": "number of funds contributing to that date; the aggregate is only comparable across dates with the same contributing funds (history starts on different dates per…",
      • "multi_day": "true when a contributing flow spans more than one trading day because the issuer history has no row for the day(s) in between",
      • "history_start": "issuer-provided official history is back-filled where it exists (21Shares valuation history, Franklin price history); other issuers start on the first collectio…"
      },
    • "meta": {
      • "schema": "coinboss.sd.etf/1",
      • "source": [ … 2 ],
      • "observed_at": 1794441600000,
      • "received_at": 1794537318126,
      • "fetched_at": 1794542297946,
      • "window": "30d",
      • "quality": "PARTIAL",
      • "is_stale": false,
      • "cache_ttl_s": 300,
      • "fallback": "collector failure keeps the last issuer row with its real as_of_date; a fund whose as_of_date is more than 1 trading day behind the expected as-of is flagged is…"
      }
    }

Verified samples

Besides the example above, the probe calls this endpoint with these parameters and checks the schema each time.

ParametersHTTPLatencyResult
asset=ETH&range=90d&metric=aum2005 msPass PARTIAL
asset=BTC&metric=holdings&ticker=ARKB2004 msPass FRESH
asset=BTC4001 msPass returns the expected error

Checked 2026-11-13 03:58:17 UTC

Details

Authentication
None. Public endpoint.
Rate limit
1200 requests per minute per IP
Server cache
5m
Edge micro-cache
10s
Update frequency
Three collector rounds per day (02:35, 10:35, 16:35 UTC). Issuers publish once per US trading day, usually the evening of the trade date.
Window
30d / 90d / all, one point per issuer as-of date.
Data sources
Daily disclosures published by the fund issuers themselves (holdings, net assets, shares outstanding, NAV), collected and stored by CoinBoss (sd_etf_fund_daily). Net flow is computed by CoinBoss from those disclosures.
Exchange coverage
Only funds whose issuer publishes machine-readable daily data are covered. `funds_total` and `funds_covered` state how many; every fund that is not covered is listed under `coverage.unavailable` with the reason. Totals are sums over covered funds only (`totals_scope = "covered_funds_only"`), not the whole market.
Pagination
No paging; `range` bounds the number of points.
Sorting
Date ascending.
Units
Amounts in USD; holdings in units of the underlying coin; NAV and market price in USD per share; `premium_pct` and `fee_pct` in percent.
Method
A point sums the funds that have a row on that date; `funds` is that count. Points with different `funds` are not directly comparable. Flow is bucketed by its booking date.
Timestamps
Unix epoch milliseconds (UTC) unless the field description says otherwise
Response format
json
Stability
Stable
Available since
2026-11-11

Live status

PartialChecked 2026-11-13 03:58:17 UTCHTTP 2005 msSchema matchesNewest data point 83m old

The endpoint reports data quality PARTIAL — Partial coverage: several large issuers do not offer a public machine-readable disclosure that can be collected from a server. Their funds are listed as unavailable, and totals cover the remaining funds only. Compare `funds_covered` / `funds_total` before comparing totals with other sources.

Availability, last 30 days

100% of 407 checks passed

Errors

Failed calls share one shape on every endpoint. The full list is on the errors page. Errors and rate limits →

CodeHTTPMeaningWhat to do
INVALID_PARAM400A required parameter is missing or a value is not accepted. `param` names the parameter when it is known.Do not retry unchanged; fix the request.
UNAUTHORIZED401The `CB-API-KEY` header was sent but the key is unknown or revoked. Public data needs no key — drop the header or use a valid key.Do not retry unchanged.
FORBIDDEN403The route is not part of the public API (internal or account-only).Do not retry.
NOT_FOUND404Unknown route, or the requested coin / exchange / fund does not exist.Do not retry; check the path and identifiers against the catalog.
RATE_LIMITED429More requests than the per-minute limit. `Retry-After` gives the seconds to wait.Wait for `Retry-After`, then retry with backoff.
INTERNAL500Unexpected server error. The message is generic by design; quote `request_id` when reporting it.Retry once after a few seconds; report it with the request id if it persists.
UPSTREAM_FAILED503The data source behind this endpoint did not answer in time. No stale or substitute numbers are returned in its place.Retry with backoff; check the status page.
UNAVAILABLE501 / 503The dataset is temporarily not ready (cache warming) or the endpoint has no lawful public source yet.Retry later; the catalog marks endpoints that are unavailable by design.
REQUEST_FAILED200Some older endpoints answer HTTP 200 with `success: false`. Always check `success`, not only the HTTP status.Depends on the message; treat as a failed request.

Try it

GET/api/sd/etf/historyPartial
Parameters

string — Underlying asset, case-insensitive. `coin` is accepted as an alias.

string — Series to return: holdings (coin), net assets (USD) or net flow (USD).

string · default 30d — Look-back range.

string — Fund ticker registered for the asset (for example `ARKB`). Default: all covered funds summed. An unregistered ticker returns 404; a registered fund that cannot be collected returns 200 with `series: null`.

Request URLhttps://www.coinboss.com/api/sd/etf/history?asset=BTC&metric=flow
Choose an endpoint and press “Send request”. The response, headers and timing will appear here.