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

# Set up resources manually

> Create an account, connect an agent, fund a Tempo Testnet wallet, and make your first policy-checked payment. No real funds required.

End-to-end setup on **Tempo Testnet**. By the end you'll have a Conto organization, an AI agent, a funded testnet wallet, two test policies, and a verified onchain payment.

Total time: about 10 minutes. No real funds required.

## What you'll build

<Check>A Conto organization with your account</Check>
<Check>An AI agent connected in Conto</Check>
<Check>A Tempo Testnet wallet funded with pathUSD</Check>
<Check>Spending policies that approve, require approval, or deny payments</Check>
<Check>A verified test payment on Tempo Testnet</Check>

## Why Tempo Testnet?

Tempo Testnet pays transaction fees in `pathUSD` itself, so you don't need a separate gas token. Combined with free faucet funds, it's the fastest way to test the full flow.

| Property | Value                                                              |
| -------- | ------------------------------------------------------------------ |
| Network  | Tempo Testnet                                                      |
| Chain ID | `42431`                                                            |
| Currency | `pathUSD` (TIP-20)                                                 |
| Gas      | Paid in `pathUSD`. No separate gas token.                          |
| Explorer | [`explore.moderato.tempo.xyz`](https://explore.moderato.tempo.xyz) |

Prefer automated setup? Use the [first-payment quickstart](/docs/quickstart/setup). This walkthrough lets you create and inspect each resource yourself.

## Choose Your Key Up Front

Most developers need both of these at different points in the integration:

| Use case                                                                            | Credential                         | Env var             |
| ----------------------------------------------------------------------------------- | ---------------------------------- | ------------------- |
| Create agents, link wallets, assign policies, or manage ownership from your backend | Organization API key (`conto_...`) | `CONTO_ORG_API_KEY` |
| Let the agent call `/api/sdk/*` payment and read endpoints                          | Agent SDK key (`conto_agent_...`)  | `CONTO_API_KEY`     |

<Info>
  If your app provisions agents for end users, create the agent with an org API key first, then hand
  the agent its own SDK key for runtime payment calls.
</Info>

## Step 1. Create your account

1. Visit [conto.finance](https://conto.finance) and sign up with your email and a strong password.
2. Create your **organization**. This is the top-level container for agents, wallets, and policies.

## Step 2. Create and fund a wallet

<Steps>
  <Step title="Create the wallet">
    Sidebar > **Wallets > Create Wallet**.

    | Field        | Value                    |
    | ------------ | ------------------------ |
    | Name         | `Test Operations Wallet` |
    | Custody Mode | `MANAGED` (recommended)  |
    | Chain Type   | `EVM`                    |
    | Chain        | Tempo Testnet (`42431`)  |
  </Step>

  <Step title="Confirm the address">
    Conto assigns an onchain address when the managed wallet is created. The wallet is assigned to
    your Conto organization, while Conto controls signing through secure managed wallet
    infrastructure. You do not receive a separate wallet-provider account or direct key access.
  </Step>

  <Step title="Fund with the faucet">
    On the wallet detail page, click **Faucet**. Free testnet `pathUSD` arrives in seconds.
  </Step>
</Steps>

For other custody modes (`EXTERNAL`, `SMART_CONTRACT`), see [Custody modes](/docs/guides/custody-modes).

## Step 3. Connect an agent

<Steps>
  <Step title="Open Agents">
    Sidebar > **Agents > Connect Agent**.
  </Step>

  <Step title="Fill in details">
    | Field       | Example                      |
    | ----------- | ---------------------------- |
    | Name        | `Test Payment Agent`         |
    | Type        | `CUSTOM` (or your framework) |
    | Description | `Quickstart test agent`      |
  </Step>

  <Step title="Connect">
    Click **Connect Agent**. The agent starts in `ACTIVE` status.
  </Step>
</Steps>

Via API:

If you create agents through the API, active agents must include an owner. First fetch one stable
membership id for your org:

```bash theme={null}
curl https://conto.finance/api/organizations/me/members \
  -H "Authorization: Bearer $CONTO_ORG_API_KEY"
```

Pick `members[].id` for the org member or service account that should own the agent, then create
the agent:

```bash theme={null}
curl -X POST https://conto.finance/api/agents \
  -H "Authorization: Bearer $CONTO_ORG_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Test Payment Agent",
    "agentType": "CUSTOM",
    "description": "Quickstart test agent",
    "ownerMembershipId": "mem_abc123..."
  }'
```

Valid `agentType` values: `OPENAI_ASSISTANT`, `ANTHROPIC_CLAUDE`, `LANGCHAIN`, `AUTOGPT`, `CUSTOM`. Agent statuses: `ACTIVE`, `PAUSED`, `SUSPENDED`, `REVOKED`.

## Step 4. Link the wallet to the agent

<Steps>
  <Step title="Assign the wallet">
    Open the agent detail page. In the **Wallets** section, click **Assign Wallet** and pick the Tempo Testnet wallet.
  </Step>

  <Step title="Set spending limits">
    Recommended for the quickstart:

    | Setting         | Value  |
    | --------------- | ------ |
    | Per Transaction | `50`   |
    | Daily Limit     | `500`  |
    | Weekly Limit    | `2000` |
    | Monthly Limit   | `5000` |

    <Warning>
      Don't use Per Transaction `0` as a kill switch. Wallet-level spend limits treat `0` as
      unlimited. Use a positive limit for a cap, or suspend the agent when you need to block spend.
    </Warning>
  </Step>
</Steps>

Default limits, time windows, and other agent-wallet link defaults are listed on the [Defaults](/docs/reference/defaults) page.

## Step 5. Generate an SDK key

<Steps>
  <Step title="Open SDK Integration">
    On the agent detail page, click the **SDK Integration** tab.
  </Step>

  <Step title="Generate the key">
    Click **Generate New Key**. Name it (e.g. `Testnet Key`). Keep the default `expiresInDays`.
    The default **Standard SDK key** preset covers everything in this guide: it includes
    `payments:request` for policy evaluation and `payments:execute` for Step 8's
    `POST /api/sdk/payments/{requestId}/execute` call. Reserve **Admin SDK keys** for agents that
    also manage agents, wallets, or policies.
  </Step>

  <Step title="Store the key immediately">
    The full key is shown once. Save it to your environment:

    ```bash theme={null}
    export CONTO_API_KEY="conto_agent_your_key_here"
    ```
  </Step>
</Steps>

For scopes and key types (`standard` vs `admin`), see [Authentication](/docs/sdk/authentication).

Verify the setup:

```bash theme={null}
curl https://conto.finance/api/sdk/setup \
  -H "Authorization: Bearer $CONTO_API_KEY"
```

You should see:

* the agent is available for payment calls
* the setup summary includes your Tempo Testnet wallet and balance
* `scopes` includes `payments:request` and `payments:execute` (both are part of the standard
  preset)

## Step 6. Create two test policies

These two policies together produce three different payment outcomes:

### Policy A: spend limit

<Steps>
  <Step title="Create the policy">
    Sidebar > **Policies > New Policy**.

    | Field       | Value                       |
    | ----------- | --------------------------- |
    | Name        | `Test Spend Limit`          |
    | Policy Type | `SPEND_LIMIT`               |
    | Description | Deny transactions over \$15 |
  </Step>

  <Step title="Add the rule">
    | Field     | Value        |
    | --------- | ------------ |
    | Rule Type | `MAX_AMOUNT` |
    | Operator  | `LTE`        |
    | Value     | `15`         |
    | Action    | `ALLOW`      |
  </Step>
</Steps>

### Policy B: approval threshold

<Steps>
  <Step title="Create the policy">
    Sidebar > **Policies > New Policy**.

    | Field       | Value                                       |
    | ----------- | ------------------------------------------- |
    | Name        | `Test Approval Threshold`                   |
    | Policy Type | `APPROVAL_THRESHOLD`                        |
    | Description | Require approval for transactions over \$10 |
  </Step>

  <Step title="Add the rule">
    | Field     | Value                    |
    | --------- | ------------------------ |
    | Rule Type | `REQUIRE_APPROVAL_ABOVE` |
    | Operator  | `GREATER_THAN`           |
    | Value     | `10`                     |
    | Action    | `REQUIRE_APPROVAL`       |
  </Step>
</Steps>

### Assign both to the agent

Open the agent detail page > **Permissions** tab > assign **Test Spend Limit** and **Test Approval Threshold**.

Policies combine with AND logic. The most restrictive outcome wins. Higher priority numbers evaluate first (default priority is `50`).

## Step 7. Run three test transactions

With both policies active you should see three different outcomes:

| Amount | Expected outcome    | Why                                                        |
| ------ | ------------------- | ---------------------------------------------------------- |
| `5`    | `APPROVED`          | Under both thresholds                                      |
| `12`   | `REQUIRES_APPROVAL` | Over the $10 approval threshold, under the $15 spend limit |
| `20`   | `DENIED`            | Over the \$15 spend limit                                  |

Before running the examples, install `curl` and `jq`, then choose a **second Tempo Testnet EVM
address you control** as the recipient. Do not send to the placeholder address printed in this
guide. Set a run ID once and reuse it if you retry a command; it makes each authorization request
idempotent.

```bash theme={null}
export RECIPIENT_ADDRESS="0xYOUR_TEMPO_TESTNET_ADDRESS"
export QUICKSTART_RUN_ID="${QUICKSTART_RUN_ID:-qs-$(date +%s)}" # Reuse it on retries.

if ! [[ "$RECIPIENT_ADDRESS" =~ ^0x[0-9a-fA-F]{40}$ ]]; then
  echo "RECIPIENT_ADDRESS must be a Tempo Testnet EVM address you control" >&2
  exit 1
fi
```

### Test 1. `$5` should be APPROVED

```bash theme={null}
APPROVED_RESPONSE=$(
  jq -n \
    --arg recipient "$RECIPIENT_ADDRESS" \
    --arg idempotencyKey "quickstart-$QUICKSTART_RUN_ID-approved" \
    '{
      amount: 5,
      recipientAddress: $recipient,
      purpose: "Test - under all limits",
      category: "TESTING",
      idempotencyKey: $idempotencyKey
    }' | curl --fail-with-body --silent --show-error --max-time 15 \
  -X POST https://conto.finance/api/sdk/payments/request \
  -H "Authorization: Bearer $CONTO_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @-
)

printf '%s\n' "$APPROVED_RESPONSE" | jq .
```

Response: `"status": "APPROVED"`, `"currency": "pathUSD"`.

### Test 2. `$12` should REQUIRE\_APPROVAL

```bash theme={null}
jq -n \
  --arg recipient "$RECIPIENT_ADDRESS" \
  --arg idempotencyKey "quickstart-$QUICKSTART_RUN_ID-approval" \
  '{
    amount: 12,
    recipientAddress: $recipient,
    purpose: "Test - over approval threshold",
    idempotencyKey: $idempotencyKey
  }' | curl --fail-with-body --silent --show-error --max-time 15 \
  -X POST https://conto.finance/api/sdk/payments/request \
  -H "Authorization: Bearer $CONTO_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- | jq .
```

Response: `"status": "REQUIRES_APPROVAL"` with a customer-facing reason explaining that approval
is needed.

### Test 3. `$20` should be DENIED

```bash theme={null}
jq -n \
  --arg recipient "$RECIPIENT_ADDRESS" \
  --arg idempotencyKey "quickstart-$QUICKSTART_RUN_ID-denied" \
  '{
    amount: 20,
    recipientAddress: $recipient,
    purpose: "Test - over max amount",
    idempotencyKey: $idempotencyKey
  }' | curl --fail-with-body --silent --show-error --max-time 15 \
  -X POST https://conto.finance/api/sdk/payments/request \
  -H "Authorization: Bearer $CONTO_API_KEY" \
  -H "Content-Type: application/json" \
  --data-binary @- | jq .
```

Response: `"status": "DENIED"` with a customer-facing reason explaining that a spending control
blocked the payment.

## Step 8. Execute the approved payment

This step uses the `payments:execute` scope, which your standard SDK key already includes. Validate
the saved response from Test 1 before extracting its ID. Never execute a request whose status is
missing, unknown, `DENIED`, or `REQUIRES_APPROVAL`.

```bash theme={null}
if ! jq -e '.status == "APPROVED" and (.requestId | type == "string" and length > 0)' \
  >/dev/null <<<"$APPROVED_RESPONSE"; then
  echo "Payment was not exactly APPROVED or did not return a requestId; refusing to execute" >&2
  exit 1
fi

REQUEST_ID=$(jq -r '.requestId' <<<"$APPROVED_RESPONSE")
```

Then execute it:

```bash theme={null}
curl --fail-with-body --silent --show-error --max-time 30 \
  -X POST "https://conto.finance/api/sdk/payments/$REQUEST_ID/execute" \
  -H "Authorization: Bearer $CONTO_API_KEY"
```

If execution times out or the connection drops, do not submit a new payment request or blindly
retry execution. Reconcile the saved ID first with `GET /api/sdk/payments/$REQUEST_ID`; its
`transaction` field shows whether the transfer was submitted.

The response includes:

* `txHash`. Onchain transaction hash on Tempo Testnet.
* `explorerUrl`. Link to view on [`explore.moderato.tempo.xyz`](https://explore.moderato.tempo.xyz).

## Step 9. Same flow via the SDK

```typescript theme={null}
import { Conto } from '@conto_finance/sdk';

const conto = new Conto({ apiKey: process.env.CONTO_API_KEY! });

const recipientAddress = process.env.RECIPIENT_ADDRESS;
const runId = process.env.QUICKSTART_RUN_ID;
if (!recipientAddress || !/^0x[0-9a-fA-F]{40}$/.test(recipientAddress) || !runId) {
  throw new Error('Set RECIPIENT_ADDRESS to a Tempo address you control and set QUICKSTART_RUN_ID');
}

// Test 1
const test1 = await conto.payments.request({
  amount: 5,
  recipientAddress,
  purpose: 'Test - under all limits',
  idempotencyKey: `quickstart-${runId}-sdk-approved`,
});
console.log('Test 1:', test1.status); // APPROVED

if (test1.status !== 'APPROVED' || !test1.requestId) {
  throw new Error(`Refusing to execute payment with status ${test1.status}`);
}

const result = await conto.payments.execute(test1.requestId);
console.log('TX hash:', result.receipt?.txHash);
console.log('Explorer:', result.receipt?.explorerUrl);

// Test 2
const test2 = await conto.payments.request({
  amount: 12,
  recipientAddress,
  purpose: 'Test - over approval threshold',
  idempotencyKey: `quickstart-${runId}-sdk-approval`,
});
console.log('Test 2:', test2.status); // REQUIRES_APPROVAL

// Test 3
const test3 = await conto.payments.request({
  amount: 20,
  recipientAddress,
  purpose: 'Test - over max amount',
  idempotencyKey: `quickstart-${runId}-sdk-denied`,
});
console.log('Test 3:', test3.status); // DENIED
```

For one-call `request + execute`, set `autoExecute: true` on the request. It works with any key that has `payments:execute`, which the standard preset includes.

## Verify in the dashboard

After Step 8:

1. Dashboard > **Transactions**. The transaction shows `Confirmed` with the Tempo Testnet chain.
2. Click the explorer link to verify onchain.
3. Dashboard > **Audit Logs**. See the full policy evaluation trail.

<Check>You've verified policy enforcement and made a real onchain payment on Tempo Testnet.</Check>

## Troubleshooting

<AccordionGroup>
  <Accordion title="Expected a block after setting per-transaction limit to 0">
    Wallet-level per-transaction limit `0` means unlimited. Edit the wallet limits on the agent
    detail page and set a positive cap, or suspend the agent if all payments should stop.
  </Accordion>

  <Accordion title="Payment denied but expected REQUIRES_APPROVAL">
    Policies combine with AND logic. If one policy denies while another requires approval, the
    denial wins. Check the **Permissions** tab for every assigned policy.
  </Accordion>

  <Accordion title="INSUFFICIENT_BALANCE">
    The testnet wallet needs funding. Use the **Faucet** button on the wallet detail page.
  </Accordion>

  <Accordion title="AUTH_FAILED">
    Invalid or expired SDK key. Generate a new one from the agent detail page.
  </Accordion>
</AccordionGroup>

## Moving to production

Once the testnet flow works:

1. Create a production wallet on **Tempo Mainnet** (`USDC.e`), **Base** (`USDC`), or **Solana** (`USDC`).
2. Fund it with real stablecoins.
3. Create separate production credentials and confirm the custody model for every funded wallet.
4. Configure and test production policies, approval routes, webhook verification, and monitoring.
5. Complete the [Production Readiness Checklist](/docs/guides/production-readiness) before enabling live funds.

Your application code may stay largely the same, but live operation requires separately reviewed
credentials, custody, policies, approvals, webhooks, monitoring, and incident controls.

## Next steps

<CardGroup cols={2}>
  <Card title="Agent sandbox quickstart" icon="robot" href="/docs/quickstart/agent-sandbox">
    Let an autonomous agent create a test-mode sandbox without human signup
  </Card>

  <Card title="Connect your framework" icon="plug" href="/docs/quickstart/connecting-agents">
    OpenAI, Claude, LangChain, Python integration snippets
  </Card>

  <Card title="SDK payments reference" icon="code" href="/docs/sdk/payments">
    Full method signatures, options, error model
  </Card>

  <Card title="Policy overview" icon="shield" href="/docs/policies/overview">
    Every policy type and rule type
  </Card>

  <Card title="Defaults" icon="gear" href="/docs/reference/defaults">
    Every default value in one place
  </Card>
</CardGroup>
