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

# Merge Outcome Shares

<div className="venue-tags" aria-label="Supported venues">
  <span className="venue-tag">Hyperliquid</span>
</div>

Merges an equal number of Yes and No shares for one Hyperliquid-routed outcome into USDC.

## Endpoint

```text theme={null}
POST /exchange
```

`/exchange/userOutcome` is not a separate URL. `userOutcome` is the action type sent to the shared
`/exchange` endpoint.

## Request Body

| Parameter     | Type   | Description                                   |
| ------------- | ------ | --------------------------------------------- |
| `action`\*    | object | Outcome-action wrapper                        |
| `nonce`\*     | number | Unique replay-protection nonce                |
| `signature`\* | object | Notional EIP-712 signature with `r`, `s`, `v` |

### action

| Field            | Type   | Description                 |
| ---------------- | ------ | --------------------------- |
| `type`\*         | string | Must be `"userOutcome"`     |
| `mergeOutcome`\* | object | Outcome and amount to merge |

### action.mergeOutcome

| Field       | Type             | Description                                                                |
| ----------- | ---------------- | -------------------------------------------------------------------------- |
| `outcome`\* | number           | `outcomeId` returned by `outcomeMarkets`, e.g., `10218`                    |
| `amount`\*  | string or `null` | Positive integer number of complete sets, or `null` for the maximum amount |

Use the numeric `outcomeId`, not a side `assetId`, `hlEncoding`, or question ID.

When `amount` is `null`, Notional computes:

```text theme={null}
min(available Yes shares, available No shares)
```

Available shares are `total - hold`. If either side has no available shares, the request is
rejected. Explicit amounts must be positive integer-valued strings; fractional sets are not
supported.

## Signing

Sign the complete `action` and `nonce` using Notional's `NotionalExchange` domain:

```typescript theme={null}
import { signNotionalOrder } from "@notional/common";

const action = {
  type: "userOutcome",
  mergeOutcome: {
    outcome: 10218,
    amount: null,
  },
};
const nonce = Date.now();
const signature = await signNotionalOrder(
  apiWalletPrivateKey,
  action,
  nonce,
  undefined,
  true, // false for testnet
);
```

Submit `signature.r`, `signature.s`, and `signature.v` in the request. The user wallet or an
approved API wallet may sign.

<Warning>
  Do not sign this client request with Hyperliquid's native `Exchange` domain. Notional uses the
  distinct `NotionalExchange` domain so the signature cannot be replayed directly against
  Hyperliquid.
</Warning>

## Response

<Tabs sync={false}>
  <Tab title="200: Accepted">
    ```json theme={null}
    {
      "status": "ok",
      "response": {
        "type": "default"
      }
    }
    ```
  </Tab>

  <Tab title="400: No Balance">
    ```json theme={null}
    {
      "error": "No available outcome balance to merge",
      "code": "VALIDATION_FAILED",
      "timestamp": 1785254400000
    }
    ```
  </Tab>
</Tabs>

This response means Notional accepted and recorded the request. It does not mean Hyperliquid has
completed the merge.

## Progress and Balance Effects

1. `OutcomeMergeRequested` reserves `amount` on both outcome sides.
2. Notional submits the merge to Hyperliquid asynchronously.
3. `OutcomeMergeExecuted` removes the reserved Yes and No shares and credits the same amount in
   USDC.
4. `OutcomeMergeFailed` releases both reservations without crediting USDC.

Subscribe to `userTransactions` to track these transaction types. After an executed or failed
event, refresh `outcomeBalances` and `assets`.

After an uncertain response, retry only by resubmitting the identical signed body and nonce. Do not
change the amount or nonce while reusing the old signature.

## Validation Rules

* Use an `outcomeId` returned by `outcomeMarkets`; both sides must be quoted in USDC.
* The user must have enough unheld shares on both sides.
* The amount must be a positive whole number of outcome sets.
* Frozen accounts and accounts in active liquidation cannot submit the action.
* Only `mergeOutcome` is currently enabled under `userOutcome`.

`splitOutcome`, `mergeQuestion`, and `negateOutcome` are not public actions. Requests containing
those variants currently return HTTP `400`.

See [Outcome Markets](/api-reference/info-endpoints/outcome-markets) for outcome ids,
[Outcome Balances](/api-reference/info-endpoints/outcome-balances) for available shares, and
[Signing, Nonces, and API Wallets](/api-reference/signing-nonces-api-wallets) for signature details.
