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

# Closed Hedge History

> Returns your closed hedges, newest first, with realized P&L, carry, and fees. Each record covers the full open-to-close lifecycle: entry and exit price, gross and net realized P&L, carry, and fees.



## OpenAPI

````yaml /api-reference/openapi.json get /hedges/history
openapi: 3.1.0
info:
  title: Marks Partner API
  version: v2
  description: >
    Marks is an FX hedging platform. This API lets you open and manage hedges
    programmatically, currently on USDT/NGN, with more pairs to follow.


    Each hedge is a non-deliverable forward (NDF): a contract that fixes an
    exchange rate for a chosen tenor and cash-settles the difference at
    maturity, with no physical delivery of currency. A hedge opens at the
    prevailing spot rate, accrues carry over its tenor, and settles in USDC.


    The API is organized around four areas:


    - **Market data** - available markets, prices, capacity, and the current
    carry rate.

    - **Account** - your balance, margin, exposure, and unrealized P&L.

    - **Quotes** - an indicative price and cost breakdown for a hedge before you
    open it.

    - **Hedges** - open, monitor, close, and review hedges.


    Every response uses the same envelope: `{ "data", "error", "meta" }`. On
    success `data` is populated and `error` is null; on failure `data` is null
    and `error` carries a machine-readable `code`, a `message`, and optional
    `details`. Amounts are in USDC unless noted.
servers:
  - url: https://api.marks.finance/api/v2/partners
    description: Base URL (mode is selected by the API key prefix / X-Marks-Mode header)
security:
  - ApiKey: []
tags:
  - name: Authentication
    description: >
      Every request authenticates with your API key, sent as a Bearer token:


      ```

      Authorization: Bearer mk_live_xxxxxxxx

      ```


      Create and manage keys in Settings. The full key is shown only once at
      creation and cannot be retrieved later, so save it somewhere secure and
      keep it secret. A request without a valid key returns `401`.


      Your key prefix selects the environment:


      - `mk_live_` - production

      - `mk_test_` - sandbox


      The prefix is authoritative: a `mk_test_` key always runs against the
      sandbox, so a test call can never reach production by accident. The same
      endpoints serve both; only the key differs.
  - name: Sandbox
    description: >
      The sandbox is a full copy of the API running against test infrastructure,
      so code that works in the sandbox works in production unchanged. Use it to
      build and verify your integration before going live.


      Create a `mk_test_` key in Settings and send it as your Bearer token.
      Sandbox accounts are funded with test balances, so you can open and settle
      hedges end to end without real money.


      Sandbox and production are fully isolated, with separate balances,
      positions, and history. A test key cannot see or touch production data.


      Prices in the sandbox track the same live FX rates as production. Fees in
      the sandbox are indicative and may differ from production.


      In the reference below, **Test Request** calls the API live with the key
      you provide. With a `mk_test_` key this is safe to experiment with freely.
      With a `mk_live_` key the calls are real, and opening a hedge places a
      real position.
  - name: Errors
    description: >
      Every error response has `data: null` and a populated `error` with a
      stable `code`, a human-readable `message`, and optional `details`. Branch
      on `code`.


      | Code | HTTP | Meaning |

      |---|---|---|

      | `validation_error` | 400 | Malformed or missing fields (see
      `details.fields`) |

      | `market_not_allowed` | 400 | Market not enabled for your account |

      | `exposure_exceeded` | 400 | Total open exposure would exceed your cap
      (see `details.available_headroom_usd`) |

      | `insufficient_collateral` | 400 | Not enough balance for the requested
      size |

      | `hedge_not_open` | 400 | The target hedge is not open, so it can't be
      added to |

      | `account_not_configured` | 400 | Your partner account has no on-chain
      account set yet |

      | `missing_credentials` | 401 | No `Authorization` header |

      | `invalid_api_key` | 401 | API key not found or revoked |

      | `insufficient_scope` | 403 | API key lacks the required scope |

      | `account_forbidden` | 403 | The requested account is not yours |

      | `hedge_not_found` | 404 | No hedge with that id on your account |

      | `no_open_hedge` | 404 | No open hedge on that market + side to add to
      (open one instead) |

      | `hedge_exists` | 409 | You already have an open hedge on that market +
      side; add to it or settle it first |

      | `idempotency_in_flight` | 409 | A request with this `Idempotency-Key` is
      still processing |

      | `idempotency_key_reuse` | 409 | `Idempotency-Key` reused with a
      different request body |

      | `rate_limited` | 429 | Too many requests |

      | `quote_failed` | 502 | Could not build a quote |

      | `execution_failed` | 502 | The order could not be submitted |

      | `onchain_read_failed` | 502 | Could not read market or account data |

      | `price_unavailable` | 503 | Price feed temporarily unavailable |

      | `executor_unavailable` | 503 | Execution service temporarily unavailable
      |

      | `service_unavailable` | 503 | A required service is temporarily
      unavailable |


      5xx errors are transient; retry with backoff.
  - name: Market data
    description: >
      Read-only market data to size and price hedges before opening them.


      - `GET /markets` lists the markets available to you, with each market's
      status, current rate, available capacity per side, and daily carry rate.

      - `GET /prices` returns the latest mid rate for a market.


      Prices here are indicative mid rates for reference. The executable price
      for a hedge, with impact applied, comes from a quote.
  - name: Account
    description: >
      Your account: balances, margin, exposure, and open positions.


      - `GET /account` returns a summary - free balance, margin in use, total
      exposure, and unrealized P&L.

      - `GET /positions` returns each open position with its entry, mark price,
      gross and net P&L, accrued carry, and net margin.


      Amounts are in USDC.
  - name: Quotes
    description: >-
      Price a hedge before you open it. Quotes are indicative: they are not
      binding and not persisted, and opening a hedge re-prices against the live
      rate.
  - name: Hedges
    description: >
      Open, close, list, and review hedges.


      ## Lifecycle


      Opening and closing are asynchronous: you submit an order and it's filled
      shortly after, so you poll for the result. There are no webhooks yet.


      1. **Quote** (optional) - `POST /quotes` returns an indicative price and
      full cost breakdown. Quotes are not binding and not persisted; opening
      re-prices against the live rate.

      2. **Open** - `POST /hedges` returns `status: "submitted"` with an
      `order_tx_hash` and a `hedge_id`. The position is not live yet.

      3. **Fill** - poll `GET /hedges/{id}` until `status` is `filled` (with a
      `fill_tx_hash`). This usually takes a few seconds.

      4. **Monitor** - `GET /positions` shows the live position (mark price,
      gross and net P&L, accrued carry). `GET /account` shows aggregate balance,
      margin, exposure, and unrealized P&L.

      5. **Close** - `POST /hedges/close` closes a (market, side); it fills the
      same asynchronous way, and `GET /positions` returns to flat once drained.

      6. **Review** - `GET /hedges/history` lists closed hedges with realized
      P&L, carry, and fees.


      Each hedge carries a `maturity_at`, its settlement date derived from the
      tenor. Status values: `submitting`, `submitted`, `filled`, `failed`,
      `closed`.


      **One open hedge per market + side.** You hold at most one open hedge on a
      given market and side. Opening a second on the same market+side returns
      `409 hedge_exists`. To grow a position, add to the existing hedge with
      `POST /hedges/{id}/add` (or `POST /hedges/add` by market + side): the
      added notional nets into the same position at a size-weighted blended rate
      and inherits the original `maturity_at`. To change the maturity, settle
      the current hedge and open a new one.


      ## Idempotency


      Opening and closing are state-changing, so make them safe to retry with an
      `Idempotency-Key` header (any unique string, such as a UUID or your own
      deal id):


      ```

      Idempotency-Key: 9f1c2e7a-...

      ```


      Retrying with the same key and the same body returns the original result
      instead of acting twice. Reusing a key with a different body returns `409
      idempotency_key_reuse`. A key whose request is still in flight returns
      `409 idempotency_in_flight`. Keys are scoped per environment, so sandbox
      and production never collide.
