Get bridge intent status
Bridge Status
[Alpha Preview] Look up the status of a bridge intent, or long-poll until it terminates.
GET
Get bridge intent status
Two endpoints share this page:
This is the expected state right after the deposit is broadcast but before
the solver has indexed it. Keep polling.
Long-poll variant. Blocks server-side until the intent reaches
Pass the key as the
Every other destination returns a real
Omit
WebSocket or
Both are push — neither makes you poll. Use the WebSocket when you want the
progress (a status bar that moves through
See the Bridge Implementation guide for the
full no-sleep
GET /api/2/bridge/status/{id}— returns the current row immediately.GET /api/2/bridge/status/{id}/wait— long-polls server-side until the intent reaches a terminal state (or the timeout elapses).
Path parameter
id accepts any of these — pass whichever you have:
intentIdfrom/quote(formatxxxxxxx-xxxxxxx-xxx).- The on-chain
bytes32intent ID (EVM only, emitted byMobulaBridge). - The deposit TX hash.
- The fill TX hash.
Response
latencyMs is the deposit-detected → fill-confirmed delta. settleTxHash /
timestamps.settled populate only once the solver has been reimbursed on
the origin chain — that step is async and can lag the user-visible fill. On a
slippage refund, failureReason.code is "slippage" and a human-readable
message field is added telling the user to raise their slippage.
fillTxHashPending is true when the fill is already complete
(status: "filled") but its canonical destination tx hash hasn’t been indexed
yet — the case for Hyperliquid destinations, whose L1 hash is assigned a
moment after the funds move. While it’s true, fillTxHash is null. Treat the
bridge as done as soon as you see filled; fetch the hash separately (see the
best practice below).
Status lifecycle
The statuses the solver actually writes:
On deposit detection the solver writes
filling directly — there is no
intermediate deposited status. (deposited and retrying exist in the
underlying type enum but are not currently emitted; retries are tracked in a
separate queue and the intent stays in filling.) A relaying intent resolves
to filled (or refunded) like any other; the terminal row then carries
isRelayFallback: true and a relayRequestId. Treat any non-terminal status
as “keep waiting,” and any unknown status defensively.
The terminal set is filled, settled, failed, refunded. Stop polling once
you see one of them.
GET /status/{id}/wait
Long-poll variant. Blocks server-side until the intent reaches filled,
settled, failed, or refunded, then returns the same shape as
/status/{id}. If the window elapses first, you get the current
(non-terminal) row and should call again.
Query parameter
How it actually waits
The server holds the request open and resolves it the moment your intent reaches a terminal state (filled, settled, failed, or refunded) — the
result is always current, with no client-side polling interval to tune.
In practice, fills are delivered with the latency of the destination chain —
typically a few hundred ms. The 30 s default is just an upper bound; you almost
always return earlier.
Recommended client loop
?apiKey= query param (not an Authorization header).
Don’t add a client-side sleep — the server already blocks until something
happens; firing again with no delay keeps one open long-poll waiting for the
next state change.
Stale-response handling
If you start a new bridge while a previous/wait is still in flight, the
previous response will arrive after your new intentId is active. Track
the active intent ID client-side and discard any /wait result that doesn’t
match it — otherwise you’ll attach an old fill TX to the new attempt.
Best practice: don’t block completion on the fill hash (Hyperliquid)
A Hyperliquid-destination fill is final the instant the funds leave HL, but HL only assigns the canonical L1 transaction hash a moment later. The solver therefore marks the intentfilled immediately and patches fillTxHash in
afterward — so a filled response can briefly carry fillTxHash: null with
fillTxHashPending: true.
Show the user “bridge complete” as soon as status is filled — do not wait
on the hash. Then, only if you want an explorer link, make a second long-poll
with ?waitForFillTxHash=true and update your UI when the hash lands:
fillTxHash up front (fillTxHashPending: false), so the second call returns immediately and this branch is a no-op.
Live updates over WebSocket
bridge-status is the push equivalent of this endpoint: subscribe to an intent
and the server sends its status now, then again on every transition —
including the intermediate ones (pending → filling → filled) that a
one-shot long-poll can’t report.
It’s a channel on the standard Mobula gateway (wss://api.mobula.io), so the
subscribe / unsubscribe contract is the same as every other stream and one
connection can carry bridge tracking alongside your market subscriptions.
Subscribe
Frames
data is byte-for-byte the data of GET /status/{id} — same fields, same
fillTxHashPending semantics, same failureReason.
A frame is sent only when something actually changed, so an intent that sits in
filling stays quiet rather than repeating itself.
Frames are pushed, not polled: the solver announces each transition the moment it
commits it and the server forwards it straight to your socket. Expect a frame
within a few milliseconds of the state change on-chain — ahead of what
/status/{id}/wait can return, and far ahead of any client-side polling loop.
final is true on the last frame an intent will ever produce — its status
reached filled, settled, refunded or failed. The server then stops
tracking that id: there is nothing left to unsubscribe from, and re-subscribing
to it simply replays the terminal row.
If the id has no row yet (deposit broadcast but not yet indexed) you get no
frame until one exists — the subscription is live and waiting, exactly like the
pending reply on the REST endpoint.
Unsubscribe
subscriptionId to drop every bridge-status subscription on the
connection. Everything is released automatically when the socket closes.
Example
WebSocket or /wait?
Both are push — neither makes you poll. Use the WebSocket when you want the
progress (a status bar that moves through filling), when you’re following
several bridges at once, or when you already hold a gateway connection. Use
/status/{id}/wait when a single request that returns the finished bridge is
all you need — a script, a server-side flow, a backend with no socket to spare.
Example
while(true) polling loop and how to handle stale responses
when running multiple bridges in parallel.