# Python SDK

> The tickwire Python package. Typed sync and async clients for MT4 and MT5 accounts, with idempotent trading, safe retries, resumable streams and webhook verification.

Source: https://tickwire.io/docs/sdk-python/

`tickwire` is our Python package for the Tickwire API. It has typed clients, sync and async, and
works the same for MT4 and MT5 accounts. It needs Python 3.11 or later.

**It isn't on PyPI yet.** We're publishing the package as `tickwire`; until it's there,
`pip install tickwire` won't find it. If you want to use the SDK before then,
[contact us](https://tickwire.io/contact/). Everything it does is a plain HTTP call, so you can also use the
[REST API](https://tickwire.io/docs/reference/) directly with any HTTP client.

## Your first calls in the sandbox

```python
from tickwire import Tickwire, trade_succeeded

# TICKWIRE_SANDBOX_URL and TICKWIRE_API_KEY (your sandbox key) from the environment.
with Tickwire(sandbox=True, actor="quickstart") as tw:
    acc = tw.account(tw.list_accounts()[0]["id"])      # MT4 and MT5 look the same
    print(acc.health()["status"])                      # healthy | stale | disconnected | down
    print(acc.price("EURUSD"))
    r = acc.market_order("EURUSD", 0.01, reason="quickstart")   # Idempotency-Key generated for you
    print(trade_succeeded(r), r["numericCode"])
    print(acc.audit(limit=5))                          # who did what, when, why
```

`sandbox=True` never guesses a host. It reads `sandbox_url=` or `TICKWIRE_SANDBOX_URL`, and raises
`ConfigError` if neither is set. For a live account, pass the URL or set `TICKWIRE_API_URL`. See
[Sandbox](https://tickwire.io/docs/sandbox/) for how to get a sandbox key.

## Async and streaming

`AsyncTickwire` has the same methods (`async with …`, `await …`), plus streams that resume after
a reconnect:

```python
from tickwire import AsyncTickwire

async with AsyncTickwire(sandbox=True) as tw:
    async with tw.account(account_id).stream() as s:
        state = await s.wait_synchronized()
        s.on("positionUpdated", lambda frame, st: print(frame["position"]))
```

The stream re-subscribes from the last sequence number it saw. If it detects a gap, it does a
full resync, so your copy of the account is never silently wrong. See
[Streaming](https://tickwire.io/docs/streaming/).

## What it covers

- **Accounts:** health, account information, positions, orders, deals and history, symbols,
  prices, server time, one-call snapshots, the audit log, and trading.
- **Accounts and webhooks:** accounts and webhooks, including deliveries, resends and secret rotation.
- **Sandbox:** sign-up and sandbox keys.
- **Agent keys, kill switches and the pre-trade decision hook:** the SDK has clients for them
  (`AgentClient` and the owner's admin methods), but the agent API isn't available yet.

Native `/v1` lists are [cursor-paginated](https://tickwire.io/docs/pagination/). `tw.pages(...)` follows the cursor
for you.

## Safety defaults

- **Idempotency.** Every mutation sends an `Idempotency-Key` (yours, or a generated one),
  `X-Actor` and `X-Reason`. Pass `idempotency_key=` so that repeating the same decision is safe
  across restarts. See [Idempotency](https://tickwire.io/docs/idempotency/).
- **Retries only when safe.** Reads retry on transport errors and 408, 429, 502, 503 and 504,
  with backoff and a per-client retry budget. A mutation retries only when the server confirms it
  didn't run it, and always with the same key.
- **`unknown` is never retried.** If the reply to a mutation is lost, the SDK raises
  `OutcomeUnknown` with the idempotency key, so you can check what happened instead of sending
  the order twice.
- **Typed errors.** `NotFound`, `Conflict`, `NotSupportedOnMt4`, `RateLimited`, `ConfigError` and
  others keep the server's [error envelope](https://tickwire.io/docs/errors/) in `.body`. `health()` returns the
  body of a 503, because "down" is an answer, not an exception.
- **Webhooks.** `verify_webhook(secret, headers, body)` checks the HMAC-SHA256 signature and
  rejects replays outside a 5-minute window. See [Webhooks](https://tickwire.io/docs/webhooks/).
- **No secrets in logs.** Keys never appear in `repr()`.

## The CLI

The [`tickwire` command](https://tickwire.io/docs/cli/) is built on this SDK.
