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

# Quickstart

> Connect a user, read their account, chat with Ask Circuit and confirm what it proposes.

Every call sends `Circuit-Partner-Version: 0.1`. Calls after connecting also send the user's permit as `Authorization: Bearer <permit>`. Build against `https://api.circuit.org` with paper money; see [Test with paper money](https://docs.circuit.org/apps-testing.md).

**1. Add the client**

Download [`circuit.ts`](https://circuit.org/partners/circuit.ts) into your app. It has no dependencies and runs in browsers, Node 22+ and Bun. The curl tabs show the same calls without it.

**2. Connect a user**

Start a connection, open its `url` in a real browser, and wait for the permit. The client generates the key pair, polls, and decrypts the permit for you.

```typescript TypeScript theme={null}
import { circuit, connect } from "./circuit";

const api = "https://api.circuit.org";
const started = await connect("yourapp", api, "https://yourapp.com/connected");
window.open(started.url); // on iOS: ASWebAuthenticationSession
const permit = await started.permit; // an access token for this user: store it securely
const user = circuit(permit, api);
```

```bash curl theme={null}
curl -X POST https://api.circuit.org/partner/connections \
  -H 'Circuit-Partner-Version: 0.1' -H 'Content-Type: application/json' \
  -d '{"app": "yourapp", "recipientPublicKey": "<64 hex characters>", "returnUrl": "https://yourapp.com/connected"}'

# then poll every retryAfterMs until sealedPermit arrives
curl https://api.circuit.org/partner/connections/conn_9c99… \
  -H 'Circuit-Partner-Version: 0.1'
```

```json Response theme={null}
{ "id": "conn_9c9915b3-…", "url": "https://app.circuit.org/?authHandoff=…", "expiresAt": "2026-11-06T15:55:26Z" }
```

The user signs in, picks wallets and approves with their passkey. Circuit then sends them to your `returnUrl`. The permit lasts 30 days.

**3. Read the account**

```typescript TypeScript theme={null}
const account = await user.account();
```

```bash curl theme={null}
curl https://api.circuit.org/partner/account \
  -H 'Circuit-Partner-Version: 0.1' -H 'Authorization: Bearer <permit>'
```

```json Response theme={null}
{
  "expiresAt": "2026-12-06T16:47:51Z",
  "wallets": [{
    "id": "wal_3457", "name": "Main", "address": "0x…", "valueUsd": "1234.50",
    "holdings": [{ "id": "hld_3457:lighter:perp:ETH:", "symbol": "ETH", "network": "lighter", "kind": "perp", "amount": "0.0412", "valueUsd": "145.40" }]
  }],
  "agents": []
}
```

**4. Send a message**

Pick a UUID per conversation and one per message. Reuse the message id if you retry; a retry never acts twice. Then poll the conversation until `retryAfterMs` is null.

```typescript TypeScript theme={null}
const conversationId = crypto.randomUUID();
const sent = await user.send(conversationId, "Long $50 of ETH on Lighter at 3x");
const turn = await user.settled(conversationId, sent.id);
```

```bash curl theme={null}
curl -X POST https://api.circuit.org/partner/messages \
  -H 'Circuit-Partner-Version: 0.1' -H 'Authorization: Bearer <permit>' -H 'Content-Type: application/json' \
  -d '{"conversationId": "<uuid>", "messageId": "<uuid>", "text": "Long $50 of ETH on Lighter at 3x"}'

curl https://api.circuit.org/partner/conversations/<conversationId> \
  -H 'Circuit-Partner-Version: 0.1' -H 'Authorization: Bearer <permit>'
```

```json Response (one turn) theme={null}
{
  "id": "<messageId>", "state": "done", "text": "Long $50 of ETH on Lighter at 3x",
  "message": "Here's a $150 ETH long on Lighter for you to confirm…",
  "actions": [{ "id": "op_721a08fa-…", "title": "Buy 0.0412 ETH on Lighter perp", "state": "review", "message": null, "agentId": null, "decisions": ["confirm", "dismiss"] }]
}
```

**5. Confirm the action**

Offer what `decisions` lists, and nothing else.

```typescript TypeScript theme={null}
for (const action of turn.actions)
  if (action.decisions.includes("confirm")) await user.decide(action.id, "confirm");
```

```bash curl theme={null}
curl -X POST https://api.circuit.org/partner/actions/op_721a08fa-… \
  -H 'Circuit-Partner-Version: 0.1' -H 'Authorization: Bearer <permit>' -H 'Content-Type: application/json' \
  -d '{"decision": "confirm"}'
```

The answer is the action, now `pending` and then `done`. Poll the conversation to follow it.

**6. Run and stop agents**

Start an agent by asking: "Start Funding Fade with \$1,000 of paper money". Ask proposes the start as an action to confirm. Stop it with the controls the agent lists.

```typescript TypeScript theme={null}
const agent = (await user.account()).agents[0];
if (agent.controls.includes("stop")) await user.control(agent.id, "stop");
```

```bash curl theme={null}
curl -X POST https://api.circuit.org/partner/agents/agt_6073 \
  -H 'Circuit-Partner-Version: 0.1' -H 'Authorization: Bearer <permit>' -H 'Content-Type: application/json' \
  -d '{"control": "stop"}'
```

## Next

* [Concepts](https://docs.circuit.org/apps-concepts.md): permits, polling, ids, errors and versions.
* [API reference](https://docs.circuit.org/api-reference/start-connecting-a-user.md): every route and field.
* [Reference client](https://docs.circuit.org/apps-client.md): the client's source and a server-side example.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.