# Example projects

> Starter templates to copy. Quickstarts in Python and TypeScript, webhook receivers, a pre-trade guard and an AI assistant over MCP. Sandbox only, MIT licensed.

Source: https://tickwire.io/docs/guides/examples/

We've written small example projects you can copy. Each one has its own README, an MIT
license, and tests that run offline against mocks. They aren't published yet; until they are,
[contact us](https://tickwire.io/contact/) if you'd like one. The runnable parts
target the [sandbox](https://tickwire.io/docs/sandbox/) only. The quickstarts refuse any key that isn't a sandbox
key (`twsk_…`), and nothing has a live host built in.

| Directory | What it shows |
|---|---|
| `examples/python-quickstart` | Create a sandbox account, read it, and place one idempotent order with a reason. It handles `applied`, `rejected`, `held` and `unknown`, and never retries `unknown` |
| `examples/typescript-quickstart` | The same with the TypeScript SDK |
| `examples/webhook-receiver-python` | A FastAPI receiver: verify [Standard Webhooks](https://tickwire.io/docs/webhooks/) signatures, reject stale timestamps, de-duplicate by event id |
| `examples/webhook-receiver-node` | The same with Express |
| `examples/pretrade-guard` | A minimal service on the pre-trade decision hook. It verifies Tickwire's signature, answers a signed `allow`, `deny` or `hold`, and releases holds |
| `examples/ai-agent-mcp` | Connect an AI assistant to the Tickwire MCP server with a read-only or scoped agent key |

> **Tickwire ships no trading rules.** The guard's rule (deny orders above a size, hold mid-size
> ones for a person) is only an example of the moving parts. The rules you enforce are yours.

## Try each outcome

The quickstarts take a [magic login](https://tickwire.io/docs/sandbox/#magic-logins), so you can see every outcome
without a broker:

```bash
python quickstart.py --reason "normal fill"         --login 1000   # applied
python quickstart.py --reason "reply lost, filled"  --login 1031   # applied
python quickstart.py --reason "reply lost, no fill" --login 1032   # unknown: check before acting
python quickstart.py --reason "no money"            --login 1019   # rejected
```

`unknown` means the order **may** have executed. The examples print the open positions and the
idempotency key, and stop. Re-running with the same key returns the recorded answer and never
fills twice. A retry with a new key could open a second position. See
[Idempotency](https://tickwire.io/docs/idempotency/).

## Before you ship one

- The webhook receivers keep seen event ids in memory. In production, put a unique key on the
  event id in your database.
- The guard keeps no state and has no login. A real guard product needs both.
- The SDKs aren't on PyPI or npm yet. See the [Python SDK](https://tickwire.io/docs/sdk-python/) page. AI apps
  don't need a package: they connect to Tickwire's hosted MCP address (see
  [AI agents](https://tickwire.io/ai-agents/#connect)).
