> ## Documentation Index
> Fetch the complete documentation index at: https://pmxt-sync-hosted-docs.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Trading Quickstart

> Place your first hosted trade in 60 seconds — API key, escrow deposit, market order.

From a fresh `pmxt_api_key` to a confirmed position on Polymarket in under a minute. For the full hosted model, see [Hosted trading](/concepts/hosted-trading).

<Info>
  Hosted writes today: **Polymarket**, **Opinion**, and **Limitless**. Other venues are read-only via the hosted catalog; use [self-hosted](/guides/self-hosted) for venue-native trading where the venue exposes writes. Check [Feature Support & Compliance](https://github.com/pmxt-dev/pmxt/blob/main/core/COMPLIANCE.md) for per-venue support.
</Info>

## 1. Get an API key

Go to [pmxt.dev/dashboard](https://pmxt.dev/dashboard), create a key, and copy it. It looks like `pmxt_live_...` and works immediately.

```bash theme={null}
export PMXT_API_KEY="pmxt_live_..."
```

## 2. Install the SDK

<CodeGroup>
  ```bash Python theme={null}
  pip install pmxt
  ```

  ```bash TypeScript theme={null}
  npm install pmxtjs
  ```
</CodeGroup>

## 3. Construct a hosted client

A hosted trading client takes three things: your PMXT API key, the wallet address you'll trade from, and the private key for that wallet (used only to sign EIP-712 messages locally — it is never sent to PMXT). The SDK auto-wraps `private_key` into an `EthAccountSigner` / `EthersSigner` for you.

<CodeGroup>
  ```python Python theme={null}
  import pmxt

  client = pmxt.Polymarket(
      pmxt_api_key="pmxt_live_...",
      wallet_address="0xYourWallet...",
      private_key="0xYourPrivateKey...",
  )
  ```

  ```typescript TypeScript theme={null}
  import { Polymarket } from "pmxtjs";

  const client = new Polymarket({
    pmxtApiKey: "pmxt_live_...",
    walletAddress: "0xYourWallet...",
    privateKey: "0xYourPrivateKey...",
  });
  ```

  ```bash curl theme={null}
  # Trading via curl is possible but tedious — you have to build the
  # EIP-712 payload, sign it locally, and POST it yourself. The SDK
  # does all of this for you. See /guides/signing for the protocol.
  echo "Use an SDK for the quickstart."
  ```
</CodeGroup>

<Note>
  PMXT is non-custodial by construction: the SDK signs locally and your key never leaves your machine. For production, a practical habit is to keep only the float you're actively trading in this wallet. See [Security](/security).
</Note>

## 4. Approve and deposit USDC into escrow

Hosted trades execute against your balance in the non-custodial `PreFundedEscrow` contract. The first time you trade, you need to approve the escrow to pull USDC from your wallet and make an initial deposit. The fastest way is the dashboard.

### Recommended: deposit from the dashboard

Open [pmxt.dev/dashboard](https://pmxt.dev/dashboard), connect the wallet that matches `0xYourWallet`, and use the Deposit flow. Your wallet (MetaMask, Rabby, WalletConnect, etc.) prompts you to sign each transaction — PMXT never sees your private key.

1. Go to [pmxt.dev/dashboard](https://pmxt.dev/dashboard) and connect the same wallet address you passed to the SDK.
2. Click **Deposit** and enter the USDC amount.
3. Approve the USDC allowance in your wallet (one-time per token).
4. Confirm the deposit transaction in your wallet.

<Note>
  Approval and deposit are one-time setup. Subsequent trades just spend from escrow until you withdraw. See [Escrow Lifecycle](/guides/escrow-lifecycle) for the full deposit / withdraw flow.
</Note>

<Accordion title="Advanced: programmatic deposit">
  If you're scripting deposits (CI, treasury automation, custom wallet integrations), `client.escrow` builds **unsigned** transactions you sign and broadcast with your own wallet library (web3, ethers, viem, etc.).

  <CodeGroup>
    ```python Python theme={null}
    # 1. Build an unsigned ERC-20 approval tx for USDC
    approve_tx = client.escrow.approve_tx("usdc")["tx"]
    # Sign and send approve_tx with your wallet library...
    # (escrow builders return {"tx": {...}}; unwrap with ["tx"])

    # 2. Build an unsigned deposit tx for 10 USDC
    deposit_tx = client.escrow.deposit_tx(amount=10.0)["tx"]
    # Sign and send deposit_tx with your wallet library...

    # 3. Confirm the deposit landed
    balances = client.fetch_balance()
    print(f"Escrow USDC: {balances[0].available}")
    ```

    ```typescript TypeScript theme={null}
    // 1. Build an unsigned ERC-20 approval tx for USDC
    const { tx: approveTx } = await client.escrow.approveTx("usdc");
    // Sign and send approveTx with your wallet library...
    // (escrow builders return { tx: {...} }; destructure as shown)

    // 2. Build an unsigned deposit tx for 10 USDC
    const { tx: depositTx } = await client.escrow.depositTx(10);
    // Sign and send depositTx with your wallet library...

    // 3. Confirm the deposit landed
    const balances = await client.fetchBalance();
    console.log(`Escrow USDC: ${balances[0].available}`);
    ```
  </CodeGroup>
</Accordion>

## 5. Find a market and place your first order

`client.fetch_markets` queries the venue's live catalog and returns markets you can trade directly. Pass any returned outcome straight to `create_order` — no UUID lookup required.

<CodeGroup>
  ```python Python theme={null}
  markets = client.fetch_markets({"query": "knicks 2026 nba champion"})
  market = markets[0]
  yes = next(o for o in market.outcomes if o.label.lower() == "yes")

  order = client.create_order(
      outcome=yes,
      side="buy",
      order_type="market",
      amount=5.0,   # market buys are denominated in USDC: spend exactly $5
  )
  print(f"Order {order.id}: {order.status} filled={order.filled}")
  ```

  ```typescript TypeScript theme={null}
  const markets = await client.fetchMarkets({ query: "knicks 2026 nba champion" });
  const market = markets[0];
  const yes = market.outcomes.find((o) => o.label.toLowerCase() === "yes")!;

  const order = await client.createOrder({
    outcome: yes,
    side: "buy",
    type: "market",
    amount: 5, // market buys are denominated in USDC: spend exactly $5
  });
  console.log(`Order ${order.id}: ${order.status} filled=${order.filled}`);
  ```

  ```bash curl theme={null}
  # create_order is a convenience wrapper. The hosted API exposes a
  # build → sign → submit flow. See /guides/signing for the raw protocol.
  echo "Use an SDK for create_order."
  ```
</CodeGroup>

<Note>
  The hosted trading API accepts either the venue-native identifier (returned by `client.fetch_markets`) or a catalog UUID (returned by [Router](/router/overview)) — whichever you have. The SDK picks the right wire field automatically. See [Catalog UUID vs Venue ID](/concepts/catalog-uuid-vs-venue-id) when cross-venue identity matters.
</Note>

<Note>
  **`outcome=` requires a `MarketOutcome` instance**, not a bare dict — passing a raw dict raises `AttributeError`. Use the object you got from `client.fetch_markets()[i].outcomes[j]` (or `router.fetch_markets()[i].outcomes[j]`) as shown above. If you only have string ids, pass them explicitly instead: `client.create_order(market_id="...", outcome_id="...", side="buy", ...)`.
</Note>

<Note>
  **What PMXT abstracts vs what leaks through from the venue.** PMXT unifies the order shape across venues, but a few Polymarket rules pass through as-is. Polymarket enforces **two independent minimums on marketable BUY orders** — a **5-share minimum** AND a \*\*$1 notional minimum** — and the higher of the two binds. At $0.138/share the 5-share rule alone would only require $0.69, but the $1 rule raises the effective minimum to ~~8 shares (~~$1.10); a 5-share buy at that price is rejected by the venue with `invalid amount for a marketable BUY order ($0.69), min size: 1`and PMXT surfaces it as`OrderSizeTooSmall`. Market orders are **budget-capped** (a buy spends exactly `amount`USDC, a sell sells exactly`amount`shares —`slippage\_pct`is ignored). Hosted **limit** orders are supported via`client.create\_order(order\_type="limit", price=..., amount=...)`and the same 5-share and $1 marketable-BUY minimums apply; limit BUY and SELL are supported, and both use`denom="shares"\` in hosted SDK requests.
</Note>

## 6. Verify the fill

Hosted positions appear immediately on `fetch_positions`. The position's `size` is your share count; the remaining USDC sits in `fetch_balance`.

<Note>
  The `id` returned by hosted `create_order` is a **PMXT internal task id**, not a Polymarket (or other venue) order id. Calling Polymarket's own order-lookup with it will return nothing. Use `client.fetch_order(id)` — the hosted SDK knows how to resolve the task and reports the live status (`queued`, `fulfilling`, `fulfilled`, `failed`, `no_fill`). A fresh `create_order` returns `status="queued"` because the venue submit happens asynchronously; poll `fetch_order` (or pass `wait=true`) to get the venue-confirmed outcome.
</Note>

<CodeGroup>
  ```python Python theme={null}
  positions = client.fetch_positions()
  for p in positions:
      print(f"{p.market_id}  {p.outcome_label}  size={p.size}")

  balances = client.fetch_balance()
  print(f"Escrow USDC left: {balances[0].available}")
  ```

  ```typescript TypeScript theme={null}
  const positions = await client.fetchPositions();
  for (const p of positions) {
    console.log(`${p.marketId}  ${p.outcomeLabel}  size=${p.size}`);
  }

  const balances = await client.fetchBalance();
  console.log(`Escrow USDC left: ${balances[0].available}`);
  ```
</CodeGroup>

That's it — you placed a real trade through hosted PMXT. From here:

* [Escrow lifecycle](/guides/escrow-lifecycle) — deposits, withdrawals, the request/claim timelock.
* [Hosted errors](/guides/hosted-errors) — what each error means and how to recover.
* [Signing](/guides/signing) — the EIP-712 protocol underneath `create_order`.
* [Self-hosted](/guides/self-hosted) — when to skip hosted and run pmxt-core yourself.