paths:
  /hedges/history:
    get:
      tags:
        - Hedges
      summary: Closed Hedge History
      description: >-
        Returns your closed hedges, newest first, with realized P&L, carry, and
        fees. Each record covers the full open-to-close lifecycle: entry and
        exit price, gross and net realized P&L, carry, and fees.
      operationId: hedge_history_api_v2_partners_hedges_history_get
      parameters:
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 100
            title: Limit
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_List_HistoryItem__'
              example:
                data:
                  - market: USDTNGN
                    side: sell
                    size_usd: 100000
                    collateral_usdc: 5000
                    entry_price: 1619.8
                    exit_price: 1631.2
                    opened_at: '2026-08-08T12:00:00Z'
                    closed_at: '2026-08-15T00:00:00Z'
                    exit_type: closed
                    gross_pnl_usd: 703
                    net_pnl_usd: 273
                    carry_usd: -350
                    fees_usd: 80
                error: null
                meta: {}
        '401':
          description: missing_credentials, invalid_api_key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: insufficient_scope
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: rate_limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: service_unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    Envelope_List_HistoryItem__:
      properties:
        data:
          anyOf:
            - items:
                $ref: '#/components/schemas/HistoryItem'
              type: array
            - type: 'null'
          title: Data
        error:
          anyOf:
            - $ref: '#/components/schemas/ErrorObject'
            - type: 'null'
        meta:
          additionalProperties: true
          type: object
          title: Meta
      type: object
      title: Envelope[List[HistoryItem]]
    ErrorResponse:
      type: object
      properties:
        data:
          type: 'null'
        error:
          $ref: '#/components/schemas/ErrorObject'
        meta:
          type: object
      required:
        - data
        - error
        - meta
    HistoryItem:
      properties:
        market:
          type: string
          title: Market
        side:
          type: string
          title: Side
        size_usd:
          type: number
          title: Size Usd
        collateral_usdc:
          type: number
          title: Collateral Usdc
        entry_price:
          type: number
          title: Entry Price
        exit_price:
          anyOf:
            - type: number
            - type: 'null'
          title: Exit Price
        opened_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Opened At
        closed_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Closed At
        exit_type:
          anyOf:
            - type: string
            - type: 'null'
          title: Exit Type
          description: closed | liquidated | take_profit | stop_loss | partial_close.
        gross_pnl_usd:
          type: number
          title: Gross Pnl Usd
          description: Realized price P&L, before carry/fees.
        net_pnl_usd:
          type: number
          title: Net Pnl Usd
          description: Realized P&L net of carry and fees.
        carry_usd:
          type: number
          title: Carry Usd
          description: Net carry over the hold, signed (+ earned / − paid).
        fees_usd:
          type: number
          title: Fees Usd
          description: Total fees paid.
      type: object
      required:
        - market
        - side
        - size_usd
        - collateral_usdc
        - entry_price
        - gross_pnl_usd
        - net_pnl_usd
        - carry_usd
        - fees_usd
      title: HistoryItem
    ErrorObject:
      properties:
        code:
          type: string
          title: Code
          description: Machine-readable error code, e.g. exposure_exceeded.
        message:
          type: string
          title: Message
          description: Human-readable explanation.
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Details
          description: Optional structured context (e.g. field errors, limits).
      type: object
      required:
        - code
        - message
      title: ErrorObject
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: 'Partner API key: `mk_live_...` (production) or `mk_test_...` (sandbox).'

````