Get bridge intent status
Bridge (Alpha Preview)
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
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.
Example
while(true) polling loop and how to handle stale responses
when running multiple bridges in parallel.