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

# Trading & Orders

> Create and manage orders with the Go SDK

## Overview

The `OrderClient` handles order creation, EIP-712 signing, and order management. It supports Good-til-cancelled (GTC), Fill-and-kill (FAK), and Fill-or-kill (FOK) orders.

## Prerequisites

Before placing orders, you need three components:

```go theme={null}
import (
    "context"
    "log"
    "os"

    limitless "github.com/limitless-labs-group/limitless-exchange-go-sdk/limitless"
)

client := limitless.NewHttpClient(
    limitless.WithHMACCredentials(limitless.HMACCredentials{
        TokenID: os.Getenv("LMTS_TOKEN_ID"),
        Secret:  os.Getenv("LMTS_TOKEN_SECRET"),
    }),
)
marketFetcher := limitless.NewMarketFetcher(client)

orderClient, err := limitless.NewOrderClient(
    client,
    "0xYOUR_PRIVATE_KEY",  // hex-encoded private key (with or without "0x" prefix)
)
if err != nil {
    log.Fatal(err)
}
```

| Component       | Purpose                                        |
| --------------- | ---------------------------------------------- |
| `HttpClient`    | Authenticated HTTP client for API requests     |
| `MarketFetcher` | Fetches market data and caches venue addresses |
| `OrderClient`   | Creates, signs, and submits orders             |

<Note>
  The `OrderClient` lazily fetches your user profile on the first order to determine your fee rate. The `CHAIN_ID` environment variable defaults to `8453` (Base mainnet).
</Note>

