> ## 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.

# Open a Hedge

> Opens a hedge for the given market, side, size, and tenor. Returns immediately with status `submitted`, an `order_tx_hash`, and a `hedge_id`; it's filled shortly after, so poll `GET /hedges/{id}` for the fill. Pass a unique `Idempotency-Key` to make retries safe, and (for API keys) a `client_reference` to tag the hedge with your own id.

Restriction: **one open hedge per market + side per account.** If you already have an open hedge on that market and side, this returns `409 hedge_exists` - use `POST /hedges/{id}/add` to increase it (keeps the original maturity), or settle it first. A different maturity on the same market+side requires settling the current hedge first.



## OpenAPI

````yaml /api-reference/openapi.json post /hedges
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:
    post:
      tags:
        - Hedges
      summary: Open a Hedge
      description: >-
        Opens a hedge for the given market, side, size, and tenor. Returns
        immediately with status `submitted`, an `order_tx_hash`, and a
        `hedge_id`; it's filled shortly after, so poll `GET /hedges/{id}` for
        the fill. Pass a unique `Idempotency-Key` to make retries safe, and (for
        API keys) a `client_reference` to tag the hedge with your own id.


        Restriction: **one open hedge per market + side per account.** If you
        already have an open hedge on that market and side, this returns `409
        hedge_exists` - use `POST /hedges/{id}/add` to increase it (keeps the
        original maturity), or settle it first. A different maturity on the same
        market+side requires settling the current hedge first.
      operationId: open_hedge_api_v2_partners_hedges_post
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OpenHedgeRequest'
            example:
              market: USDTNGN
              side: sell
              notional_usd: 100000
              tenor_days: 7
              client_reference: deal-4821
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Envelope_HedgeOpenResult_'
              example:
                data:
                  status: submitted
                  order_tx_hash: >-
                    0x9c1e4f2a7b8d3e6c5a0f1b2d4e6a8c0f2b4d6e8a1c3f5b7d9e0a2c4f6b8d0e2a
                  hedge_id: hdg_3f9a2c7e5b1d
                  client_reference: deal-4821
                  collateral_usdc: 5080
                  maturity_at: '2026-08-15T00:00:00Z'
                  quote:
                    market: USDTNGN
                    side: sell
                    notional_usd: 100000
                    tenor_days: 7
                    maturity: '2026-08-15T00:00:00Z'
                    pricing:
                      market_price: 1620.5
                      execution_price: 1619.8
                      price_impact_usd: -43.2
                    carry:
                      daily_usdc: 50
                      daily_rate_pct: 0.05
                      total_usdc: 350
                      total_rate_pct: 0.35
                    upfront:
                      required_margin_usdc: 5000
                      platform_fee_usdc: 80
                      total_upfront_usdc: 5080
                error: null
                meta: {}
        '400':
          description: >-
            validation_error, market_not_allowed, exposure_exceeded,
            insufficient_collateral, account_not_configured
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: missing_credentials, invalid_api_key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: insufficient_scope, account_forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: hedge_exists, idempotency_in_flight, idempotency_key_reuse
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: rate_limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: execution_failed, quote_failed, onchain_read_failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: price_unavailable, executor_unavailable
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    OpenHedgeRequest:
      properties:
        market:
          type: string
          title: Market
          description: e.g. USDTNGN
        side:
          type: string
          title: Side
          description: buy | sell
        notional_usd:
          type: number
          exclusiveMinimum: 0
          title: Notional Usd
        tenor_days:
          type: integer
          enum:
            - 1
            - 3
            - 7
          title: Tenor Days
          description: 'Settlement tenor in days. Allowed: 1, 3, or 7.'
        client_reference:
          anyOf:
            - type: string
            - type: 'null'
          title: Client Reference
          description: >-
            Your own deal id, echoed back on reads. Required for API-key
            (server) callers.
      type: object
      required:
        - market
        - side
        - notional_usd
        - tenor_days
      title: OpenHedgeRequest
    Envelope_HedgeOpenResult_:
      properties:
        data:
          anyOf:
            - $ref: '#/components/schemas/HedgeOpenResult'
            - type: 'null'
        error:
          anyOf:
            - $ref: '#/components/schemas/ErrorObject'
            - type: 'null'
        meta:
          additionalProperties: true
          type: object
          title: Meta
      type: object
      title: Envelope[HedgeOpenResult]
    ErrorResponse:
      type: object
      properties:
        data:
          type: 'null'
        error:
          $ref: '#/components/schemas/ErrorObject'
        meta:
          type: object
      required:
        - data
        - error
        - meta
    HedgeOpenResult:
      properties:
        status:
          type: string
          title: Status
          description: >-
            `submitted` - the hedge is filled shortly after; poll GET
            /hedges/{id}.
        order_tx_hash:
          anyOf:
            - type: string
            - type: 'null'
          title: Order Tx Hash
          description: The create-order transaction. The fill lands later as fill_tx_hash.
        hedge_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Hedge Id
          description: Identifier to poll / reconcile this hedge.
        client_reference:
          anyOf:
            - type: string
            - type: 'null'
          title: Client Reference
          description: Your own deal id, echoed back.
        collateral_usdc:
          type: number
          title: Collateral Usdc
          description: Total locked at open (margin + platform fee).
        maturity_at:
          anyOf:
            - type: string
            - type: 'null'
          title: Maturity At
          description: Settlement date (ISO-8601).
        quote:
          $ref: '#/components/schemas/Quote'
          description: 'Agreed terms at open (pre-fill): pricing, carry, upfront.'
      type: object
      required:
        - status
        - collateral_usdc
        - quote
      title: HedgeOpenResult
    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
    Quote:
      properties:
        market:
          type: string
          title: Market
        side:
          type: string
          title: Side
        notional_usd:
          type: number
          title: Notional Usd
        tenor_days:
          type: integer
          title: Tenor Days
        maturity:
          type: string
          title: Maturity
          description: Settlement date (ISO-8601).
        pricing:
          $ref: '#/components/schemas/QuotePricing'
        carry:
          $ref: '#/components/schemas/QuoteCarry'
        upfront:
          $ref: '#/components/schemas/QuoteUpfront'
      type: object
      required:
        - market
        - side
        - notional_usd
        - tenor_days
        - maturity
        - pricing
        - carry
        - upfront
      title: Quote
    QuotePricing:
      properties:
        market_price:
          type: number
          title: Market Price
          description: Indicative mid rate.
        execution_price:
          type: number
          title: Execution Price
          description: Price including impact (what the hedge would open at).
        price_impact_usd:
          type: number
          title: Price Impact Usd
          description: Price-impact cost, signed (− = cost to you).
      type: object
      required:
        - market_price
        - execution_price
        - price_impact_usd
      title: QuotePricing
    QuoteCarry:
      properties:
        daily_usdc:
          type: number
          title: Daily Usdc
          description: Net daily carry in USDC at the quoted rate, signed (+ = you pay).
        daily_rate_pct:
          type: number
          title: Daily Rate Pct
          description: Net daily carry as % of notional, signed.
        total_usdc:
          type: number
          title: Total Usdc
          description: Carry over the full tenor (daily × tenor_days).
        total_rate_pct:
          type: number
          title: Total Rate Pct
          description: Carry over the tenor as % of notional.
      type: object
      required:
        - daily_usdc
        - daily_rate_pct
        - total_usdc
        - total_rate_pct
      title: QuoteCarry
    QuoteUpfront:
      properties:
        required_margin_usdc:
          type: number
          title: Required Margin Usdc
          description: Margin required to open the hedge.
        platform_fee_usdc:
          type: number
          title: Platform Fee Usdc
          description: Open + close platform fee, both reserved at open.
        total_upfront_usdc:
          type: number
          title: Total Upfront Usdc
          description: Total locked at open = margin + platform fee.
      type: object
      required:
        - required_margin_usdc
        - platform_fee_usdc
        - total_upfront_usdc
      title: QuoteUpfront
  securitySchemes:
    ApiKey:
      type: http
      scheme: bearer
      description: 'Partner API key: `mk_live_...` (production) or `mk_test_...` (sandbox).'

````