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

# Get apiv1positions



## OpenAPI

````yaml /proto-openapi/api/openapi.yaml get /api/v1/positions/{positionId}
openapi: 3.0.3
info:
  title: Monaco Protocol API
  description: REST API for the Monaco Protocol hybrid CLOB exchange.
  version: 1.0.0
servers:
  - url: https://staging.apimonaco.xyz
    description: Staging server (Testnet)
security: []
tags:
  - name: AccountsService
  - name: ApplicationsService
  - name: AuthService
  - name: BuildercodeRewardsService
  - name: CopyTradingService
  - name: DelegatedAgentsService
  - name: FaucetService
  - name: FeesService
  - name: HealthService
  - name: ManagedMarketsService
    description: |-
      Wallet-authenticated maker assignments. The signed session must match both
       configured maker user and application. Owner IDs are process fences, never auth.
       Only wallet sessions are supported; delegated-agent sessions receive 403.
  - name: MarginAccountsService
    description: |-
      Current public isolated-margin semantics:
       - a user has one parent margin account per application scope
       - opening orders create or reuse isolated position buckets under that parent
       - parent account creation is handled internally by margin workflows
  - name: MarketService
  - name: OrderbookService
  - name: OrdersService
  - name: PositionsService
    description: |-
      Current public isolated-margin semantics:
       - positions link to a parent margin account and, when applicable, a bucket id
       - opening orders create or reuse isolated position buckets under the parent
       - users can open another isolated position by reusing the parent account with a different market bucket
  - name: PulseService
  - name: SweeperService
  - name: TraderCodeService
  - name: TradesService
  - name: WhitelistService
  - name: WithdrawalsService
paths:
  /api/v1/positions/{positionId}:
    get:
      tags:
        - PositionsService
      operationId: get_position
      parameters:
        - name: positionId
          in: path
          required: true
          schema:
            type: string
            default: 2b1a5f9c-0000-4000-8000-000000000002
          example: 2b1a5f9c-0000-4000-8000-000000000002
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetPositionResponse'
        '429':
          description: >-
            Read rate limit exceeded — every authenticated read draws one
            request from the account's read budget; retry after the interval in
            details.retryAfter
      security:
        - monacoSignature: []
        - monacoHttpSignature: []
