Documentation

Schemas

The shapes that appear in more than one response, written once. These are generated from the same definitions core validates its own responses against, so a field here is a field the API returns.

32 shapes · generated from /openapi.json

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[]

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

ReliabilityResponse

generatedAtstring (date-time)
daysinteger

min 1

fleetobject
fleet.venuesinteger
fleet.uptimePctnumber | null
fleet.typicalP50Msinteger | null
fleet.typicalP95Msinteger | null
fleet.incidentsinteger

DetectionResponse

generatedAtstring (date-time)
daysinteger

min 1

venuesobject[]

IncidentsResponse

generatedAtstring (date-time)
incidentsIncident[]

IncidentDetailResponse

generatedAtstring (date-time)
incidentIncident
venueobject
venue.idstring

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

venue.namestring
venue.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.

venue.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.

componentobject
component.idstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

component.kindstring

"rest""ws"

component.labelstring
component.targetstring | null
detectionDetection
officialobject
official.sourcestring | null
official.pagestring | null
official.observedboolean
relatedIncident[]

HealthResponse

statusstring
servicestring

"core""web""probe"

versionstring
uptimeSecondsinteger
timestring (date-time)

RegionsResponse

generatedAtstring (date-time)
quoruminteger

ThresholdsResponse

generatedAtstring (date-time)
versionstring

Incident

idinteger

min 1

slugstring

Stable permalink id — {venue}-{YYYY-MM-DD}-{rest|ws}, with -2, -3 for a second incident of the same shape on the same day. Never rewritten after it opens. Incidents opened before 12 Sep 2026 carry a fourth segment naming the severity they had at the moment they opened; it was dropped because severity is the one field an incident is meant to revise, and those slugs keep serving unchanged.

e.g. "binance-2026-08-12-rest"

venuestring

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

componentstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

severitystring

The worst state reached, not the state right now — an incident is named for its peak.

"degraded""outage"

startedAtstring (date-time)
endedAtstring (date-time) | null

When the venue came back, not when the state machine finished clearing. Null while open.

durationMsinteger

To endedAt, or to now while the incident is open.

summarystring
errorClassstring | null

"timeout""dns""tls""conn""http_429""http_403""http_451""http_4xx""http_5xx""bad_body""stalled""rejected""refused""unknown""lag"

retractedobject | null

Set when up24 withdrew this incident as its own fault — a probe bug, not the venue. Retracted incidents are excluded from every list, count and feed; the permalink keeps serving so the record of the correction is public. Null for every incident that stands.

retracted.atstring (date-time)
retracted.reasonstring
leadMsinteger | null

Their acknowledgment minus our detection, in ms. Positive means up24 timestamped first; negative means the venue did. Null wherever official is null. Time order only — see subjectMatched, which is false on every pairing: nothing checks that the notice is about the same fault.

IncidentEvent

atstring (date-time)
kindstring

"detected""escalated""acknowledged""venue-resolved""recovered"

severitystring | null

"degraded""outage"

errorClassstring | null

"timeout""dns""tls""conn""http_429""http_403""http_451""http_4xx""http_5xx""bad_body""stalled""rejected""refused""unknown""lag"

titlestring | null
urlstring | null

IncidentLatency

scopestring

"endpoint""venue"

endpointstring | null
bucketMsinteger

min 1

fromstring (date-time)
tostring (date-time)

ErrorBreakdown

sourcestring | null

"rollup_1m""stream_health"

classesobject[]
observationsinteger
failedinteger

OfficialIncident

sourcestring
kindstring

"incident""maintenance"

titlestring
urlstring
startedAtstring (date-time)
endedAtstring (date-time) | null
acknowledgedAtstring (date-time)
impactstring | null
observedboolean
subjectMatchedboolean

Always false. Pairing is a symmetric ±6h window on the same venue and nothing tests that the notice describes the fault up24 measured — hand-checking the fleet in Aug 2026 found every pairing was a different subject. Read leadMs as time order, not as a scoop.

Detection

incidentsinteger
matchedinteger
aheadUncorrelatedinteger

Of matched, how many up24 timestamped before the venue published. Time order only: pairing is a symmetric ±6h window with no test that the two describe the same fault, and every pairing carries subjectMatched: false for that reason. Not a count of scoops, and not to be quoted as one.

medianLeadMsinteger | null
bestLeadMsinteger | null

VenueStatus

idstring

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

namestring
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"

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.

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

Ok checks over total checks across 90 days, 0–100, floored to two decimals so 100 means no check failed. REST only — a stream has no "check" to be a denominator. Null where the venue was never measured.

typicalMsinteger | null

Median of the last 24h of per-minute p50s, in ms. Not the 24h p50 — percentiles do not compose. The exact figure is on /v1/exchanges/{venue}, which computes it from raw samples.

measuredDaysinteger

Days of the 90-day window with at least one check. Read it beside uptimePct90d: the percentage covers these days and no others.

methodologyUrlstring (uri)

How every figure on this row is computed, including what counts as an ok check and how regions are combined. Travels with the row so a number quoted elsewhere keeps its method.

openIncidentsinteger
unknownComponentsinteger
sparkinteger | null[]

