All three methods require an authenticated wallet session, and delegated-agent sessions are refused with
403 on every one of them, permanently rather than as
a rollout state.
The maker requirement applies differently per method. claimLease and
refreshQuotes are launch-scoped and need a session whose user and application
both match that launch’s configured maker; a launch the caller is not the maker
for reads as 404 rather than 403, so the endpoint never confirms a launch the
caller has no part in. listAssignments takes any authenticated wallet and
simply filters by it — a non-maker gets an empty page, not an error.
ownerId is a process fence, not authorization. It is a UUID you choose to
identify the process holding the lease; authorization is derived entirely from
the authenticated session’s user and application binding and never from any
identity in the request body, so no ownerId widens what a caller can reach.
It does not let a standby seize a live lease either. A claim from a different
ownerId succeeds only once the current lease has expired; until then it answers
409. So a takeover is “wait out the remaining lease, then claim”, not “claim
harder”. Claiming after expiry bumps generation, which is what makes the
previous holder’s next refresh fail as stale.
A claim from the current owner behaves differently depending on
expectedGeneration. Supply it and the call renews: the lease’s expiry moves
out and the generation is unchanged. Omit it while you still hold an unexpired
lease and the call reconciles rather than renews — it replays the existing
reservation and returns its original expiresAt. A loop that keeps omitting the
generation expecting a renewal will let its own lease lapse.
generation and quoteRevision are uint64 fences carried as exact decimal
strings in JSON (ManagedMarketFence) and as uint64 over gRPC. Keep the
wire value as text, but do not order or increment it as text — "10" < "2"
lexically — and do not round-trip it through Number, which loses values above
2^53. Use BigInt:
(request?: ListManagedMarketAssignmentsRequest) => Promise<ListManagedMarketAssignmentsResponse>
List the launches this maker wallet is assigned to, for the authenticated
application.Parameters: all optional
page?: number — 1-based page number,1–10000(default1)pageSize?: number —1–100; this endpoint defaults it to100rather than the shared20
400 below: page must be >= 1, page must be <= 10000, or pageSize must be between 1 and 100.Returns: ListManagedMarketAssignmentsResponse:items:ManagedMarketAssignment[]—launchId,tradingPairId,symbol,phase,refreshIntervalMs,allocationUsdcandquoteEnabledtotal,page,pageSize: numberinventoryObservedAt: string — when the server read this inventory (ISO 8601)
quoteEnabled: false is still yours and still listed, but claimLease and
refreshQuotes on it answer 409 until the launch is ready to quote: its
launch phase is "warming", "activating" or "live", its runtime phase is
warming or live, and its allocated collateral has reached the configured
allocation in full. "activating" counts — keep quoting through
activation, which is the phase that depends on those quotes.lease is declared on the type but never populated by this endpoint. The
handler sets it to None on every row on purpose — the database reservation
cannot prove the engine’s current generation or quote revision, and a
fabricated zero would read as a usable fence — and the field is
skip_serializing_if = "Option::is_none", so the key is absent from the JSON
entirely rather than present as null. claimLease is the only source of a
lease you may act on.phase here is the launch phase: "pending", "validating",
"registering", "warming", "activating", "live" or "failed". The
phase on a quote refresh is a different, narrower vocabulary — see
refreshQuotes below.Errors: 401 (auth required), 403 (delegated-agent session), 400
(invalid pagination), 429 (this is an authenticated GET, so it is charged
to your per-account read budget before the handler runs — a polling loop
here is bounded like any other read), 500.A wallet that is simply not this application’s configured maker is not an
error: it gets an empty page. 403 is for delegated-agent sessions only.(launchId: string, request: ClaimManagedMarketLeaseRequest) => Promise<ManagedMarketLease>
Claim, renew or reconcile the maker lease on one launch. A lease runs for 30
seconds and is the fence every quote refresh is checked against.Parameters:
ownerId: string — UUID identifying the claiming processexpectedGeneration?:ManagedMarketFence— required when renewing an unexpired lease you already hold; omit it for an initial claim or after expiry
ManagedMarketLease — launchId, ownerId, the engine-observed
generation and quoteRevision, expiresAt, refreshIntervalMs and the
launch phase.The reply is the engine’s view, not the database reservation: the call
reserves the lease, asks the matching engine to fence it, and then rechecks
ownership, so a lease that expired in flight fails rather than being reported
as held. An initial claim whose response was lost replays its existing
reservation instead of incrementing generation, so a transport retry does
not cost you the lease you already hold.Read generation back from this reply and carry it into refreshQuotes
rather than assuming it survived from an earlier call.Errors: 400 (launchId or ownerId is not a UUID), 401, 403
(delegated-agent session), 404 (no such launch for this maker and
application), 409 (Managed market is not ready for maker quotes, or
Managed market lease changed or expired; reconcile the lease), 429 (the
claim costs one item against your order-creation budget), 500, 503 (the
matching engine is unreachable).(launchId: string, request: RefreshManagedMarketQuotesRequest) => Promise<ManagedMarketQuoteStatus>
Ask the engine to restate this launch’s bounded quote set under a lease you
hold, and report what it now holds.Parameters:
ownerId: string — the same process UUID the lease was claimed withgeneration:ManagedMarketFence— the generation fromclaimLeasequoteRevision:ManagedMarketFence— must be positive and at least the revision the engine already holds for this generation. A lower one is refused; re-sending the one it holds is an accepted idempotent no-op. Derive it fromclaimLease’s reply (BigInt(lease.quoteRevision) + 1n) rather than starting at"1": a renewal keeps the generation’s existing revision, so"1"merely restates the quote set while the held revision is exactly1, and is refused once it has advanced past that. Only a claim that bumped the generation resets the revision to0
ManagedMarketQuoteStatus — launchId, the acknowledged
generation and quoteRevision, phase, bidNotional, askNotional,
oracleReady, readyToActivate and observedAt.phase on this reply is the runtime phase and takes only "warming",
"live" or "halted" — a narrower set than the launch phase on an
assignment. Anything else the engine reports is answered as 503 with
Managed market status unavailable; reconcile the lease.The refresh places one bounded bid and one bounded ask and costs two items
against your order-creation budget. The engine also enforces the launch’s own
cadence and refuses a refresh that advances the revision less than
refreshIntervalMs after the last one — a rejection, not a silently dropped
no-op — so pace the loop on refreshIntervalMs. Re-sending the revision the
engine already holds is exempt: that equality check runs before the cadence
check, so an idempotent retry succeeds inside the window rather than being
refused.You cannot tell the engine’s refusals apart, and there are two 409 paths.
Before the engine is called at all, the handler re-checks the launch’s
persisted readiness, so a launch already recorded as halted (or otherwise not
quotable) answers 409 Managed market is not ready for maker quotes. Every
refusal that comes back from the engine — a stale revision, an early refresh,
an expired lease, a market the engine has halted since — is folded into a
single 409 Managed market lease changed or expired; reconcile the lease. Both
are 409, so never branch on the message: call claimLease and act on the
generation and quoteRevision it returns.Prices, sizes, fees and the risk bucket are all server-derived — the request
carries no price, quantity or identity to override them.Treat an ambiguous failure as an unknown outcome. On a timeout or a 503
you do not know whether the intent reached the engine, so you do not know which
revision it now holds. Call claimLease and read the engine-observed
quoteRevision back before choosing the next one. Blindly re-sending the same
revision is not itself dangerous — the engine treats an equal revision as a
no-op and refuses a lower one — it simply tells you nothing, and leaves you
advancing from a number you never confirmed.Errors: 400 (launchId / ownerId not a UUID, or
quoteRevision must be positive), 401, 403 (delegated-agent session),
404, 409 (launch not ready to quote, or the lease changed or expired),
429 (the two items this call costs against your order-creation budget — the
engine’s cadence refusal is not a 429; it arrives as the 409 above),
500, 503.See Also
- Managed Markets protobuf reference — the gRPC service and message shapes
- Rate limits — the order-creation budget these calls draw on

