> ## Documentation Index
> Fetch the complete documentation index at: https://docs.murmo.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Perps bot

> A complete perpetuals flow: open a leveraged position with a take-profit, watch live PnL, then close.

A full, runnable perps bot. It opens a leveraged BTC long with a take-profit bracket, reads live PnL,
and closes the position. Collateral is **USDC**, and closing settles back to USDC.

**Before you run it:** create an API key and fund your wallet with USDC ([Quickstart](/quickstart)).
Perpetuals are restricted in some regions and may require identity verification; a blocked call
returns `403` (see [Eligibility & geo restrictions](/concepts/geo-restrictions)).

<Warning>
  Leverage can liquidate your collateral on an adverse move. Size positions you can afford to lose and
  watch `liquidationPriceUsd`.
</Warning>

```bash theme={null}
export MURMO_API_KEY="murmo_your_key_here"
export MURMO_BASE="https://api.alpha-labs.trade"
```

## The whole flow

<CodeGroup>
  ```javascript Node 18+ theme={null}
  const BASE = process.env.MURMO_BASE;
  const KEY = process.env.MURMO_API_KEY;
  const headers = { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" };

  async function api(method, path, body) {
    const res = await fetch(`${BASE}/api/v1${path}`, {
      method,
      headers,
      body: body ? JSON.stringify(body) : undefined,
    });
    const json = await res.json();
    if (!res.ok) throw new Error(`${path} -> ${res.status} ${json.code ?? ""} ${json.message ?? ""}`);
    return json.data;
  }

  // 1. A group to open the idea in.
  const { groupId } = await api("POST", "/groups", {
    name: "Perps bot",
    joiningFee: "0",
    groupAccessType: "PRIVATE",
  });

  // 2. Read the market to size your entry.
  const market = await api("GET", "/perps/markets/BTC");
  console.log("BTC mark:", market.markPriceUsd);

  // 3. Open: $25 USDC collateral at 5x, take profit at +100% of collateral.
  const opened = await api("POST", "/perps/proposals", {
    groupId,
    marketSymbol: "BTC",
    side: "LONG",
    collateralUsd: "25.00",
    leverage: "5",
    takeProfitPct: "100",
    reason: "Bullish",
  });
  const assignmentId = opened.assignmentId; // your position id

  // 4. Check live PnL.
  const positions = await api("GET", "/perps/positions?filter=active");
  const live = positions.find((p) => p.id === assignmentId);
  console.log("PnL (USDC):", live?.unrealizedPnlUsd, "liq:", live?.liquidationPriceUsd);

  // 5. Close it fully (settles proceeds back to USDC).
  const closed = await api("POST", `/perps/positions/${assignmentId}/reduce`, {
    reduceFraction: "1",
    isFullClose: true,
  });
  console.log("close pnl:", closed.closePnlUsd, "proceeds (USDC):", closed.closeProceedsUsd);
  ```

  ```python Python theme={null}
  import os, requests

  BASE = os.environ["MURMO_BASE"]
  KEY = os.environ["MURMO_API_KEY"]
  HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}

  def api(method, path, body=None):
      res = requests.request(method, f"{BASE}/api/v1{path}", headers=HEADERS, json=body)
      data = res.json()
      if not res.ok:
          raise RuntimeError(f"{path} -> {res.status_code} {data.get('code','')} {data.get('message','')}")
      return data["data"]

  # 1. A group to open the idea in.
  group = api("POST", "/groups", {
      "name": "Perps bot",
      "joiningFee": "0",
      "groupAccessType": "PRIVATE",
  })
  group_id = group["groupId"]

  # 2. Read the market.
  market = api("GET", "/perps/markets/BTC")
  print("BTC mark:", market["markPriceUsd"])

  # 3. Open: $25 USDC at 5x, take profit at +100% of collateral.
  opened = api("POST", "/perps/proposals", {
      "groupId": group_id,
      "marketSymbol": "BTC",
      "side": "LONG",
      "collateralUsd": "25.00",
      "leverage": "5",
      "takeProfitPct": "100",
      "reason": "Bullish",
  })
  assignment_id = opened["assignmentId"]

  # 4. Check live PnL.
  positions = api("GET", "/perps/positions?filter=active")
  live = next((p for p in positions if p["id"] == assignment_id), None)
  print("PnL (USDC):", live and live["unrealizedPnlUsd"], "liq:", live and live["liquidationPriceUsd"])

  # 5. Close it fully.
  closed = api("POST", f"/perps/positions/{assignment_id}/reduce", {
      "reduceFraction": "1",
      "isFullClose": True,
  })
  print("close pnl:", closed["closePnlUsd"], "proceeds (USDC):", closed["closeProceedsUsd"])
  ```
</CodeGroup>

## Step by step

1. **Create a group** (`POST /groups`) to open the idea in.
2. **Pick a market** (`GET /perps/markets/{symbol}`) and read `markPriceUsd` to size your entry.
3. **Open a position** (`POST /perps/proposals`) with `side`, `collateralUsd`, `leverage`, and an
   optional `takeProfitPct` / `stopLossPct` bracket (expressed as **% of collateral ROI**). You get
   back your **`assignmentId`** — your position's id.
4. **Monitor** (`GET /perps/positions?filter=active`) for live `unrealizedPnlUsd`,
   `liquidationPriceUsd`, and funding. For low-latency prices, use
   [market data over WebSocket](/websockets/market-data).
5. **Close** (`POST /perps/positions/{assignmentId}/reduce`) with `reduceFraction: "1"` and
   `isFullClose: true`. Proceeds settle back to your wallet in USDC.

<Note>
  If your `takeProfitPct` bracket fires before you close, the position closes automatically and becomes
  **claimable**. In that case skip `/reduce` and call
  `POST /perps/positions/{assignmentId}/claim` to drain the proceeds. See the
  [Perpetuals guide](/guides/perpetuals).
</Note>