ComponentStatus

idstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

kindstring

"rest""ws"

labelstring
targetstring
statestring

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

sincestring (date-time)
errorClassstring | null

"timeout""dns""tls""conn""http_429""http_403""http_451""http_4xx""http_5xx""bad_body""stalled""rejected""refused""unknown""lag"

UptimeDay

daystring
uptimePctnumber | null
checksinteger
statestring

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

RegionSummary

idstring
labelstring
citystring
countrystring
primaryboolean
reportingboolean
lastSampleAtstring (date-time) | null
samples1hinteger
venuesinteger
firstSampleAtstring (date-time) | null

When this probe box first shipped a sample. Read it beside preliminary: it is the denominator behind every number this region contributes.

preliminaryboolean

True while the box has been measuring for fewer than seven days — the same window every baseline in the incident engine is computed over, so a younger region has no normal to be abnormal against and its percentiles still describe the box settling in. The readings are published either way; this says how much weight they have earned. False for a region that has never reported at all, which is reporting: false rather than preliminary.

RegionComparison

idstring
labelstring
citystring
countrystring
p50Msinteger | null
p95Msinteger | null
uptimePct24hnumber | null
checks24hinteger
preliminaryboolean

True while this box has been measuring for fewer than seven days. Its numbers are real measurements; they have simply not seen a full baseline window yet.

blockedobject | null

Set where this vantage point cannot measure this venue, and null — the usual case — where it can. The refused checks are out of checks24h and uptimePct24h and counted in blocked.checks24h instead: they say what the venue does about this vantage point, not whether it is up. Read fault before quoting the row — venue is the target refusing this country, vantage is up24’s own box or route failing to reach a target that is serving everyone else.

blocked.faultstring

venue — the target refuses this vantage point, so its refusals say nothing about availability. vantage — up24’s own probe host or route cannot reach a target that is answering elsewhere, so the readings measure up24 rather than the target.

"venue""vantage"

blocked.errorClassstring

The class discounted. Any other reading from this region counts as normal.

"timeout""dns""tls""conn""http_429""http_403""http_451""http_4xx""http_5xx""bad_body""stalled""rejected""refused""unknown""lag"

blocked.sincestring

The first day it was measured, YYYY-MM-DD.

blocked.untilstring | null

The day it stopped, or null while it is still in force.

blocked.notestring

What was observed and what settled it, in plain words.

blocked.urlstring (uri) | null

The venue’s own document, where one was readable.

blocked.checks24hinteger

Refused checks in the last day. Out of the uptime denominator, kept here.

LatencyPoint

tstring (date-time)
p50Msinteger | null
p95Msinteger | null
okinteger
totalinteger

StreamStatus

idstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

labelstring
channelstring
statestring

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

sincestring (date-time)
connectedPct24hnumber | null
deliveringPct24hnumber | null
messages24hinteger | null
maxGapMs24hinteger | null
seqGaps24hinteger | null
seqCheckedboolean
reconnects24hinteger | null
rttMsinteger | null

StreamSummary

connectedPct24hnumber | null
deliveringPct24hnumber | null
reconnects24hinteger | null
seqGaps24hinteger | null
seqCheckedboolean
maxGapMs24hinteger | null
coveragePct24hnumber | null

Share of the last 24 hours, 0–100, that up24 has stream evidence for on this venue. Everything else in this object is computed over these windows only.

probeFaultboolean

True when some of the 24-hour window is missing or was discarded as up24’s own fault, so the percentages above describe less than a day. Never a statement about the venue.

ReliabilitySummary

daysinteger

The window asked for.

min 1

measuredDaysinteger

Days of that window with any measurement at all. Quote it beside days: a venue watched for eight days of ninety has not been 99.99% for a quarter.

uptimePctnumber | null

Ok checks over total checks across the window, 0–100, floored to two decimals so 100 means no check failed. REST only, as everywhere.

checksinteger

The denominator behind uptimePct. Quote both or neither.

worstDayUptimeDay | null

The measured day with the lowest uptime. Null when nothing was measured.

typicalP50Msinteger | null

Median of the window’s *daily* p50s, in ms — not the window’s own percentile. Percentiles do not compose, and the daily rollup is the finest grain that outlives raw retention.

typicalP95Msinteger | null

Median of the window’s *daily* p95s, in ms. Same caveat as typicalP50Ms.

incidentsinteger

Incidents up24 opened in the window. Not what the venue announced.

ReliabilityVenue

venuestring

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

namestring
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"

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.

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)
openIncidentsinteger
detectionDetection
officialobject
official.sourcestring | null
official.pagestring | null

PublishedRule

idstring
labelstring
valuenumber
unitstring

"ms""count""percent""days""multiple"

whystring

BlockLag

chainstring
chainNamestring
blockTimeMsinteger

The chain’s documented block time, from the page blockTimeUrl names.

min 1

blockTimeUrlstring (uri)
blockTimeCaveatstring | null

Set where the documented block time is a ceiling rather than a heartbeat — Arbitrum One produces a block only when there are transactions to sequence, and Base streams preconfirmations faster than its canonical block. Null where the number means what it says.

