# How Fin works

Fin separates the person asking for work, the conversation that holds its history, the agent
run that carries out an instruction, and any financial operation it requests. Each has its own
identity and lifecycle, so your application can read the facts it needs directly.

## Users and credentials

A **user** is a Fin account mapped to a verified identity. Call
[`users.ensure`](/api-reference/users/ensure) with your partner key and the user's valid access
token before making account-dependent requests. It creates the account once and returns the
same account on later calls.

Use the returned `userId` in API paths. This is Fin's internal UUID, distinct from the identity
provider's `subject`; do not substitute a wallet address or decoded JWT subject.

| Credential | Identifies | Held by |
| --- | --- | --- |
| `X-Api-Key` | Your integration | Your backend |
| `Authorization: Bearer <access token>` | The end user | Forwarded by your backend |

Every `/v1` request needs both. A partner key alone cannot act for a user. A path naming a
different Fin user returns `403 subject_mismatch`. A verified identity without a provisioned
account can call `users.ensure`; other account-dependent requests return
`412 account_not_provisioned`. Provisioning never makes an invalid credential valid or
re-enables a disabled account. See [Authentication](/authentication).

## Conversations and agent runs

A **conversation** holds messages, events, approvals and files. Use
[`conversations.create`](/api-reference/conversations/create) to open one. Your application
chooses which conversation to show and stores its id; Fin does not designate a special main
conversation. Reuse that id for the same thread, or create another for separate work.

An **agent run** carries out an instruction inside that conversation.
[`runs.start`](/api-reference/agent-runs/runs-start) accepts `conversationId`, instruction text,
an optional execution profile and an optional client-chosen `runId`. It returns `202` when
work is accepted; it does not wait for completion.

| Run status | Client behavior |
| --- | --- |
| `running` | Continue showing progress. |
| `completed` | Read the public assistant response or requested structured output. |
| `failed` | Show the failure and inspect recorded details. |
| `aborted` | Show that this work was stopped, including when a pending approval expired. |
| `paused` | Read the approval state; the run awaits a decision and is not terminal. |

The public run keeps the same id, input and admitted profile across approvals and
continuations. A paused execution keeps the conversation reserved but releases its user
execution capacity. An approval decision must pass admission again before work continues.
Internal continuation segments do not create new public runs.

Read [`runs.get`](/api-reference/agent-runs/runs-get) for the original request, current status,
pending approvals and retained public result. Its `response` contains the full assistant text
and whether it is complete or partial. Its `output` separately carries a structured result
when the admitted profile requested one. You do not need to reconstruct the journal to read
the result. List runs with `runs.list`, or stop the stable run id with `runs.abort`, including
while it is paused.

A decision emits `approval.decided`, with no new `run.started` event. Keep following the
conversation for tool results, assistant replies and the eventual `run.ended`, or keep polling
the same run id. A `run.ended` event with `status: "paused"` ends an execution segment; it does
not end the public run.

Starting unrelated work while a conversation is held returns `409 run_active`. Supply a
client-chosen `runId` and reuse it for retries of the same start request. Replaying that id
cannot replace its admitted instruction or profile.

## Financial operations

A **financial operation** records one exact request, its consent, frozen execution plan and
settlement evidence. An agent-proposed operation links to its actual conversation, stable run
and tool call. A direct withdrawal belongs to the user and has no conversation or agent run;
its approval belongs to that financial operation.

Read [`financialOperations.get`](/api-reference/financial-operations/financial-operations-get)
for the operation's request, execution legs and complete public receipts. An accepted command
or a completed agent run does not establish that funds settled. See
[Financial operations](/financial-operations) for the lifecycle and uncertain outcomes.

## Journal and stream

The **journal** is the conversation's durable history. The **stream** replays that history and
then delivers new events, including temporary text deltas for a responsive UI. Use durable
events as the source of truth. Read [Streaming and events](/streaming) for replay and reconnects.

## Approvals and consent

An approval describes one action the user may accept or decline. Its status starts as
`pending`, then becomes `approved`, `denied` or `expired`.
[`approvals.get`](/api-reference/approvals/get) returns the persisted input, fingerprint,
summary, authorization contract and decision state. Show those exact terms before sending a
decision; a friendly summary alone is not the consent payload.

| Path | Review | Decision |
| --- | --- | --- |
| A tool call during a run | Exact terms from `approvals.get`; `approval.opened` announces the review | `approvals.approve` or `approvals.deny` |
| A direct withdrawal | Terms from `wallets.prepareWithdrawal` | `wallets.confirmWithdrawal` with its `approvalId` and unchanged `fingerprint` |

The generic approval endpoint does not execute a prepared withdrawal. `consumedAt` and
`approval.consumed` record permission being spent to authorize execution; the action can
still fail afterward. Read the financial operation's outcome and receipts before reporting
settlement. Direct withdrawals have no conversation journal.

An automation can use a previously approved, persisted authorization contract within its exact
bounds, without a fresh approval for every authorized occurrence. A saved instruction or
schedule on its own grants no permission to move funds.

## Agent wallet and budget

The **agent wallet** is separate from the human's connected wallet. Fin manages its backend
credentials. [`wallets.ensure`](/api-reference/wallets/ensure) creates or reconnects it;
[`wallets.get`](/api-reference/wallets/get) only reads it. Provisioning a user does not provision
or fund the wallet. Availability depends on the deployment's configured provider.

The **budget** tracks execution spend and reservations.
[`budgets.headroom`](/api-reference/budgets/headroom) reports day and month limits, reserved
spend, recorded spend and any freeze. It is separate from token balances in the agent wallet.

## Automations

An **automation** starts work on a schedule or a supported event. Its runs use the same
conversation, journal, policy and consent boundaries as interactive work. Your integration can
inspect and control existing automations through the API. Authoring and financial consent are
part of the agent's reviewed tool flow; a run request is not a standing authorization.

Continue with [Your first run](/quickstart).
