# Quickstart

Create an account, open a conversation, and get your first agent response. This run disables
tools, so it needs no agent wallet or funded balance.

## Before you begin

Obtain your deployment's API base URL, a partner API key, and a valid end-user access token
from the configured identity provider. Fin does not issue human login tokens. Your deployment
also needs model access and available execution budget.

These examples use Bash, `curl`, `jq` and `uuidgen`. Set the values in a trusted terminal or
backend; keep the partner key out of browser code. Replace the placeholder URL with your API
origin, without a trailing `/v1`.

```bash
FIN_BASE_URL=https://api.example.test
FIN_API_KEY=your_partner_key
FIN_USER_TOKEN=your_user_access_token
FIN_AUTH=(-H "X-Api-Key: $FIN_API_KEY" -H "Authorization: Bearer $FIN_USER_TOKEN")
```

See [Authentication](/authentication) for how the two credentials work together.

## 1. Provision the user

[`users.ensure`](/api-reference/users/ensure) creates the verified identity's Fin account if
needed, or returns the existing account. Save its `userId` for subsequent paths; it is not the
identity provider's subject.

```bash
FIN_USER_ID=$(curl --fail-with-body -sS -X POST "$FIN_BASE_URL/v1/users" \
  "${FIN_AUTH[@]}" -H 'Content-Type: application/json' -d '{}' | jq -er '.userId')
```

## 2. Open a conversation

[`conversations.create`](/api-reference/conversations/create) opens a conversation and returns `201`
with its id. Save and reuse that id to continue the same thread; create another conversation
when your application needs a separate one. Fin does not designate a special main conversation.

```bash
FIN_CONVERSATION_ID=$(curl --fail-with-body -sS \
  -X POST "$FIN_BASE_URL/v1/users/$FIN_USER_ID/conversations" \
  "${FIN_AUTH[@]}" -H 'Content-Type: application/json' -d '{}' | jq -er '.id')
```

## 3. Start a run

Generate one `runId` for this instruction and retain it. Reuse the same id if you need to retry
this start after a timeout. Generate a new id for a new instruction.

```bash
FIN_RUN_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')
curl --fail-with-body -sS \
  -X POST "$FIN_BASE_URL/v1/users/$FIN_USER_ID/agent-runs" \
  "${FIN_AUTH[@]}" -H 'Content-Type: application/json' \
  -d "$(jq -n --arg runId "$FIN_RUN_ID" --arg conversationId "$FIN_CONVERSATION_ID" \
    '{conversationId: $conversationId, text: "Say hello in one sentence.", runId: $runId, profile: {tools: []}}')"
```

A successful response is `202` with the accepted `runId`. It confirms admission, not completion.
The explicit empty `profile.tools` list prevents tool calls. Omitting that list allows the
deployment's registered tools, subject to policy and consent.

## 4. Follow the response

Open the conversation stream. It replays the journal, so opening it after the start response
does not lose recorded events.

```bash
curl --fail-with-body -sSN \
  "$FIN_BASE_URL/v1/users/$FIN_USER_ID/conversations/$FIN_CONVERSATION_ID/stream?cursor=0" \
  "${FIN_AUTH[@]}" -H 'Accept: text/event-stream'
```

Show `agent.text_delta` as temporary text. Use durable `agent.entry` for the saved reply and
`run.ended` for the recorded outcome. The stream stays open for future work; press Ctrl-C to
close this terminal connection. See [Streaming and events](/streaming) for reconnect handling.

You can also read a run's state without holding a connection open:

```bash
curl --fail-with-body -sS \
  "$FIN_BASE_URL/v1/users/$FIN_USER_ID/agent-runs/$FIN_RUN_ID" \
  "${FIN_AUTH[@]}"
```

`status` reports `running`, `completed`, `failed`, `aborted` or `paused`. Read `response.text`
for the retained public assistant answer and `response.completeness` for a complete or partial
ending. `response` is null until an answer is recorded. `output` separately carries a structured
result when the run requested a `profile.outputContract`; `output: null` does not mean a text
response failed.

## When you enable tools

An action needing consent can open an approval and pause the run. `approval.opened` announces
it, and the run's `pendingApprovals` lists undecided approvals. Fetch
[`approvals.get`](/api-reference/approvals/get) for the persisted tool input, fingerprint,
summary and authorization contract. Show the exact assets, amounts, destinations, limits and
validity before asking the user to decide. A friendly summary alone is not the consent payload.

For an approval opened by a run, call
[`approvals.approve`](/api-reference/approvals/approve) or
[`approvals.deny`](/api-reference/approvals/deny) only after that user decision. Successful
decisions resume work automatically in the same conversation; do not send a second start.

Keep following the conversation after `approval.decided`, or poll the same run id until its
status is `completed`, `failed` or `aborted`. Approval resume does not emit another `run.started`;
the public run keeps the same id and admitted input. A `run.ended` frame with `status: "paused"`
is not terminal. If its pending approval expires, Fin records Stop and ends the run as aborted.

If resuming cannot be admitted, the decision is not recorded and the approval remains pending.
If it expired or was already decided, handle `409 approval_not_pending` by refreshing state.
An approved or consumed approval does not establish settlement. Read financial operations for
the exact request, consent, execution plan and receipts:

```bash
curl --fail-with-body -sS \
  "$FIN_BASE_URL/v1/users/$FIN_USER_ID/financial-operations?runId=$FIN_RUN_ID" \
  "${FIN_AUTH[@]}"
```

### Direct withdrawals

Withdrawals use a separate review and confirmation flow. Review the terms returned by
[`wallets.prepareWithdrawal`](/api-reference/wallets/prepare-withdrawal), then pass its
`approvalId` and unchanged `fingerprint` to
[`wallets.confirmWithdrawal`](/api-reference/wallets/confirm-withdrawal). Do not send a
withdrawal approval to the generic approval endpoint. Retain its `operationId` to read the
result; a direct withdrawal has no conversation or agent run.

## Continue building

- [Core concepts](/concepts): resource ownership, lifecycle and consent.
- [Streaming and events](/streaming): durable history and reconnection.
- [Financial operations](/financial-operations): consent, settlement and uncertain results.
- [Errors](/errors): machine-readable refusals and retry handling.
- [Docs for agents](/agents): Markdown exports and the documentation MCP server.
