Skip to main content
POST
/
2
/
pm
/
redeem
/
build
Build position redemption transaction
curl --request POST \
  --url https://demo-api.mobula.io/api/2/pm/redeem/build \
  --header 'Content-Type: application/json' \
  --data '
{
  "address": "<string>",
  "conditionId": "<string>",
  "indexSets": [
    123
  ],
  "isNegRisk": false
}
'
{
  "data": {
    "to": "<string>",
    "calldata": "<string>",
    "chainId": 123,
    "safeAddress": "<string>"
  },
  "hostname": "<string>",
  "took": 123
}

Request Body

address
string
required
The wallet address (EOA). The Safe address is derived automatically.
conditionId
string
required
The condition ID of the market (same as marketId from market details).
indexSets
array
required
Array of index sets to redeem. For binary markets, use [1, 2] (Yes=1, No=2).
isNegRisk
boolean
default:false
Set to true for neg-risk (multi-outcome) markets. This routes the redemption through the NegRiskAdapter contract instead of ConditionalTokens directly.

Response

data
object
Transaction calldata for the redemption.
hostname
string
Server node identifier.
took
number
Request processing time in milliseconds.

How Redemption Works

For standard markets (isNegRisk: false):
  • Calls ConditionalTokens.redeemPositions(USDC, 0x0, conditionId, indexSets) through the Safe.
  • Burns outcome tokens and returns USDC to the Safe for winning positions.
For neg-risk markets (isNegRisk: true):
  • Calls NegRiskAdapter.redeemPositions(conditionId, indexSets) through the Safe.

Usage Example

curl -X POST "https://api.mobula.io/api/2/pm/redeem/build" \
  -H "Content-Type: application/json" \
  -d '{
    "address": "0xYourWalletAddress",
    "conditionId": "0x5a300c31e036a97a7a14aa248f5fb0d39c02a06803a910643f1ab2edc22fa99f",
    "indexSets": [1, 2],
    "isNegRisk": false
  }'

Integration Example

// Build the redeem transaction
const res = await fetch('https://api.mobula.io/api/2/pm/redeem/build', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    address: walletAddress,
    conditionId: market.marketId,
    indexSets: [1, 2],
    isNegRisk: market.negRisk
  })
});
const { data: redeemTx } = await res.json();

// Send the transaction on-chain (Polygon)
const txHash = await walletClient.sendTransaction({
  to: redeemTx.to,
  data: redeemTx.calldata,
  chain: polygon
});
Redemption is only possible after a market has been resolved. The transaction is wrapped in a Safe execTransaction call because the outcome tokens are held by the Safe, not the EOA directly. The EOA (as Safe owner) can authorize this call using a pre-approved sender signature.

Body

application/json
address
string
required
conditionId
string
required
indexSets
number[]
required
isNegRisk
boolean
default:false

Response

200 - application/json

Redeem transaction

data
object
hostname
string
took
number