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

# PnL calendar

> GET /v1/wallets/pnl_calendar: realized PnL per UTC day of a verified wallet, grouped by month, with trade counts and win and loss streaks.

Realized PnL per UTC day of a verified wallet of your users, grouped by month, with buy and sell counts, volume, tokens traded and win and loss streaks. It covers the whole history of the wallet.

Use it to render a green and red PnL heatmap on a profile page.

<Tip>
  Months are ordered oldest first. The current month is also returned on its own as month, with its days in dates, so a calendar for this month needs no extra work.
</Tip>

## Query Parameters

<ParamField query="blockchain" type="string" required>
  Chain of the wallet. One of solana, bnb, base, eth, rh.
</ParamField>

<ParamField query="address" type="string" required>
  A wallet verified on this chain by one of your users.
</ParamField>

<ParamField query="scope" default="instance" type="string">
  `global` allows any CabalSpy ID wallet. Enterprise plan only.
</ParamField>

<ParamField query="instance" type="string">
  Your Instance ID. Only needed when your account has several instances.
</ParamField>

<ParamField query="api_key" type="string" required>
  Your API key. Alternatively pass it as an Authorization Bearer header.
</ParamField>

## Usage Example

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api-id.cabalspy.xyz/v1/wallets/pnl_calendar?blockchain=solana&address=7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW" \
    -H "Authorization: Bearer YOUR_KEY"
  ```

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

  params = {"blockchain": "solana", "address": "7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW"}
  r = requests.get("https://api-id.cabalspy.xyz/v1/wallets/pnl_calendar", params=params,
                   headers={"Authorization": "Bearer YOUR_KEY"})
  for m in r.json()["data"]["months"]:
      print(m["year"], m["month"], m["realized_pnl"], "best streak", m["positive_streak"])
  ```

  ```javascript JavaScript theme={null}
  const p = new URLSearchParams({
    blockchain: "solana",
    address: "7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW",
  });
  const res = await fetch(`https://api-id.cabalspy.xyz/v1/wallets/pnl_calendar?${p}`, {
    headers: { Authorization: "Bearer YOUR_KEY" },
  });
  const { data } = await res.json();
  data.dates.forEach(d => console.log(d.date, d.realized_pnl));
  ```
</CodeGroup>

## Response

<ResponseField name="success" type="boolean">
  True on success.
</ResponseField>

<ResponseField name="data" type="object">
  <Expandable title="data">
    <ResponseField name="wallet" type="string">
      The wallet address.
    </ResponseField>

    <ResponseField name="profile" type="object">
      The owner's profile, the same fields as on the [tracker](/cabalspy-id/tracker).
    </ResponseField>

    <ResponseField name="months" type="array">
      <Expandable title="month">
        <ResponseField name="month" type="integer">
          Month, 1 to 12.
        </ResponseField>

        <ResponseField name="year" type="integer">
          Year.
        </ResponseField>

        <ResponseField name="dates" type="array">
          Days with trades in this month, see day below.
        </ResponseField>

        <ResponseField name="realized_pnl" type="number">
          Realized PnL in the month (native).
        </ResponseField>

        <ResponseField name="realized_pnl_usd" type="number">
          Realized PnL in USD.
        </ResponseField>

        <ResponseField name="volume" type="number">
          Buy plus sell volume (native).
        </ResponseField>

        <ResponseField name="total_buy" type="number">
          Bought (native).
        </ResponseField>

        <ResponseField name="total_buy_usd" type="number">
          Bought in USD.
        </ResponseField>

        <ResponseField name="total_sell" type="number">
          Sold (native).
        </ResponseField>

        <ResponseField name="total_sell_usd" type="number">
          Sold in USD.
        </ResponseField>

        <ResponseField name="buy_txn" type="integer">
          Buys.
        </ResponseField>

        <ResponseField name="sell_txn" type="integer">
          Sells.
        </ResponseField>

        <ResponseField name="txn_total" type="integer">
          All trades.
        </ResponseField>

        <ResponseField name="tokens_traded" type="integer">
          Distinct tokens traded in the month.
        </ResponseField>

        <ResponseField name="positive_streak" type="integer">
          Longest run of consecutive trading days in profit.
        </ResponseField>

        <ResponseField name="negative_streak" type="integer">
          Longest run of consecutive trading days at a loss.
        </ResponseField>

        <ResponseField name="current_positive_streak" type="integer">
          Current month only: the running profit streak.
        </ResponseField>

        <ResponseField name="current_negative_streak" type="integer">
          Current month only: the running loss streak.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="dates" type="array">
      <Expandable title="day">
        <ResponseField name="date" type="string">
          UTC day as dd-mm-yy.
        </ResponseField>

        <ResponseField name="realized_pnl" type="number">
          Realized PnL of the day (native), sells minus buys.
        </ResponseField>

        <ResponseField name="realized_pnl_usd" type="number">
          Realized PnL in USD.
        </ResponseField>

        <ResponseField name="buy_txn" type="integer">
          Buys.
        </ResponseField>

        <ResponseField name="sell_txn" type="integer">
          Sells.
        </ResponseField>

        <ResponseField name="txn_total" type="integer">
          All trades.
        </ResponseField>

        <ResponseField name="tokens_traded" type="integer">
          Distinct tokens traded.
        </ResponseField>

        <ResponseField name="volume" type="number">
          Buy plus sell volume (native).
        </ResponseField>

        <ResponseField name="total_buy" type="number">
          Bought (native).
        </ResponseField>

        <ResponseField name="total_sell" type="number">
          Sold (native).
        </ResponseField>

        <ResponseField name="total_buy_usd" type="number">
          Bought in USD.
        </ResponseField>

        <ResponseField name="total_sell_usd" type="number">
          Sold in USD.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="month" type="object">
      The current month, the same shape as an entry of months, or null when the wallet has no trades this month.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseExample>
  ```json Response theme={null}
  {
    "success": true,
    "data": {
      "wallet": "7j7AA3HZR2zEjwAQEKPFh2qucLY4fqZpB9iodf39w8xW",
      "profile": {
        "csid_id": "0b7c4a52-3f1e-4f43-9d0a-2b5e7c1d9a11",
        "username": "MazeCCC",
        "name": "Maze",
        "image_url": "https://pbs.twimg.com/profile_images/.../photo.jpg",
        "twitter": "https://x.com/MazeCCC",
        "telegram": "",
        "blockchain": "solana",
        "currency": "SOL",
        "type": "csid",
        "kol": true,
        "active_hours": "",
        "profile_url": "https://id.cabalspy.xyz/u/MazeCCC"
      },
      "months": [
        {
          "month": 10,
          "year": 2026,
          "dates": [
            {
              "date": "12-10-26",
              "realized_pnl": 4.12,
              "realized_pnl_usd": 339.21,
              "buy_txn": 6,
              "sell_txn": 5,
              "txn_total": 11,
              "tokens_traded": 4,
              "volume": 30.5,
              "total_buy": 13.19,
              "total_sell": 17.31,
              "total_buy_usd": 1086.1,
              "total_sell_usd": 1425.31
            }
          ],
          "realized_pnl": 4.12,
          "realized_pnl_usd": 339.21,
          "volume": 30.5,
          "total_buy": 13.19,
          "total_buy_usd": 1086.1,
          "total_sell": 17.31,
          "total_sell_usd": 1425.31,
          "buy_txn": 6,
          "sell_txn": 5,
          "txn_total": 11,
          "tokens_traded": 4,
          "positive_streak": 1,
          "negative_streak": 0,
          "current_positive_streak": 1,
          "current_negative_streak": 0
        }
      ],
      "dates": [
        {
          "date": "12-10-26",
          "realized_pnl": 4.12,
          "realized_pnl_usd": 339.21,
          "buy_txn": 6,
          "sell_txn": 5,
          "txn_total": 11,
          "tokens_traded": 4,
          "volume": 30.5,
          "total_buy": 13.19,
          "total_sell": 17.31,
          "total_buy_usd": 1086.1,
          "total_sell_usd": 1425.31
        }
      ],
      "month": { "month": 10, "year": 2026, "...": "same as months[-1]" }
    },
    "meta": {
      "request_id": "req_5162c7cf7f87",
      "cached": false,
      "cache_age_seconds": 0,
      "version": "v1",
      "timestamp": "2026-10-13T08:04:11Z"
    }
  }
  ```
</ResponseExample>

## Errors

| Status | Code | Meaning |
| - | - | - |
| 400 | missing\_parameter | blockchain or address is missing. |
| 400 | invalid\_parameter | blockchain or address invalid. |
| 401 | missing\_api\_key | API key missing. |
| 403 | invalid\_api\_key | API key invalid or not enabled for CabalSpy ID. |
| 403 | scope\_not\_allowed | scope=global needs the Enterprise plan. |
| 404 | wallet\_not\_found | The wallet is not verified on this chain by one of your users. |
| 429 | rate\_limit\_exceeded | Rate limit exceeded. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.