Skip to content

Reading the bridge's state

Two public, read-only services describe the bridge. Neither can move funds.

Service Mainnet base URL Reference
The coordinator’s API The address on Status: Addresses, once the launch is verified Coordinator API
The monitor’s status The address on Status: Addresses, once the launch is verified The monitor

The API is answered from what the coordinator writes. The monitor reads every chain from its own nodes and takes nothing from the coordinator, so the two are separate views.

GET /api/v1/signal on the monitor’s status is the answer meant for integrators (The integrators’ signal):

{
"version": 1, "at": "2026-11-05T12:00:00.000Z", "ok": true, "reasons": [],
"checkedAt": "2026-11-05T11:59:58.000Z",
"backing": { "healthy": true, "owed": "249000000", "total": "249000000", "unverifiedMinted": "0" },
"paused": { "minter": false, "pool": false, "vaults": { "ethereum": false, "bsc": false } },
"alarms": { "open": 0, "codes": [] }
}

ok is false while an alarm is open, while the backing does not cover what is owed (INV-1), while kUSDT was minted for a deposit the monitor has not seen yet (since round 20: a forged mint shows here minutes before its alarm), while the minter, the pool or a vault is paused, when the last check is over 5 minutes old, or when the monitor’s Kaspa view lags. reasons says which. backing.healthy is never true while owed exceeds total; unverifiedMinted is the part of owed the monitor has not judged against a deposit yet.

While ok is false, stop accepting new kUSDT: no new deposits credited, no kUSDT taken as payment. kUSDT transfers cannot be paused, and forged kUSDT looks like the real token, so this signal is the warning. Treat no answer, or an answer you cannot read, as ok: false. Read it from more than one monitor once more than one is published. The same facts are on-chain: the minter’s paused flag, each vault’s paused() and the pool’s paused. What to do meanwhile: When the bridge is paused.

Call Means
GET /health 200 while the monitor is healthy (no alarm open, the backing read covers what is owed, and no kUSDT minted for a deposit it has not seen yet), its last check is under 5 minutes old and its status file under a minute; otherwise 503. Point uptime checks here, and alert when it does not answer at all
GET /api/v1/monitor The last check in full: minted, released, owed and backing per chain, the alarms, the warnings, the pauses and the pool

The paths are relative to the monitor’s address on Status: Addresses. An answer can be a few seconds old: the status process reads the monitor’s files at most once a second (Operating it).

The full list, with every field, is on Coordinator API: Calls. What each one is for:

Call Use it to
GET /health See whether the coordinator is running and following its chains. 503 says it is stopped, behind, or cannot write, and says why
GET /status Read the deployment: kUSDT’s covenant ID (kaspa.covenantId), the pool’s (kaspa.poolId), each vault’s address, parameters, fees and paused, and the finality tiers. Take the IDs and addresses from here instead of hard-coding them
GET /reserves Read the supply and the backing. healthy means backing ≥ minted − released (INV-1)
GET /tokens?owner=… List an owner’s kUSDT states
GET /positions?owner=… List an owner’s liquidity positions
GET /pool Read the pool for a quote: its states, spot prices, the circuit breaker’s room, paused. 404 until the pool exists, 503 with retryAt while the coordinator is not keeping it current
GET /deposits/:chain/:nonce, GET /deposits?sender=… Follow a deposit until it is minted, or refunded
GET /recipients/:chain/:address Ask whether the vault would pay an EVM address. Burn only when payable is true
GET /redeems/:txid/:outputIndex Follow a redemption until it is released
POST /redeems Report a burn the coordinator has not seen. A report is a claim, not a fact (Reporting a burn)

The statuses a deposit, a refund and a redemption go through are on Status values.

Every answer that matters can be checked against a node. A wallet, an exchange or a site that holds value should check token and pool states on its own node before it acts on them (Verifying answers).

  • Exact integers. Amounts can exceed 2⁵³, and a large one can arrive as a decimal string. Some fields are always strings (every breaker and exact value, genesisRemaining, each tier’s above). Parse numbers and strings exactly, never as JavaScript numbers.
  • How old. The records are as of the coordinator’s last save, a few seconds behind. GET /health and GET /pool answer 503 rather than serve a copy more than 15 seconds old (Where the answers come from).
  • 503 and 429 carry retryAt. Ask again then, not before.
  • stale: true on /tokens or /positions is the last answer, given while the reads are over their budget.
Limit API Monitor status
Requests per client address per minute 240 by default, when the operator turns the count on; 429 past it 240 by default, when the operator turns the count on; 429 past it
Request body 512 kB (413 above it), whole within 10 seconds
Bodies read at a time 64 in all, 4 from one client, 16 from one client network (an IPv4 /24, an IPv6 /48), the last 16 only for a network that holds none (429 past it)
Recipient checks not already answered (/recipients) 120 a minute in all by default (503 with retryAt past it), 20 a minute from one client network (429 with retryAt)
Reported burns waiting (POST /redeems) 32 at once, each for 15 seconds; 503 with retryAt past it

Details: Request limits and Operating it. A proxy in front can add limits of its own.

Both services answer with Access-Control-Allow-Origin: *, allow GET, POST and OPTIONS and the Content-Type header, and answer a preflight OPTIONS with 204. A page on any site can read them from the browser. A preflight counts as a request toward the client’s limit per minute, and is refused with 429 past it like any other (since run 21; it used to be answered whatever the count).