referencestring

What the lag is measured against, in words, so the number never travels without it.

referenceMsinteger

How near in time two readings must be to be compared. Two heights read at two instants differ by whatever the chain built in between; the fleet’s polling spread is corrected out at the documented block time, one-directionally, so the correction can only remove lag and never add it — and lag smaller than this width is therefore invisible.

min 1

degradedMsinteger

Where the incident engine calls this provider degraded. Also on /v1/thresholds.

min 1

hoursinteger

The window the figures cover.

min 1

BlockLagRegion

regionstring
typicalBlocksnumber | null

Median of the per-minute readings over the window, in blocks. Null where this region produced no comparable round — one provider alone is its own reference, and a lag of zero off a fleet of one would be a flattering fiction rather than a measurement.

worstBlocksnumber | null

The largest single-minute reading in the window, in blocks.

typicalMsinteger | null

typicalBlocks at the chain’s documented block time, which is the unit the threshold is expressed in — a threshold in blocks would be three thresholds and would fire on an idle Arbitrum minute. Read blockTimeCaveat before treating it as elapsed time.

minutesinteger

Minutes of the window that produced a reading — the denominator behind the two figures above. Fewer than the window holds is normal: the block read is polled every 45 seconds, so about one minute in four contains no round at all.

StallThreshold

venuestring

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

venueNamestring
componentstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

channelstring
stallMsinteger

How long this feed may say nothing, from this region, before the window is counted as failed. Read off the measured distribution of the feed’s own quiet periods, not picked.

min 1

regionstring

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

regionOverrideboolean

True where this feed is measurably quieter from this vantage point than elsewhere and so carries its own threshold. Latency is never averaged across regions for the same reason.

AlertPayload

eventstring

incident.opened, incident.escalated or incident.closed — the conventional shape for a webhook, and the field to route on. kind is the same value without the prefix.

kindstring

Which of the three this is. escalated is separate from opened because a degradation becoming an outage is one incident throughout — the engine escalates in place rather than opening a second.

"opened""escalated""closed"

eventIdinteger

The event’s own id. Delivery is at-least-once by design, so de-duplicate on this. Zero on a test alert, which corresponds to no event and no incident — a subscriber that keys off these ids therefore ignores tests for free instead of storing one under a fabricated real id.

incidentIdinteger

The incident all three events of one fault share, and therefore the right thing to group by — or to use as a pager’s deduplication key, so an escalation updates the page it opened and a close resolves it.

venuestring

The venue, as its id on this site.

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

venueNamestring

The venue’s display name, as the board writes it.

componentstring

One REST endpoint or one WebSocket stream of one venue — rest:ticker, ws:book. ws:conn is the shared socket itself, which is where a connection-scoped fault is recorded.

matches ^(rest|ws):[a-z]+$ · e.g. "rest:ticker"

severitystring

What the engine graded the incident. The two it can open at; a channel’s severity floor decides which of them reaches you.

"degraded""outage"

statestring

What the component is right now — operational on a close, which is the one event where this and severity deliberately disagree.

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

summarystring

One sentence, produced by a switch over states with the measured numbers substituted in. Never model-written, which is why it is safe to forward verbatim.

errorClassstring | null

The dominant failure behind the incident — one of timeout, dns, tls, conn, http_429, http_403, http_451, http_4xx, http_5xx, bad_body, stalled, rejected, refused, unknown, lag — or null where there was no single one. stalled and rejected come only from stream monitoring: a stalled feed is not a timeout, the socket is open and the venue has simply stopped saying anything.

startedAtstring (date-time)

When the incident began, which is not when this event was sent.

endedAtstring (date-time) | null

Null while the incident is open. On a close it is when recovery began, not when the engine’s two-minute confirmation hold expired.

occurredAtstring (date-time)

When this event was written, within one engine tick of the change it reports. The delivery timestamp is on the dashboard’s log, not in the body.

urlstring

Where a human goes to see it: the venue’s page on up24, with the window, the denominator and the vantage points the verdict was reached from.

testbooleanoptional

Present and true only for the test button on the dashboard. Absent on every real alert.

NotifyResponse

generatedAtstring (date-time)
daysinteger

min 1

deliveriesinteger

How many delivered openings the two percentiles are over — deliveries only, not the skips and failures the delivery log also records, and not a backfilled event. Zero means nothing has been delivered in the window and both percentiles are null.

p50Msinteger | null

Median of delivered_at − startedAt across every opening alert delivered in the window, over every channel and every account. Includes detection — the engine needs consecutive bad samples before it opens anything — so this is time from the fault, not time from the decision. Excludes any event that waited over an hour in the outbox before a delivery was claimed for it, which is a backfill rather than a notification. Null when deliveries is 0.

p95Msinteger | null

The same measurement at the 95th percentile: the slow tail, which is the one worth quoting at a desk. Read it against deliveries — a p95 over a handful of alerts is that handful’s worst one. Null when deliveries is 0.

Error

Every failure on this API, at every status. A 4xx carries the reason; a 5xx is always the opaque string internal error, because the alternative is publishing stack shapes to strangers.

errorstring