components:
  schemas:
    GetPositionResponse:
      type: object
      properties:
        positionId:
          type: string
          nullable: true
        marginAccountId:
          type: string
          description: Margin account UUID for the isolated bucket that owns this position.
          nullable: true
        tradingPairId:
          type: string
          nullable: true
          format: uuid
        side:
          type: string
          nullable: true
        size:
          type: string
          description: |-
            Open rows: current absolute position quantity. Terminal rows
             (CLOSED/LIQUIDATED/EXPIRED): total quantity closed over the position's
             life, summed from its reducing executions when available.
          nullable: true
        entryPrice:
          type: string
          nullable: true
        markPrice:
          type: string
          nullable: true
        indexPrice:
          type: string
          nullable: true
        unrealizedPnl:
          type: string
          nullable: true
        realizedPnl:
          type: string
          nullable: true
        isolatedMargin:
          type: string
          description: >-
            Open ISOLATED rows: principal committed to the filled position,
            adjusted
             by settled realized PnL, fees and funding, clamped at zero. Collateral
             allocated to unfilled orders is excluded. This is the unrealized-return
             denominator and the same backing used by isolated liquidation. Placing,
             cancelling or resizing an unfilled order does not add position backing.
             A price gap can pass the backing before asynchronous liquidation occurs.
             Live and persisted reads use the same position-principal basis.
             Open CROSS rows: the position's posted margin. Terminal rows: total
             initial margin allocated across the position's reducing executions when
             available, used as the basis for lifetime realized return.
          nullable: true
        leverage:
          type: string
          nullable: true
        maintenanceMarginRequired:
          type: string
          description: |-
            Maintenance margin required by this position at mark_price using the
             market maintenance-margin rate. Zero when the position has no open exposure.
          nullable: true
        initialMarginRequired:
          type: string
          description: >-
            Initial margin required by this position at mark_price, honoring
            both its
             effective leverage and the market initial-margin floor. Zero when the
             position has no open exposure.
          nullable: true
        liquidationPrice:
          type: string
          description: |-
            Liquidation mark-price threshold. In ISOLATED mode, this is the
             position/risk-bucket threshold. In CROSS mode, it is conditional: it varies
             only this position's mark while all other marks in the cross risk bucket
             remain unchanged. Other position marks, funding, realized PnL,
             fees/reserves, and collateral can change it. Treat an absent or blank value
             as unavailable, never as zero.
          nullable: true
        status:
          type: string
          nullable: true
        updatedAt:
          type: string
          description: |-
            RFC 3339 instant at which this position was last MUTATED — a fill,
             collateral transfer, funding settlement or close — as the producer that
             owns the position recorded it. It is NOT the instant the response was
             built: polling an unchanged position returns the same value, and an oracle
             reprice does not move it. For an OPEN position every surface reports the
             same instant — the list, the detail read, the risk read, the WebSocket
             positions snapshot, and the live position_update frames.

             A TERMINAL row carries the instant the matching engine emitted the
             close, which can differ slightly from the close instant on the live
             position_update frame; older terminal rows may instead carry the
             persistence clock, trailing the close by the persistence lag. Any
             position read after a matching-engine restart also comes from the
             persistence clock and differs from the matching engine's by that lag.
             Accurate to that lag, not to the microsecond.

             A third case is not lag-bounded: an OPEN row read while the matching
             engine is unreachable falls back to the row's own lifecycle columns
             (close, then last funding, then open), so a position filled repeatedly
             since it opened reports its opening instant until funding settles. The
             live position_update frame is unaffected.

             Display metadata. `version` is the reconciliation key; ordering position
             state by this field is never correct.
          nullable: true
        riskBucketId:
          type: string
          nullable: true
        marginMode:
          type: string
          nullable: true
        netRealizedPnl:
          type: string
          description: |-
            Lifetime realized PnL net of trading fees and funding. Terminal rows
             only; absent when the position's reducing executions are unavailable.
             Deducts whole-life `cum_fees` once. Also absent after close until the
             final close is recorded in the PnL sample and the fee history is complete.
             A position with no PnL sample stays absent for 28 days after close while
             its sample may be pending. Beyond that it serves the closing-execution
             net, without opening fees that are no longer available.
          nullable: true
        realizedRoe:
          type: string
          description: |-
            Lifetime realized return on the total allocated initial margin, as a
             percentage, computed from NET realized PnL (after trading fees and
             funding). The denominator is initial margin only: fees and funding are
             costs rather than posted collateral, and funding is signed, so folding it
             into the denominator could drive it to zero or negative. Terminal rows
             only; absent when unavailable, including when the position's reducing
             executions do not account for its whole lifetime, and under the same
             conditions as `net_realized_pnl`.
          nullable: true
        exitPrice:
          type: string
          description: >-
            Volume-weighted average price across the position's reducing
            executions.
             Positions closed in several fills exit at this price, not at the final
             fill or the mark at close. Terminal rows only; absent when the position's
             reducing executions do not account for its whole lifetime.
          nullable: true
        fundingPaid:
          type: string
          description: >-
            Lifetime funding paid (signed; negative means received), summed over
            the
             position's reducing executions. Terminal rows only; absent when the
             position's reducing executions do not account for its whole lifetime.
          nullable: true
        feesPaid:
          type: string
          description: >-
            Trading fees paid on the position's reducing executions (signed;
            negative
             means rebated). Closing-side fees only — fees on opening fills are not
             included. Terminal rows only; absent when the position's reducing
             executions do not account for its whole lifetime.
          nullable: true
        cumFees:
          type: string
          description: >-
            Total lifetime trading fees for the position: opening-fill fees
            (from the
             PnL cost-basis engine) plus every reducing execution's fees — decreases,
             close, and any liquidation penalty. Signed; negative means net rebated,
             inclusive of the application-fee component. Unlike the closing-side
             reducing-execution fee field above, which omits opening fills, this is the
             whole-life figure, on open and terminal rows alike.
             Null when the opening-fill fees are unavailable — before the position's
             first PnL sample flushes, after its samples age out of PnL retention, or
             for positions predating the PnL service — rather than an understated
             partial. On a terminal row it is also null until the final close is
             recorded in the position's PnL sample, or while fee data is incomplete.
             On an OPEN or LIQUIDATING row it is also null when the position's reductions
             do not account for its realized PnL (lifetime_totals_status INCOMPLETE),
             rather than an understated total.
          nullable: true
        version:
          example: 918342
          type: integer
          description: >-
            Opaque, non-negative producer-owned version for this position row.
            Compare only within the same position; higher is newer. 0 is the
            unranked legacy sentinel and never participates in ordering: treat
            it exactly as an absent version and fall back to a full field
            comparison rather than ranking it as oldest. It advances on
            sequenced position mutations (open, add, reduce, close, funding,
            margin transfer, liquidation, ADL) and is shared by the persisted
            read, the WebSocket positions snapshot and a RANKED live
            position_update frame. Ranked live frames include fills, non-zero
            funding settlements, terminal closes/liquidations/ADL, direct
            isolated-position margin adds/reductions, and copy-position margin
            adds; each uses captured post-command state, and terminal frames
            retain the stored size and exact CLOSED/LIQUIDATED classification.
            After restart, a terminal frame rebuilt from legacy reduction
            history omits the version when that history lacks the margin fields
            needed to reconstruct complete lifetime allocated margin.
            Cross-risk-bucket ALLOCATE/RELEASE and copy follow/stop refreshes
            use margin_added/margin_reduced but omit the version because those
            commands write no position rows. Wallet IN/OUT and plain isolated
            allocation send no position frame. Transfer and funding frames use
            captured post-command state and are released only after durable
            acknowledgement. mark_price, unrealized_pnl, liquidation_price,
            leverage, maintenance_margin_required and initial_margin_required
            are UNVERSIONED valuation fields, re-derived per payload rather than
            served from the versioned row: the version does not advance for them
            (five move with the oracle mark; leverage does not, being opening
            notional over posted margin, but the live surfaces derive it while
            the persisted row serves its stored column, so it can still disagree
            at an unchanged version) (a valuation-only oracle tick persists
            nothing; a state-transitioning one, a breach or recovery, persists
            the account's snapshot and restamps the positions it changed), so
            the merge rule is per field group — on an equal version skip the
            versioned fields but still take all six from the newer payload,
            because discarding a whole payload on an equal version freezes
            displayed PnL and can leave a stale margin requirement on screen.
            isolated_margin is the one exception among the versioned fields: the
            WebSocket positions snapshot overlays it from an independent live
            matching-engine read rather than the versioned row, so take it from
            the newest payload on an equal version too or a consumer can retain
            stale backing. The version advances exactly when the row's versioned
            content changed at that sequence, a change undone within one
            persistence batch included; a position a command left unchanged
            keeps its version, so a RANKED live frame for an untouched sibling
            of a filled position can carry a higher version than the persisted
            row while describing identical content — rank it as newer, and
            nothing changes. A response served from live matching-engine state
            reports 0 (unranked): the engine holds the state but not the
            version.
          format: int64
          minimum: 0
          nullable: true
        openedAt:
          type: string
          description: |-
            RFC 3339 instant at which this position opened. Same contract as
             `Position.opened_at` above.
          nullable: true
        lifetimeTotalsStatus:
          enum:
            - LIFETIME_TOTALS_STATUS_UNSPECIFIED
            - LIFETIME_TOTALS_STATUS_COMPLETE
            - LIFETIME_TOTALS_STATUS_PENDING
            - LIFETIME_TOTALS_STATUS_INCOMPLETE
          type: string
          description: |-
            Whether this position's lifetime totals are served. Same contract as
             `Position.lifetime_totals_status` above.
          format: enum
          nullable: true
  securitySchemes:
    monacoSignature:
      type: apiKey
      description: >-
        Ed25519 session-key request signing. Every authenticated request carries
        three headers: `X-Monaco-PublicKey` (64-char lowercase-hex session
        public key), `X-Monaco-Timestamp` (Unix milliseconds, within 30s of
        server time), and `X-Monaco-Signature` (hex ed25519 signature). The
        signature is over `METHOD\npath?query\ntimestamp_ms\nSHA256_hex(body)`,
        where the body hash is the SHA-256 of the empty byte string when there
        is no body. Obtain the session keypair from `POST
        /api/v1/auth/challenge` followed by `POST /api/v1/auth/verify`.
      name: X-Monaco-Signature
      in: header
    monacoHttpSignature:
      type: apiKey
      description: >-
        RFC 9421 Ed25519 session-key request signatures. Send Signature-Input,
        Signature, and Content-Digest together; never combine them with
        X-Monaco-* credentials. The monaco signature covers @method, @path,
        @query, and content-digest in that order, with created (Unix seconds
        within 30s of server time), keyid (registered lowercase-hex session
        public key), and alg=ed25519 parameters. Content-Digest uses RFC 9530
        sha-256 over the exact body bytes, including the empty body. Query
        coverage retains ordering and percent encoding. Timestamp freshness does
        not reject repeated identical requests; use endpoint idempotency where
        supported. Existing legacy signing remains supported during server-first
        migration; SDK RFC 9421 signing is opt-in. See
        https://docs.0xmonaco.com/reference/http-message-signatures for the
        complete profile and trust model.
      name: Signature
      in: header

````

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