Skip to main content
Perpetuals let you take a leveraged position on a market’s price without an expiry. On Murmo they live as proposals inside a group: a proposal is a single LONG or SHORT idea on a Phoenix RISE perp market, and each member who joins runs their own position under it. You put up USD collateral, pick a multiplier, and the position tracks the market with live mark price, unrealized PnL, and funding.
Leverage cuts both ways. At , a −20% move in the underlying wipes out your collateral and the position can be liquidated — you lose what you put in. Size positions you can afford to lose, and watch liquidationPriceUsd.
Perpetuals are restricted in some jurisdictions and may require identity verification. If a call returns 403, see Eligibility & geo restrictions.

Two IDs: proposalId vs assignmentId

This is the one thing to get straight before you start. Perp routes are keyed by one of two IDs, and they are not interchangeable.
CREATE, JOIN, and CLOSE-proposal are keyed by proposalId. REDUCE and CLAIM act on a single position and are keyed by assignmentId. A PerpPosition.id and its assignment id are the same value — use it wherever a route says {assignmentId}.

Setup

Same base URL, key, and money rules as everywhere else in the API.
Every monetary value on the wire is a full-precision decimal string in USD. collateralUsd and leverage are sent as numeric strings ("25.00", "5") — never numbers, never raw base units. Base-lot quantities are strings too. See Money & precision.

Lifecycle

1

Pick a market

List the tradable perp markets and read a live price to size your entry. GET /api/v1/perps/markets (or /markets/{symbol} for one).
2

Open a position

POST /api/v1/perps/proposals creates a proposal and opens your position in one call — pick side, collateralUsd, leverage, and optional stopLossPct / takeProfitPct brackets. To back an idea someone else posted, POST /perps/proposals/{id}/increase instead.
3

Monitor PnL

GET /api/v1/perps/positions?filter=active returns your open positions with live markPrice-derived value, unrealizedPnlUsd, funding, and liquidationPriceUsd. For low-latency price ticks, subscribe to market data over WebSocket.
4

Reduce or close

POST /api/v1/perps/positions/{assignmentId}/reduce trims or fully closes your position (reduceFraction in (0, 1], isFullClose). The proposal creator can close the whole proposal with POST /perps/proposals/{id}/close.
5

Claim a take-profit close

If a takeProfitPct bracket fired, the position closes automatically and becomes claimable. POST /api/v1/perps/positions/{assignmentId}/claim acknowledges it and drains the proceeds to your wallet.

Browse markets

GET /api/v1/perps/markets returns every tradable perp market; GET /api/v1/perps/markets/{symbol} returns one (and data: null if the symbol is unknown).
Response
PerpAsset (selected fields):
The market_tick WebSocket stream sends these prices as numbers, not decimal strings, for speed. For exact money math (entry sizing, accounting) read prices from GET /perps/markets. See Market data.

See proposals in a group

A proposal is a shared LONG/SHORT idea. Reads are members only — you’ll get 403 NOT_GROUP_MEMBER for a group you don’t belong to. GET /api/v1/perps/proposals?groupId=... lists a group’s perp proposals; GET /api/v1/perps/proposals/{id} returns one (data: null if not found).
Response
PerpProposal (selected fields):

Open a position (new proposal)

POST /api/v1/perps/proposals creates the proposal and opens your position atomically. The wallet is resolved for you — you never pass one.
side must be exactly "LONG" or "SHORT". Anything else is rejected with 400 — the API never silently coerces a bad value, which would otherwise open a reversed position.
Response
This is a PerpPositionResult. On an open (or increase) the close-side fields are null; they’re populated only when a reduce fully closes the position.

Stop-loss and take-profit brackets

stopLossPct and takeProfitPct are optional and expressed as % collateral ROI (account P&L), not as a price move in the underlying.
takeProfitPct: "100" means “close when the position is up 100% of collateral” — i.e. you’d roughly double your stake. stopLossPct: "50" means “close when down 50% of collateral.” Because ROI is on collateral, these scale with leverage: at higher leverage a smaller price move hits the same ROI bracket. The corresponding trigger prices come back on the position as stopLossPriceUsd and takeProfitPriceUsd.

Join a proposal (increase)

To back an idea that already exists, POST /api/v1/perps/proposals/{id}/increase opens a new position under that proposal. The side is inherited from the proposal — you only send your own collateralUsd and leverage. You must be a member of the proposal’s group.
The response is a PerpPositionResult with your new assignmentId (same shape as opening above).
{id} here is the proposalId. This is the only join path on REST — a position’s own assignmentId is for /reduce and /claim, not for joining.

Monitor your positions

GET /api/v1/perps/positions?filter=active returns your positions, with live mark/PnL/funding fields plus realized fields once closed. filter is active (default), past, or all.
Response
PerpPosition (selected fields): When closed, the realized fields populate: priceRealizedPnlUsd, fundingRealizedUsd, totalFeesUsd, liquidationPenaltyUsd, netRealizedPnlUsd, and finalCollateralReturned — all MoneyString. Use filter=past or filter=all to see them.
currentSizeBaseLots / currentSizeBaseUnits are quantities, not USD. Everything ending in ...Usd (and prices/PnL/percent) is a human decimal string. See Money & precision → Raw vs. human quantities.

Reduce or close your position

POST /api/v1/perps/positions/{assignmentId}/reduce trims or fully closes your position. It’s keyed by assignmentId (the position’s id).
Response (full close)
The response is a PerpPositionResult (table above). On a full close, closePnlUsd, closePnlPct, closeProceedsUsd, and closedBaseUnits are populated.
reduceFraction must be in (0, 1] — a value > 1, 0, or non-numeric is rejected with 400, as is a missing isFullClose. To close everything, send reduceFraction: "1" with isFullClose: true.

Close the whole proposal (creator only)

POST /api/v1/perps/proposals/{id}/close closes the proposal, keyed by proposalId. Only the creator can do this (enforced); it closes the creator’s own open position(s) and locks out new joiners. Other members’ positions are left untouched — they manage their own exits via /reduce.
Response
If you’re not the creator, this returns 403. To exit a position you joined, use /positions/{assignmentId}/reduce instead.

Claim a take-profit close

When a takeProfitPct bracket fires, the position closes automatically and becomes claimable (isClaimable: true). POST /api/v1/perps/positions/{assignmentId}/claim acknowledges that close and drains the proceeds to your wallet. It’s keyed by assignmentId.
Response
PerpClaimResult:
Claim is only for take-profit-triggered closes. Positions you close yourself via /reduce return proceeds directly in that call — there’s nothing to claim.

Errors you’ll hit

See Errors for the full status-code and code reference and a retry pattern.

Next

Perps bot

Open, monitor, and close a position in one script.

Money & precision

Why collateralUsd is "25.00" and not 25.

Groups & proposals

The social model: groups, proposals, positions.

Market data (WebSocket)

Live per-symbol perp ticks for low-latency monitoring.

API Reference

Every Perpetuals endpoint, field by field.