> ## Documentation Index > Fetch the complete documentation index at: https://docs.polymarket.com/llms.txt > Use this file to discover all available pages before exploring further. # Get user combo positions > Combinatorial (multi-market) positions held by a user, with per-leg breakdown. Also available at /v1/data/user/{address}/positions/combos (address from the path). ## OpenAPI ````yaml /api-spec/data-openapi.yaml get /v1/positions/combos openapi: 3.0.3 info: title: Polymarket Data API version: 1.0.0 description: > HTTP API for Polymarket data. This specification documents all public routes. servers: - url: https://data-api.polymarket.com description: Relative server (same host) security: [] tags: - name: Data API Status description: Data API health check - name: Core - name: Builders - name: Misc paths: /v1/positions/combos: get: tags: - Core summary: Get user combo positions description: >- Combinatorial (multi-market) positions held by a user, with per-leg breakdown. Also available at /v1/data/user/{address}/positions/combos (address from the path). parameters: - in: query name: user required: true schema: $ref: '#/components/schemas/Address' - in: query name: status schema: type: string enum: - OPEN - PARTIAL - RESOLVED_WIN - RESOLVED_LOSS - in: query name: sort schema: type: string enum: - current_value_desc - first_entry_desc - entry_cost_desc - resolved_at_desc - updated_asc default: current_value_desc - in: query name: market_id style: form explode: false schema: type: array items: $ref: '#/components/schemas/ComboConditionId' description: >- Comma-separated combo_condition_id values to filter to specific combos. These equal the market_id of isCombo rows on /activity. Omit for all of the user's combos. - in: query name: limit schema: type: integer default: 20 minimum: 0 maximum: 1000 - in: query name: offset schema: type: integer default: 0 minimum: 0 maximum: 100000 - in: query name: updatedAfter schema: type: integer description: >- Incremental-sync watermark (epoch seconds, inclusive): only rows whose updated_at is at or after this time. Positions mutate on resolution and redemption, so this catches changes a creation-time filter cannot. In sync mode (updatedAfter/updatedBefore/sort=updated_asc) every live row is returned regardless of balance, and the effective upper bound is clamped ~90s behind now (commit-visibility safety lag) — very recent rows appear on the next poll. Rows at the boundary may re-deliver: upsert by (combo_condition_id, combo_position_id). - in: query name: updatedBefore schema: type: integer description: >- Optional upper bound (epoch seconds, inclusive) for updated_at; clamped to the safety lag. Must be >= updatedAfter. - in: query name: cursor schema: type: string description: >- Opaque continuation token from a previous response's pagination.next_cursor. When present it supersedes offset (which is ignored). Invalid, tampered, or cross-endpoint tokens return 400. responses: '200': description: Success content: application/json: schema: $ref: '#/components/schemas/CombosResponse' '400': description: Bad Request content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '401': description: Unauthorized content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' '500': description: Server Error content: application/json: schema: $ref: '#/components/schemas/ErrorResponse' components: schemas: Address: type: string description: User Profile Address (0x-prefixed, 40 hex chars) pattern: ^0x[a-fA-F0-9]{40}$ example: '0x56687bf447db6ffa42ffe2204a05edaa20f55839' ComboConditionId: type: string description: >- Combo condition ID (0x-prefixed, 62 hex chars / bytes31). Equals the market_id (unified) / conditionId (legacy) of isCombo rows on /activity. pattern: ^0x[a-fA-F0-9]{62}$ example: '0x0391ab0ebea17b65ba87e071b0566e816b0000000000000000000000000000' CombosResponse: type: object properties: combos: type: array items: $ref: '#/components/schemas/ComboPosition' pagination: $ref: '#/components/schemas/Pagination' ErrorResponse: type: object properties: error: type: string required: - error ComboPosition: type: object properties: combo_condition_id: $ref: '#/components/schemas/ComboConditionId' combo_position_id: type: string module_id: type: integer description: 3 = Combinatorial user_address: $ref: '#/components/schemas/Address' shares_balance: type: string description: Decimal string (precision-preserving). entry_avg_price_usdc: type: string entry_cost_usdc: type: string description: >- REMAINING cost basis (entry_avg_price × shares_balance). Reads ~0 after a winning combo is redeemed — use total_cost_usdc to display what was paid on closed positions. realized_payout_usdc: type: string description: >- Gross redemption proceeds (winning combo shares redeem 1:1 at $1). "0.00" while OPEN / unredeemed / RESOLVED_LOSS; accumulates under PARTIAL. Gross payout, not net PnL — net = realized_payout_usdc − total_cost_usdc. total_cost_usdc: type: string description: >- Original cost basis = entry_avg_price × (shares_balance + realized_payout). Survives redemption burning the shares; equals entry_cost_usdc while OPEN. status: type: string enum: - OPEN - PARTIAL - RESOLVED_WIN - RESOLVED_LOSS first_entry_at: type: string description: RFC3339 UTC resolved_at: type: string nullable: true updated_at: type: string description: >- Last-modified time (UTC, ISO 8601). Bumps on any recompute of the row (trade, redemption, resolution classification) — the incremental-sync watermark field. Omitted on responses served by the legacy backend. legs_total: type: integer legs_resolved: type: integer legs_pending: type: integer legs: type: array items: $ref: '#/components/schemas/ComboLeg' Pagination: type: object description: >- Standard pagination metadata. No total count; has_more is derived from page fullness. next_cursor is opaque. properties: limit: type: integer offset: type: integer has_more: type: boolean next_cursor: type: string nullable: true description: >- Opaque signed cursor for the next page; null when has_more is false. Pass it back verbatim as ?cursor= on the next request (keep the same sort where the endpoint has one). Never parse or construct it. On cursor-enabled endpoints this makes deep pagination O(page) and stable against concurrent inserts. ComboLeg: type: object properties: leg_index: type: integer leg_position_id: type: string leg_condition_id: type: string description: The leg market's condition ID (distinct from the combo's). leg_outcome_index: type: integer leg_outcome_label: type: string leg_status: type: string description: Placeholder (OPEN) until leg-resolution integration ships. leg_resolved_at: type: string nullable: true leg_current_price: type: string description: Placeholder ("0") until live-price integration ships. market: $ref: '#/components/schemas/ComboMarket' ComboMarket: type: object properties: market_id: type: string slug: type: string title: type: string outcome: type: string image_url: type: string icon_url: type: string category: type: string subcategory: type: string tags: type: array items: type: string end_date: type: string description: RFC3339 UTC event: $ref: '#/components/schemas/ComboEvent' ComboEvent: type: object properties: event_id: type: string event_slug: type: string event_title: type: string event_image: type: string ````