<Warning>
  **Wallet-mode preflight.** Accepting the one-time "choose your trading wallet" prompt in the app enables 1-click (smart wallet) trading on your Limitless profile. Once that mode is set, self-signed orders are rejected with `Signer does not match - you should use embedded address for smart wallet`. Switch the profile to EOA trading mode first: see [Trading wallet mode](/developers/eip712-signing#trading-wallet-mode-whose-address-signs).
</Warning>

## Token approvals

Before your first trade on a given venue, you must approve the exchange contracts to spend your tokens. This is a **one-time on-chain setup** per venue.

<Tabs>
  <Tab title="Standard CLOB">
    For standard CLOB markets, approve USDC and Conditional Tokens to the **exchange** contract:

    ```go theme={null}
    market, _ := marketFetcher.GetMarket(ctx, "your-market-slug")
    exchange := market.Venue.Exchange

    // Use go-ethereum or any Ethereum client to send approval transactions:
    // 1. Approve USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913) to the exchange for BUY orders
    // 2. Approve Conditional Tokens (0xC9c98965297Bc527861c898329Ee280632B76e18) to the exchange for SELL orders
    ```
  </Tab>

  <Tab title="NegRisk">
    For NegRisk markets, you must additionally approve the **adapter** contract:

    ```go theme={null}
    market, _ := marketFetcher.GetMarket(ctx, "your-negrisk-slug")
    exchange := market.Venue.Exchange
    adapter := *market.Venue.Adapter

    // 1. Approve USDC to the exchange (same as CLOB)
    // 2. Approve Conditional Tokens to the exchange (same as CLOB)
    // 3. Approve Conditional Tokens to the adapter (NegRisk only)
    ```
  </Tab>
</Tabs>

<Warning>
  Approvals are on-chain transactions that cost gas. You only need to perform them once per venue. Use `Venue.Exchange` for both CLOB and NegRisk, and additionally `Venue.Adapter` for NegRisk markets.
</Warning>

## GTC orders (Good-til-cancelled)

GTC orders remain on the orderbook until filled or explicitly cancelled. Specify `Price` (0.0–1.0, tick-aligned to 0.001) and `Size` (number of shares):

```go theme={null}
ctx := context.Background()
market, err := marketFetcher.GetMarket(ctx, "btc-above-100k-march-2025")
if err != nil {
    log.Fatal(err)
}

result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
    OrderType:  limitless.OrderTypeGTC,
    MarketSlug: "btc-above-100k-march-2025",
    Args: limitless.GTCOrderArgs{
        TokenID: market.Tokens.Yes,
        Side:    limitless.SideBuy,
        Price:   0.65,
        Size:    10.0,
    },
})
if err != nil {
    log.Fatal(err)
}
fmt.Printf("Order placed: %+v\n", result.Order)
```

### Post-only GTC order

Use `PostOnly: true` to ensure your order is never filled immediately as a taker. If the order would cross the spread (i.e., match against existing orders), it is **rejected** instead. This guarantees you always receive maker fees.

```go theme={null}
result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
    OrderType:  limitless.OrderTypeGTC,
    MarketSlug: "btc-above-100k-march-2025",
    Args: limitless.GTCOrderArgs{
        TokenID:  market.Tokens.Yes,
        Side:     limitless.SideBuy,
        Price:    0.65,
        Size:     10.0,
        PostOnly: true,
    },
})
```

### GTCOrderArgs

| Field        | Type      | Description                                                                                             |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------- |
| `TokenID`    | `string`  | Token ID from `Market.Tokens.Yes` or `Market.Tokens.No`                                                 |
| `Side`       | `Side`    | `SideBuy` (0) or `SideSell` (1)                                                                         |
| `Price`      | `float64` | Price per share (0.0–1.0, must be tick-aligned to 0.001)                                                |
| `Size`       | `float64` | Number of shares to buy or sell                                                                         |
| `PostOnly`   | `bool`    | Optional. When `true`, rejects the order if it would immediately match. Default `false`.                |
| `Expiration` | `string`  | Must be `"0"` (the default). Non-zero expiration is not currently supported and the API rejects it.     |
| `Nonce`      | `*int`    | Must be `0` (the default when `nil`). Non-zero nonce is not currently supported and the API rejects it. |
| `Taker`      | `string`  | Optional taker address (defaults to zero address)                                                       |

## Self-trade prevention

Set `StpPolicy` on `CreateOrderParams` to control what happens when your incoming order would match your own resting order on the same token. It is a top-level request field — not part of the EIP-712 signed order args — and applies to any order type. Leave it empty to keep the server default, `cancel_maker`.

```go theme={null}
result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
    OrderType:  limitless.OrderTypeGTC,
    MarketSlug: "btc-above-100k-march-2025",
    StpPolicy:  "cancel_maker", // "cancel_maker" | "cancel_taker" | "cancel_both"
    Args: limitless.GTCOrderArgs{
        TokenID: market.Tokens.Yes,
        Side:    limitless.SideBuy,
        Price:   0.65,
        Size:    10.0,
    },
})
```

| Value          | Result                                                                                 |
| -------------- | -------------------------------------------------------------------------------------- |
| `cancel_maker` | Default. Cancels your conflicting resting order and continues with the incoming order. |
| `cancel_taker` | Rejects the incoming order before it self-trades.                                      |
| `cancel_both`  | Cancels your conflicting resting order and rejects the incoming order.                 |

The create-order response carries an `Execution` field with the outcome:

```go theme={null}
if result.Execution.SettlementStatus == "CANCELED" && result.Execution.Reason == "STP_TAKER_REJECTED" {
    fmt.Println("Order rejected by self-trade prevention")
} else if len(result.Execution.StpMakerCancels) > 0 {
    fmt.Printf("Cancelled own resting orders: %v\n", result.Execution.StpMakerCancels)
}
```

| `Execution` field  | Type       | Description                                                         |
| ------------------ | ---------- | ------------------------------------------------------------------- |
| `SettlementStatus` | `string`   | `CANCELED` when a `cancel_taker` / `cancel_both` order is rejected. |
| `Reason`           | `string`   | `STP_TAKER_REJECTED` when the incoming order was rejected.          |
| `StpMakerCancels`  | `[]string` | Resting order ids cancelled by `cancel_maker` / `cancel_both`.      |

<Note>
  Self-trade prevention blocks same-profile matches on the **same token** only. Orders on a different token of the same profile are unaffected. The wire field is always `stpPolicy`, regardless of the SDK.
</Note>

## FAK orders (Fill-and-kill)

FAK orders use the same `Price` and `Size` inputs as GTC, but they only consume immediately available liquidity and cancel any unmatched remainder.

`PostOnly` is not supported for FAK orders.

```go theme={null}
result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
    OrderType:  limitless.OrderTypeFAK,
    MarketSlug: "btc-above-100k-march-2025",
    Args: limitless.FAKOrderArgs{
        TokenID: market.Tokens.Yes,
        Side:    limitless.SideBuy,
        Price:   0.45,
        Size:    10.0,
    },
})
if err != nil {
    log.Fatal(err)
}

if len(result.MakerMatches) > 0 {
    fmt.Printf("FAK order matched immediately with %d fill(s)\n", len(result.MakerMatches))
} else {
    fmt.Println("FAK remainder was cancelled.")
}
```

### FAKOrderArgs

| Field        | Type      | Description                                                                                             |
| ------------ | --------- | ------------------------------------------------------------------------------------------------------- |
| `TokenID`    | `string`  | Token ID from `Market.Tokens.Yes` or `Market.Tokens.No`                                                 |
| `Side`       | `Side`    | `SideBuy` (0) or `SideSell` (1)                                                                         |
| `Price`      | `float64` | Price per share (0.0–1.0, must be tick-aligned to 0.001)                                                |
| `Size`       | `float64` | Number of shares to buy or sell                                                                         |
| `Expiration` | `string`  | Must be `"0"` (the default). Non-zero expiration is not currently supported and the API rejects it.     |
| `Nonce`      | `*int`    | Must be `0` (the default when `nil`). Non-zero nonce is not currently supported and the API rejects it. |
| `Taker`      | `string`  | Optional taker address (defaults to zero address)                                                       |

## FOK orders (Fill-or-kill)

FOK orders execute immediately and fully, or are rejected entirely. Instead of `Price` and `Size`, you specify `MakerAmount`:

<Tabs>
  <Tab title="FOK BUY">
    When buying, `MakerAmount` is the **total USDC you want to spend** (max 6 decimal places). The exchange fills as many shares as possible at the best available price:

    ```go theme={null}
    result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
        OrderType:  limitless.OrderTypeFOK,
        MarketSlug: "btc-above-100k-march-2025",
        Args: limitless.FOKOrderArgs{
            TokenID:     market.Tokens.Yes,
            Side:        limitless.SideBuy,
            MakerAmount: 10.0, // spend 10 USDC
        },
    })
    ```
  </Tab>

  <Tab title="FOK SELL">
    When selling, `MakerAmount` is the **number of shares to sell**. The exchange returns USDC at the best available price:

    ```go theme={null}
    result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
        OrderType:  limitless.OrderTypeFOK,
        MarketSlug: "btc-above-100k-march-2025",
        Args: limitless.FOKOrderArgs{
            TokenID:     market.Tokens.Yes,
            Side:        limitless.SideSell,
            MakerAmount: 10.0, // sell 10 shares
        },
    })
    ```
  </Tab>
</Tabs>

### FOKOrderArgs

| Field         | Type      | Description                                                                                             |
| ------------- | --------- | ------------------------------------------------------------------------------------------------------- |
| `TokenID`     | `string`  | Token ID from `Market.Tokens.Yes` or `Market.Tokens.No`                                                 |
| `Side`        | `Side`    | `SideBuy` (0) or `SideSell` (1)                                                                         |
| `MakerAmount` | `float64` | USDC to spend (buy) or shares to sell (sell), max 6 decimal places                                      |
| `Expiration`  | `string`  | Must be `"0"` (the default). Non-zero expiration is not currently supported and the API rejects it.     |
| `Nonce`       | `*int`    | Must be `0` (the default when `nil`). Non-zero nonce is not currently supported and the API rejects it. |
| `Taker`       | `string`  | Optional taker address (defaults to zero address)                                                       |

## Advanced: build and sign separately

For advanced use cases, you can build and sign orders without submitting them:

```go theme={null}
// Build an unsigned order
unsigned, err := orderClient.BuildUnsignedOrder(ctx, limitless.GTCOrderArgs{
    TokenID: market.Tokens.Yes,
    Side:    limitless.SideBuy,
    Price:   0.65,
    Size:    10.0,
})
if err != nil {
    log.Fatal(err)
}

// Sign the order
signature, err := orderClient.SignOrder(unsigned)
if err != nil {
    log.Fatal(err)
}
fmt.Println("Signature:", signature)
```

## AMM trading

CLOB orders trade against the orderbook. AMM (FPMM) markets trade against a pool, and the SDK exposes them through `sdk.AMM`. The service calls `POST /amm/allowances/check`, `POST /amm/allowances/approve`, `POST /amm/buy`, and `POST /amm/sell` on behalf of a partner server wallet.

Use it when the market is an AMM market and you want the server to hold custody, sign the trade, and pay gas. See [AMM Trading (Server Wallets)](/developers/amm-trading) for the underlying endpoints and market model.

### Requirements

* Authenticate with an HMAC API token that holds **both** the `trading` and `delegated_signing` scopes, or call the `*WithIdentity` variants with a Privy identity token. Legacy `x-api-key` credentials are rejected.
* The trade runs against a server-wallet sub-account. Set `OnBehalfOf` to the sub-account profile ID (`1..=2147483647`), or omit it (zero value) to trade from the authenticated profile.
* Amounts are **positive integer strings** in the collateral token's base units (for USDC: `"1000000"` = 1 USDC). Never use `float64`.
* `SlippageBps` is optional (`*int`). `nil` uses the server default of `100` (1%); values range from `0` to `1000`.
* `OutcomeIndex` is `AMMOutcomeYes` (0) or `AMMOutcomeNo` (1).

### One-time approval per wallet and market

`BUY` and `SELL` approvals are independent and set up once per wallet and market. `Buy` and `Sell` do **not** preflight allowances themselves. Confirm the allowance first.

`EnsureAllowance` runs `CheckAllowance`, submits `ApproveAllowance` at most once when missing, then polls the check until `Confirmed` is true. Polling defaults to every two seconds; use the context timeout to bound how long it waits.

```go theme={null}
marketSlug := "btc-100k-weekly"
childProfileID := 12345

for _, side := range []limitless.AMMAllowanceSide{
    limitless.AMMAllowanceSideBuy,
    limitless.AMMAllowanceSideSell,
} {
    allowanceCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
    _, err := sdk.AMM.EnsureAllowance(allowanceCtx, limitless.AMMAllowanceParams{
        Market:     marketSlug,
        Side:       side,
        OnBehalfOf: childProfileID,
    })
    cancel()
    if err != nil {
        return err
    }
}
```

<Note>
  A `submitted` response from `ApproveAllowance` (HTTP 202) is not confirmation. Either use `EnsureAllowance`, or poll `CheckAllowance` until `Confirmed` is true.
</Note>

### Buy shares

`Buy` spends an exact collateral amount on the chosen outcome. Pass a unique `IdempotencyKey` per trade. On a timeout retry, reuse the same immutable params value so the serialized body and idempotency key stay byte-identical.

```go theme={null}
slippageBps := 100
buyParams := limitless.AMMBuyParams{
    Market:           marketSlug,
    OutcomeIndex:     limitless.AMMOutcomeYes,
    CollateralAmount: "1000000", // 1 USDC in base units
    SlippageBps:      &slippageBps,
    IdempotencyKey:   "buy-unique-key-001",
    OnBehalfOf:       childProfileID,
}

buy, err := sdk.AMM.Buy(ctx, buyParams)
if err != nil {
    return err
}
fmt.Println(buy.Status, buy.ExpectedShares, buy.MinShares)
```

### Sell shares

`Sell` requests an exact collateral return by selling outcome shares.

```go theme={null}
sellParams := limitless.AMMSellParams{
    Market:                 marketSlug,
    OutcomeIndex:           limitless.AMMOutcomeYes,
    CollateralReturnAmount: "992015",
    IdempotencyKey:         "sell-unique-key-001",
    OnBehalfOf:             childProfileID,
}

sell, err := sdk.AMM.Sell(ctx, sellParams)
if err != nil {
    return err
}
fmt.Println(sell.Status, sell.ExpectedShares, sell.MaxShares)
```

<Note>
  Reusing an `IdempotencyKey` with different params raises `ConflictError` (HTTP 409). The four AMM routes share a rate limit of 10 requests / 10 seconds per actor. Use the `*WithRawResponse` variants (e.g. `sdk.AMM.BuyWithRawResponse`) when you need the underlying HTTP status and headers.
</Note>

## Cancelling orders

<Tabs>
  <Tab title="Cancel a single order">
    Cancel a specific order by its ID:

    ```go theme={null}
    msg, err := orderClient.Cancel(ctx, "abc123-def456")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(msg)
    ```
  </Tab>

  <Tab title="Cancel all orders on a market">
    Cancel every open order you have on a given market:

    ```go theme={null}
    msg, err := orderClient.CancelAll(ctx, "btc-above-100k-march-2025")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(msg)
    ```
  </Tab>
</Tabs>

## Cancel and replace

`CancelReplace` cancels one open order and submits a replacement in the same request. Use it to reprice or resize a resting order in one round-trip instead of separate cancel and create calls. `CancelReplaceBatch` runs several of these operations in a single call.

The cancel and the replacement are **not atomic**: they report independent outcomes, and a successful cancel does not guarantee a successful replacement. Choose the failure mode with `CancelReplaceMode`:

| Mode                         | Cancellation fails      | Replacement result                               |
| ---------------------------- | ----------------------- | ------------------------------------------------ |
| `CancelReplaceStopOnFailure` | Stops the operation     | `NOT_ATTEMPTED`                                  |
| `CancelReplaceAllowFailure`  | Continues the operation | `SUCCESS`, `FAILURE`, or `UNKNOWN` independently |

Identify the order to cancel with `CancelByOrderID` or `CancelByClientOrderID`. The replacement is a normal signed order and uses the same `OrderArgs` fields as `CreateOrder`.

### Single cancel-replace

```go theme={null}
result, err := orderClient.CancelReplace(ctx, limitless.CancelReplaceParams{
    Cancel: limitless.CancelByOrderID("order_abc123"),
    Mode:   limitless.CancelReplaceStopOnFailure,
    Replacement: limitless.CancelReplaceOrderParams{
        MarketSlug: market.Slug,
        OrderType:  limitless.OrderTypeGTC,
        Args: limitless.OrderArgs{
            TokenID: market.Tokens.Yes,
            Side:    limitless.SideBuy,
            Price:   0.62,
            Size:    100,
        },
    },
})
if err != nil {
    log.Fatal(err)
}

if result.Cancel.Status() == limitless.CancelReplaceCancelSuccess {
    if data, ok := result.Cancel.Success(); ok {
        fmt.Println("Cancelled:", data.OrderID)
    }
}
if result.Replacement.Status() == limitless.CancelReplaceReplacementSuccess {
    if data, ok := result.Replacement.Success(); ok {
        fmt.Println("Replacement placed:", data.Order.ID)
    }
}
```

### Batch cancel-replace

Each operation runs independently and its result is returned with the caller's `Index`:

```go theme={null}
batch, err := orderClient.CancelReplaceBatch(ctx, []limitless.CancelReplaceParams{
    {
        Cancel: limitless.CancelByOrderID("order_abc123"),
        Mode:   limitless.CancelReplaceAllowFailure,
        Replacement: limitless.CancelReplaceOrderParams{
            MarketSlug: market.Slug,
            OrderType:  limitless.OrderTypeGTC,
            Args:       limitless.OrderArgs{TokenID: market.Tokens.Yes, Side: limitless.SideBuy, Price: 0.62, Size: 100},
        },
    },
    {
        Cancel: limitless.CancelByClientOrderID("my-tag-42"),
        Mode:   limitless.CancelReplaceStopOnFailure,
        Replacement: limitless.CancelReplaceOrderParams{
            MarketSlug: market.Slug,
            OrderType:  limitless.OrderTypeGTC,
            Args:       limitless.OrderArgs{TokenID: market.Tokens.No, Side: limitless.SideSell, Price: 0.41, Size: 50},
        },
    },
})
if err != nil {
    log.Fatal(err)
}

for _, item := range batch.Results {
    fmt.Println(item.Index, item.Cancel.Status(), item.Replacement.Status())
}
```

### Delegated cancel-replace

Partners with the `delegated_signing` scope call `delegatedOrders.CancelReplace` and `delegatedOrders.CancelReplaceBatch`. The server signs the replacement using the sub-account's managed wallet, so no signing key is required. Set `OnBehalfOf` (the sub-account profile ID) on every operation:

```go theme={null}
_, err := delegatedOrders.CancelReplace(ctx, limitless.DelegatedCancelReplaceParams{
    Cancel:     limitless.CancelByOrderID("order_abc123"),
    Mode:       limitless.CancelReplaceStopOnFailure,
    OnBehalfOf: partnerAccount.ProfileID,
    Replacement: limitless.CancelReplaceOrderParams{
        MarketSlug: market.Slug,
        OrderType:  limitless.OrderTypeGTC,
        Args:       limitless.OrderArgs{TokenID: market.Tokens.Yes, Side: limitless.SideBuy, Price: 0.62, Size: 100},
    },
})
```

<Note>
  See [`POST /orders/cancel-replace`](/api-reference/trading/cancel-replace) and [`POST /orders/cancel-replace/batch`](/api-reference/trading/cancel-replace-batch) for the full request and response shapes, per-status fields, and failure semantics.
</Note>

## Enums reference

### Side

| Constant   | Value | Description          |
| ---------- | ----- | -------------------- |
| `SideBuy`  | `0`   | Buy shares with USDC |
| `SideSell` | `1`   | Sell shares for USDC |

### OrderType

| Constant       | Value   | Description                                                 |
| -------------- | ------- | ----------------------------------------------------------- |
| `OrderTypeGTC` | `"GTC"` | Good-til-cancelled limit order (rests on the book)          |
| `OrderTypeFAK` | `"FAK"` | Fill-and-kill limit order (cancels any unmatched remainder) |
| `OrderTypeFOK` | `"FOK"` | Fill-or-kill market order (fills immediately or rejects)    |

## Error handling

The SDK returns typed errors for order failures. Use `errors.As()` to inspect them:

```go theme={null}
import "errors"

result, err := orderClient.CreateOrder(ctx, params)
if err != nil {
    var apiErr *limitless.APIError
    if errors.As(err, &apiErr) {
        fmt.Printf("Order failed — status %d: %s\n", apiErr.Status, apiErr.Message)
    }

    var validErr *limitless.OrderValidationError
    if errors.As(err, &validErr) {
        fmt.Printf("Validation error on field %s: %s\n", validErr.Field, validErr.Message)
    }
}
```

<Note>
  See [Error Handling & Retry](/developers/sdk/go/error-handling) for details on error types and the `WithRetry` function.
</Note>

## Complete example

```go theme={null}
package main

import (
    "context"
    "errors"
    "fmt"
    "log"
    "os"

    limitless "github.com/limitless-labs-group/limitless-exchange-go-sdk/limitless"
)

func main() {
    client := limitless.NewHttpClient(
        limitless.WithHMACCredentials(limitless.HMACCredentials{
            TokenID: os.Getenv("LMTS_TOKEN_ID"),
            Secret:  os.Getenv("LMTS_TOKEN_SECRET"),
        }),
    )
    marketFetcher := limitless.NewMarketFetcher(client)
    ctx := context.Background()

    orderClient, err := limitless.NewOrderClient(client, "0xYOUR_PRIVATE_KEY")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println("Wallet:", orderClient.WalletAddress())

    // Fetch market (caches venue automatically)
    market, err := marketFetcher.GetMarket(ctx, "btc-above-100k-march-2025")
    if err != nil {
        log.Fatal(err)
    }

    // Place a GTC BUY order for 10 YES shares at $0.65
    result, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
        OrderType:  limitless.OrderTypeGTC,
        MarketSlug: "btc-above-100k-march-2025",
        Args: limitless.GTCOrderArgs{
            TokenID: market.Tokens.Yes,
            Side:    limitless.SideBuy,
            Price:   0.65,
            Size:    10.0,
        },
    })
    if err != nil {
        var apiErr *limitless.APIError
        if errors.As(err, &apiErr) {
            log.Fatalf("API error — status %d: %s", apiErr.Status, apiErr.Message)
        }
        log.Fatal(err)
    }
    fmt.Printf("GTC order placed: %+v\n", result.Order)

    // Place a FAK BUY order for 10 YES shares at $0.45
    fakResult, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
        OrderType:  limitless.OrderTypeFAK,
        MarketSlug: "btc-above-100k-march-2025",
        Args: limitless.FAKOrderArgs{
            TokenID: market.Tokens.Yes,
            Side:    limitless.SideBuy,
            Price:   0.45,
            Size:    10.0,
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("FAK order placed: %+v\n", fakResult.Order)

    // Place a FOK BUY order spending 5 USDC
    fokResult, err := orderClient.CreateOrder(ctx, limitless.CreateOrderParams{
        OrderType:  limitless.OrderTypeFOK,
        MarketSlug: "btc-above-100k-march-2025",
        Args: limitless.FOKOrderArgs{
            TokenID:     market.Tokens.Yes,
            Side:        limitless.SideBuy,
            MakerAmount: 5.0,
        },
    })
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("FOK order placed: %+v\n", fokResult.Order)

    // Cancel all orders on this market
    msg, err := orderClient.CancelAll(ctx, "btc-above-100k-march-2025")
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println("Cancelled:", msg)
}
```
