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

# Quickstart

> From API key to your first governed, approved, and receipted action

# Quickstart

This walks through the shortest real path through Arclasp: create an API key, record one governed agent action, approve it from the dashboard, and get back a signed receipt. No policy setup required — a fresh organization's default threshold handles it.

The whole thing takes a few minutes, using only the low-level `arclasp.Chain` / `record_agent_action()` API — no framework adapter required.

## 1. Sign up and create an API key

Sign up at [proofrail.dev](https://proofrail.dev) and open your organization's dashboard. Create an API key from **Settings → API Keys**. Keys are prefixed with `prail_` and shown once at creation — store yours in a secrets manager or `.env` file.

```bash theme={null}
# .env
ARCLASP_API_KEY=prail_your_key_here
```

## 2. Install the SDK

```bash theme={null}
pip install arclasp
```

## 3. Initialize the SDK against the hosted backend

The SDK's `backend_url` defaults to `http://localhost:8000` for local development. To reach hosted Arclasp, pass it explicitly:

```python theme={null}
import os
import arclasp

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    backend_url="https://api.proofrail.dev",
)
```

If you skip `backend_url`, the SDK will try to talk to `localhost:8000` and fail — this is the single most common setup mistake. See [Troubleshooting](/reference/exceptions#hosted-example-accidentally-hitting-localhost).

## 4. Record a governed action

Open a chain and record one action with a payload that deterministically crosses the default approval threshold. A fresh organization's default policy requires human approval when a single action's top-level payload amount (`amount_usd`, `amount`, or `value`) exceeds **\$5,000**. No custom policy setup is needed for this — the default applies as soon as your organization exists.

```python theme={null}
import asyncio
import os

import arclasp
from arclasp.chain import Chain

arclasp.init(
    api_key=os.environ["ARCLASP_API_KEY"],
    backend_url="https://api.proofrail.dev",
)


async def main() -> None:
    async with Chain("first-governed-action") as chain:
        print(f"Chain started: {chain.chain_id}")
        print(f"View it at: https://app.proofrail.dev/dashboard/chains/{chain.chain_id}")

        # $6,000 exceeds the default $5,000 single-action threshold, so this
        # call blocks until a human approves it from the dashboard.
        decision = await chain.record_agent_action(
            agent_name="payment-agent",
            action_type="tool_call",
            action_name="initiate_transfer",
            payload={"amount_usd": 6000, "currency": "USD"},
        )

        print(f"Resolved: policy_decision={decision.policy_decision!r} "
              f"decision_source={decision.decision_source!r}")

    # Chain.__aexit__ has already called POST /v1/chains/{id}/complete —
    # the signed receipt is ready now.
    receipt = await chain.receipt()
    if receipt is not None:
        print(f"Receipt: {receipt.receipt_number}")


asyncio.run(main())
```

Run it:

```bash theme={null}
python first_governed_action.py
```

## 5. Approve it from the dashboard

Once `record_agent_action()` sends the event, the backend flags it as requiring approval (`$6,000 > $5,000`), and the call **blocks** — it polls `GET /v1/chains/{id}/approval-status` roughly every 5 seconds while the chain shows as `pending_approval`.

Leave the terminal running. Open the [Arclasp dashboard](https://app.proofrail.dev/dashboard/approvals), find the pending approval, and approve it. The default local wait timeout is 24 hours, configurable with `default_approval_timeout_hours` — see [Configuration](/reference/configuration).

## 6. Watch the SDK resume automatically

As soon as you approve from the dashboard, the next poll picks up the decision and `record_agent_action()` returns with `policy_decision="allow"` and `decision_source="human_approval"`. Your script continues from where it was blocked — no restart needed.

If you deny the action instead, the call raises `arclasp.ActionDeniedError`. If nobody resolves it within the timeout window, it raises `ChainTimeoutError`. See [Exceptions](/reference/exceptions) for the full picture — this page keeps it to the two outcomes you'll hit most.

## 7. Completion and receipt

When the `async with Chain(...)` block exits, the SDK marks the chain complete on the backend, which generates a signed receipt. That's why `chain.receipt()` is called *after* the `async with` block in the example above — the receipt doesn't exist until the chain has completed.

Two distinct pieces of evidence come out of this flow, and it's worth keeping them separate:

* **Approval certificate** — evidence of the human approval decision itself (who decided, when, and any notes).
* **Chain Record / receipt** — evidence for the completed governed chain as a whole, generated once the chain closes.

## 8. View the Chain Record

Open the chain's detail page in the dashboard (`https://app.proofrail.dev/dashboard/chains/{chain_id}`) to see the full event timeline, the approval decision, and the receipt.

## 9. Public verification (optional)

From the authenticated dashboard, an admin can issue a public verification link for a chain or receipt. That public page exposes only public-safe verification status — no internal token values or private governance data. This is an optional step once you have your first governed action working; it isn't required to complete this quickstart.

## Where to go next

<CardGroup cols={2}>
  <Card title="Chain-level governance" icon="link" href="/concepts/chain-level-governance">
    The concept that makes Arclasp different from per-call governance tools.
  </Card>

  <Card title="Human approval" icon="user-check" href="/guides/human-approval">
    The full approval flow: timeouts, fallback approvers, and denial handling.
  </Card>

  <Card title="MCP adapter" icon="plug" href="/frameworks/mcp">
    Govern MCP server tool calls.
  </Card>

  <Card title="Configuration" icon="gear" href="/reference/configuration">
    Tune thresholds, timeouts, and more.
  </Card>
</CardGroup>

<Note>
  **Trouble running this?** The most common issue is forgetting `backend_url="https://api.proofrail.dev"` — without it the SDK tries `localhost:8000` and every call fails to connect. Also check Python 3.10+ is installed, and that the amount in your payload is a **top-level** key (`amount_usd`, `amount`, or `value`) — a nested payload like `{"financial": {"amount_usd": 6000}}` will not trigger the threshold.
</Note>
