> ## Documentation Index
> Fetch the complete documentation index at: https://chainstack-docs-polygon-erigon-trace-deprecation.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# User outcome | Hyperliquid exchange

> Split or merge outcome-market shares to convert between quote tokens and Yes/No shares on Hyperliquid. On Hyperliquid exchange.

<Info>
  You can only use this endpoint on the official Hyperliquid public API. It is not available through Chainstack, as the open-source node implementation does not support it yet. See [Hyperliquid methods](/docs/hyperliquid-methods) for the full availability breakdown.
</Info>

<Note>
  This endpoint requires signature authentication. See our comprehensive [Authentication via Signatures guide](/docs/hyperliquid-authentication-guide) for implementation details.
</Note>

The `userOutcome` action manually splits or merges outcome-market shares to convert between quote tokens and Yes/No shares. Outcome markets are binary (Yes/No) prediction markets on Hyperliquid. A single `userOutcome` action carries exactly one of four operations: `splitOutcome`, `mergeOutcome`, `mergeQuestion`, or `negateOutcome`.

## Parameters

### Required parameters

* `action` (object, required) — The user outcome action. Set `type` to `"userOutcome"` and include exactly one of the following operations:
  * `splitOutcome` — Split `X` quote tokens into `X` Yes and `X` No shares of an outcome. Fields: `outcome` (number), `amount` (string, e.g. `"123.0"`).
  * `mergeOutcome` — Merge `X` Yes and `X` No shares of an outcome into `X` quote tokens. Fields: `outcome` (number), `amount` (string or `null`, where `null` means the maximum available).
  * `mergeQuestion` — Merge `X` Yes shares from each outcome associated to the same question into `X` quote tokens. Fields: `question` (number), `amount` (string or `null`, where `null` means the maximum available).
  * `negateOutcome` — Convert `X` No shares from an outcome associated with a question into `X` Yes shares of every other outcome associated with the question. Fields: `question` (number), `outcome` (number), `amount` (string).
* `nonce` (number, required) — Current timestamp in milliseconds (must be recent).
* `signature` (object, required) — EIP-712 signature of the action.

### Optional parameters

* `expiresAfter` (number, optional) — Timestamp in milliseconds after which the request is rejected.

## Returns

Returns an object with the action status:

* `status` — `"ok"` if the request was processed.
* `response` — Contains operation details:
  * `type` — `"default"`.

## Example request

<CodeGroup>
  ```shell cURL theme={null}
  # Split outcome: split 1 quote token into 1 Yes and 1 No share of outcome 0
  curl -X POST https://api.hyperliquid.xyz/exchange \
    -H "Content-Type: application/json" \
    -d '{
      "action": {
        "type": "userOutcome",
        "splitOutcome": {"outcome": 0, "amount": "1"}
      },
      "nonce": 1234567890123,
      "signature": {...}
    }'
  ```

  ```python Python (hyperliquid-python-sdk) theme={null}
  # Note: the official hyperliquid-python-sdk does not expose a userOutcome
  # helper yet, so build and post the signed action directly.
  from hyperliquid.exchange import Exchange
  from hyperliquid.utils import constants
  from hyperliquid.utils.signing import sign_l1_action, get_timestamp_ms
  import eth_account

  # Public Hyperliquid mainnet endpoint
  wallet = eth_account.Account.from_key("0x...")  # your private key
  exchange = Exchange(wallet, constants.MAINNET_API_URL)

  timestamp = get_timestamp_ms()
  action = {
      "type": "userOutcome",
      "splitOutcome": {"outcome": 0, "amount": "1"},
  }
  signature = sign_l1_action(
      wallet,
      action,
      None,  # vault_address
      timestamp,
      None,  # expires_after
      exchange.base_url == constants.MAINNET_API_URL,
  )
  result = exchange._post_action(action, signature, timestamp)
  print(result)
  ```

  ```typescript TypeScript (@nktkas/hyperliquid) theme={null}
  import { ExchangeClient, HttpTransport } from "@nktkas/hyperliquid";
  import { privateKeyToAccount } from "viem/accounts";

  // Public Hyperliquid mainnet endpoint (default transport)
  const wallet = privateKeyToAccount("0x..."); // viem or ethers account
  const transport = new HttpTransport();
  const exchange = new ExchangeClient({ transport, wallet });

  // Split 1 quote token into 1 Yes and 1 No share of outcome 0
  const result = await exchange.userOutcome({
    splitOutcome: { outcome: 0, amount: "1" },
  });

  console.log(result);
  ```
</CodeGroup>

## Response example

```json theme={null}
{
  "status": "ok",
  "response": {
    "type": "default"
  }
}
```

## Use cases

* **Provide outcome liquidity** — Split quote tokens into Yes and No shares to make markets on both sides
* **Redeem shares** — Merge matched Yes and No shares back into quote tokens
* **Manage positions across a question** — Merge or negate shares across the outcomes of a single question


## OpenAPI

````yaml openapi/hyperliquid_node_api/hypercore_exchange/exchange_user_outcome.json post /exchange
openapi: 3.0.0
info:
  title: Hyperliquid Exchange API
  version: 1.0.0
  description: >-
    API for trading operations on Hyperliquid exchange requiring authentication.
    ⚠️ WARNING: These endpoints require EIP-712 signatures for authentication.
    The example values provided will NOT work without proper cryptographic
    signing. You must implement EIP-712 signing to use these endpoints
    successfully.
servers:
  - url: https://api.hyperliquid.xyz
security: []
paths:
  /exchange:
    post:
      tags:
        - hyperliquid exchange
      summary: User outcome (split / merge / negate outcome shares)
      operationId: userOutcome
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                action:
                  type: object
                  description: >-
                    User outcome action. Provide exactly one of splitOutcome,
                    mergeOutcome, mergeQuestion, or negateOutcome alongside the
                    type.
                  properties:
                    type:
                      type: string
                      default: userOutcome
                      enum:
                        - userOutcome
                      description: Action type
                    splitOutcome:
                      type: object
                      description: >-
                        Split X quote tokens into X Yes and X No shares of an
                        outcome.
                      properties:
                        outcome:
                          type: integer
                          description: Outcome identifier.
                        amount:
                          type: string
                          description: Amount of quote tokens to split.
                  required:
                    - type
                nonce:
                  type: integer
                  description: Current timestamp in milliseconds
                signature:
                  type: object
                  description: EIP-712 signature of the action with r, s, v components
                  properties:
                    r:
                      type: string
                      description: ECDSA signature r component (hex string)
                      example: >-
                        0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
                    s:
                      type: string
                      description: ECDSA signature s component (hex string)
                      example: >-
                        0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321
                    v:
                      type: integer
                      description: ECDSA recovery id (27 or 28)
                      example: 27
                  required:
                    - r
                    - s
                    - v
                expiresAfter:
                  type: integer
                  description: >-
                    Timestamp in milliseconds after which the request is
                    rejected (optional)
              required:
                - action
                - nonce
                - signature
            example:
              action:
                type: userOutcome
                splitOutcome:
                  outcome: 0
                  amount: '1'
              nonce: 1705234567890
              signature:
                r: >-
                  0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
                s: >-
                  0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321
                v: 27
      responses:
        '200':
          description: User outcome result
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    description: Request status
                  response:
                    type: object
                    properties:
                      type:
                        type: string
                        default: default
                example:
                  status: ok
                  response:
                    type: default

````