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

# Authentication

> API keys, SDK setup, and venue credentials.

## Hosts

PMXT serves two hostnames.

* `api.pmxt.dev` — reads, catalog search via Router, MCP server, venue passthrough (`/api/*`).
* `trade.pmxt.dev` — hosted writes (build / submit / cancel) and hosted account state (orders, positions, balances, trades) via `/v0/trade/*`, `/v0/user/*`, and `/v0/orders/*`.

The same `pmxt_api_key` authenticates against both — no separate credentials.

Reads and writes have different latency and availability profiles; the trading host is the hot path for signed-order submission and is operated independently.

## API key

Every request to `https://api.pmxt.dev` needs a Bearer token. Get one
from [pmxt.dev/dashboard](https://pmxt.dev/dashboard) — it works
immediately.

```http theme={null}
Authorization: Bearer pmxt_live_...
```

`X-Api-Key: pmxt_live_...` also works as a fallback, but Bearer is
canonical and what every SDK sends.

## SDK setup

Set `PMXT_API_KEY` and the SDK automatically routes to the hosted
endpoint. No code changes versus local development.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import os, pmxt
    os.environ["PMXT_API_KEY"] = "pmxt_live_..."

    poly = pmxt.Polymarket()   # -> https://api.pmxt.dev
    ```

    Or pass it directly:

    ```python theme={null}
    import pmxt

    poly = pmxt.Polymarket(pmxt_api_key="pmxt_live_...")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import pmxt from "pmxtjs";
    process.env.PMXT_API_KEY = "pmxt_live_...";

    const poly = new pmxt.Polymarket({});  // -> https://api.pmxt.dev
    ```

    Or pass it directly:

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

    const poly = new pmxt.Polymarket({ pmxtApiKey: "pmxt_live_..." });
    ```
  </Tab>
</Tabs>

Explicit argument takes precedence over the environment variable.

## Venue credentials

### Hosted writes (recommended)

In hosted mode, trade writes use **PMXT's PreFundedEscrow custody** plus a
locally-signed EIP-712 payload. You pass your `pmxt_api_key`, the wallet
address you trade from, and a private key used only for local signing —
the private key never leaves your machine, and PMXT custodies USDC in
the escrow contract on your behalf.

```python theme={null}
import pmxt

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

# One-time: approve + deposit USDC into PreFundedEscrow
deposit_tx = client.escrow.deposit_tx(amount=10.0)
# (sign + broadcast deposit_tx with your wallet library)
```

See [Trading quickstart](/trading-quickstart) for the full 60-second flow
and [Escrow lifecycle](/guides/escrow-lifecycle) for the approve / deposit /
withdraw mechanics. Hosted writes today: Polymarket, Opinion, and Limitless.

### Self-hosted / direct venue credentials (advanced)

When you run [pmxt-core locally](/guides/self-hosted), or when you need
venue-native trading where the venue exposes writes but hosted mode does
not, you pass venue-native
credentials (Polymarket private key, Kalshi RSA, Smarkets session, etc.)
directly:

```python theme={null}
order = poly.create_order(
    outcome=market.yes,
    side="buy",
    order_type="limit",
    price=0.42,
    amount=100,
)
```

PMXT never stores venue credentials. They are forwarded to the venue and
dropped when the call completes.

<Info>
  Some venues (Polymarket, Limitless, Probable, Opinion, Baozi) require
  raw wallet private keys with full fund control. **Use a dedicated
  trading wallet** and read [Security & Credential Handling](/security)
  before passing private keys to PMXT — hosted or self-hosted.
</Info>

## Rotating keys

<Warning>
  Rotate immediately if you suspect a key is exposed. Old keys are revoked
  atomically — in-flight requests with the old key are rejected within 60
  seconds.
</Warning>

1. **Create** a new key from the [dashboard](https://pmxt.dev/dashboard).
2. **Deploy** the new key to your application.
3. **Revoke** the old key once traffic has drained.

All revocations are logged under **Settings > Audit Log**.

## Errors

| Status | Body                                     | Meaning                                   | SDK exception                            |
| ------ | ---------------------------------------- | ----------------------------------------- | ---------------------------------------- |
| `401`  | `{"error": "missing api key"}`           | No `Authorization` header on the request. | `PmxtError` (message: `missing api key`) |
| `401`  | `{"error": "invalid api key"}`           | Key unknown, revoked, or expired.         | `PmxtError` (message: `invalid api key`) |
| `429`  | `{"error": "rate_limit_exceeded", ... }` | See [Plans & Limits](/rate-limits).       | `RateLimitExceeded`                      |

<Note>
  Today the SDKs raise the base `pmxt.errors.PmxtError` for both 401 cases
  — match on the message string. A dedicated `InvalidApiKey` subclass may
  be added in a future SDK release; this doc will be updated when that
  ships.
</Note>

See [API Reference / Errors](/api-reference/errors) for the full error
class hierarchy.
