Documentation

Status

What is happening right now.

4 endpoints · all GET · no key · samples in curl, Python, JavaScript and Go

GET /v1/status

The board: every venue, every component, open incidents

import httpx

r = httpx.get(
    "https://api.up24.app/v1/status",
    params={"category": "exchange"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

One request renders the whole status board. Carries each venue’s 90-day bars and a 24-point latency sparkline, because the alternative is twelve detail requests to draw one screen and both series come free with reads this endpoint already does.

Per-component percentiles are deliberately absent: this is the cheapest and most requested endpoint in the product, and 24h percentiles per component would turn it into a scan of a day of raw measurements. They are on /v1/exchanges/{venue}.

category narrows the rows and the fleet numbers above them together. The one thing it does not narrow is summary.categories, which counts every category on the board so a page can render one category and a way to reach the others from one request.

Parameters

categorystringquery

Only rows of this category. Absent means every category, which is what an unparameterised request has always meant and still means. A category up24 does not measure is not an error: it answers with an empty list rather than a 404, because "nothing here yet" and "no such thing" are different answers and a caller polling for a category up24 is about to add should not have to tell them apart from a status code.

"exchange""rpc""market-data""oracle""stablecoin""bridge""ramp"

Responses

  • 200The current board.
  • 400`category` is not one of the accepted values.
  • 429Over the origin rate limit.

200 returns StatusResponse

generatedAtstring (date-time)
summaryobject
summary.venuesinteger
summary.regionsinteger
summary.probeIntervalMsinteger

The fleet’s default polling interval, in milliseconds, per region. An endpoint whose provider rations its free tier can be slower; /v1/exchanges/{venue} carries the resolved cadence per endpoint.

min 1

summary.statestring

"operational""degraded""outage""unknown"

summary.uptimePct90dnumber | null
summary.medianLatencyMsinteger | null
summary.activeIncidentsinteger
summary.categoriesobject[]

Counts for every category up24 lists, unaffected by category — the rest of this object describes the rows in this response, and this describes the board they came from.

incidentsIncident[]

GET /v1/exchanges/{venue}

One venue in full

import httpx

r = httpx.get(
    "https://api.up24.app/v1/exchanges/binance",
    params={"range": "24h", "region": "eu-central", "format": "json"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

Heavier than the board by design — it reads raw samples — and requested one venue at a time behind the same edge cache. Its latency points and its per-endpoint p50Ms / p95Ms are exact percentiles over raw samples, not the rollup medians the board prints, which is why they can disagree with typicalMs and why both names exist.

Its summary is the same object /v1/reliability carries for this venue, from one helper over the same rows: a venue’s uptime cannot read one way on its own page and another on the leaderboard.

lag is present on categories that read a chain and null on every other row. It is per region and never pooled: a provider can be current in one region and a block behind in another, and that difference is the finding rather than noise to average away. Read reference before quoting a figure — the lag is measured against the freshest head up24’s own fleet saw on that chain from that region, not against the chain’s true head, which is not observable from outside without trusting one provider to report it.

Parameters

venuestringpathrequired

Registry id of the exchange.

"binance""bybit""coinbase""kraken""okx""bitfinex""deribit""bitstamp""gemini""cryptocom""hyperliquid""upbit""binance-futures""bybit-futures""okx-futures"

rangestringquery

Window for the latency chart. 24h buckets per minute, 7d per hour.

"24h""7d"

Defaults to "24h".

regionstringquery

Which probe region the latency chart, the endpoint table and the stream table describe. Defaults to the primary region, so an unparameterised request means what it meant when there was one box. It does not change days, uptimePct90d or state: those combine every region by quorum. Whether an exchange is up is a fact about the exchange; how fast it answers is a fact about the route, and only the second one has a vantage point. The regions.compare block carries every region at once — that is the number to quote when the question is "from where?".

"eu-central""ap-southeast""us-east"

Defaults to "eu-central".

formatstringquery

Response shape. json is the default and is the whole of it; csv is a flat projection of the same object, with content-disposition set so a browser saves it. Every CSV row carries generatedAt, the window, the measured part of the window and methodologyUrl as columns rather than as a header comment — this is the output that ends up in a spreadsheet and gets quoted from a slide six months later, and a caveat a parser strips is a caveat that will not be there when it is needed. Here: one row per day of the 90-day window — the series that never expires and the one an auditor archives. A day nobody measured is an empty uptimePct, never a zero and never a missing row.

"json""csv"

Defaults to "json".

Responses

  • 200The venue, in detail.
  • 400`range` or `region` is not one of the accepted values.
  • 404No such venue in the registry.
  • 429Over the origin rate limit.

200 returns ExchangeResponse

generatedAtstring (date-time)
exchangeobject
exchange.idstring

"binance""bybit""coinbase""kraken""okx""bitfinex""deribit""bitstamp""gemini""cryptocom""hyperliquid""upbit""binance-futures""bybit-futures""okx-futures"

exchange.namestring
exchange.categorystring

What kind of infrastructure this row is: an exchange, an RPC provider, a market-data API, an oracle, a stablecoin, a bridge or a fiat ramp. It is what says which columns are honest for the row — a block lag means nothing on an exchange and an order book means nothing on an oracle — so read it before comparing two rows on the same number.

"exchange""rpc""market-data""oracle""stablecoin""bridge""ramp"

exchange.symbolstring | null

The instrument up24 probes, in this venue's own notation — XBTUSD on Kraken, tBTCUSD on Bitfinex — not a normalised one, so it matches what you would type into that venue’s own API. Null on any category that trades no instrument, which today is every rpc row.

exchange.quotestring | null

The currency the symbol is priced in. Venues differ, so do not compare prices across them naively. Null on any category that trades no instrument, for the same reason symbol is.

statestring

"operational""degraded""outage""unknown"

sincestring (date-time)
uptimePct90dnumber | null
typicalMsinteger | null
latencyobject
latency.rangestring

"24h""7d"

latency.bucketMsinteger

min 1

latency.pointsLatencyPoint[]
endpointsobject[]
regionsobject
regions.selectedstring
regions.compareRegionComparison[]
incidentsIncident[]

The 50 most recent, newest first, with each one’s official counterpart attached. Capped because the official join is one lookup per row; incidentPatterns covers the whole window and carries a link to every incident in it.

incidentPatternsobject[]
officialobject
official.sourcestring | null
official.pagestring | null
official.observedboolean
official.incidentsOfficialIncident[]
detectionDetection

GET /v1/targets/{venue}

One venue in full, under the general name

import httpx

r = httpx.get(
    "https://api.up24.app/v1/targets/binance",
    params={"range": "24h", "region": "eu-central", "format": "json"},
    timeout=10,
)
r.raise_for_status()
data = r.json()

The same response as /v1/exchanges/{venue}, byte for byte, from one handler registered at two paths. up24 measures more than exchanges from M14 on — RPC providers, market-data APIs, oracles — and asking for an oracle at a path that says "exchanges" would be a URL that lies about its own contents.

/v1/exchanges/{venue} is not deprecated and will not be removed. It is embedded in badges and dashboards up24 does not control, and a working path is worth more than a consistent vocabulary. Use this one in new integrations; there is no reason to move an old one.

Parameters

venuestringpathrequired

Registry id of the venue, whatever its category.

"binance""bybit""coinbase""kraken""okx""bitfinex""deribit""bitstamp""gemini""cryptocom""hyperliquid""upbit""binance-futures""bybit-futures""okx-futures"

rangestringquery

As on /v1/exchanges/{venue}.

"24h""7d"

Defaults to "24h".

regionstringquery

As on /v1/exchanges/{venue}.

"eu-central""ap-southeast""us-east"

Defaults to "eu-central".

formatstringquery

As on /v1/exchanges/{venue}.

"json""csv"

Defaults to "json".

Responses

  • 200The venue, in detail.
  • 400`range` or `region` is not one of the accepted values.
  • 404No such venue in the registry.
  • 429Over the origin rate limit.

200 returns ExchangeResponse

generatedAtstring (date-time)
exchangeobject
exchange.idstring

"binance""bybit""coinbase""kraken""okx""bitfinex""deribit""bitstamp""gemini""cryptocom""hyperliquid""upbit""binance-futures""bybit-futures""okx-futures"

exchange.namestring
exchange.categorystring

What kind of infrastructure this row is: an exchange, an RPC provider, a market-data API, an oracle, a stablecoin, a bridge or a fiat ramp. It is what says which columns are honest for the row — a block lag means nothing on an exchange and an order book means nothing on an oracle — so read it before comparing two rows on the same number.

"exchange""rpc""market-data""oracle""stablecoin""bridge""ramp"

exchange.symbolstring | null

The instrument up24 probes, in this venue's own notation — XBTUSD on Kraken, tBTCUSD on Bitfinex — not a normalised one, so it matches what you would type into that venue’s own API. Null on any category that trades no instrument, which today is every rpc row.

exchange.quotestring | null

The currency the symbol is priced in. Venues differ, so do not compare prices across them naively. Null on any category that trades no instrument, for the same reason symbol is.

statestring

"operational""degraded""outage""unknown"

sincestring (date-time)
uptimePct90dnumber | null
typicalMsinteger | null
latencyobject
latency.rangestring

"24h""7d"

latency.bucketMsinteger

min 1

latency.pointsLatencyPoint[]
endpointsobject[]
regionsobject
regions.selectedstring
regions.compareRegionComparison[]
incidentsIncident[]

The 50 most recent, newest first, with each one’s official counterpart attached. Capped because the official join is one lookup per row; incidentPatterns covers the whole window and carries a link to every incident in it.

incidentPatternsobject[]
officialobject
official.sourcestring | null
official.pagestring | null
official.observedboolean
official.incidentsOfficialIncident[]
detectionDetection

GET /v1/regions

Where the fleet watches from, and the rule it combines by

import httpx

r = httpx.get(
    "https://api.up24.app/v1/regions",
    timeout=10,
)
r.raise_for_status()
data = r.json()

Every probe region, whether it is currently reporting, and how much it shipped in the last hour. reporting is measured rather than configured: a box that was provisioned and never started, or one that died overnight, is listed as false rather than quietly omitted.

quorum is how many reporting regions must agree before a venue is called down — a simple majority. One region failing is a route or a geo-block, not an exchange outage, and this endpoint publishes the rule so the incident record can be checked against it rather than taken on faith.

Responses

  • 200The probe fleet.
  • 429Over the origin rate limit.

200 returns RegionsResponse

generatedAtstring (date-time)
quoruminteger