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

# Bank accounts: give your agent real banking rails

> Open a US bank account for a managed Laso account, retrieve its routing and account numbers, and move money between dollars and USDC. Your agent can drive the whole setup except identity verification.

A managed Laso account can have real banking rails attached to it: a **US bank account that receives dollars** and turns them into USDC in the managed wallet, and a **crypto address that pays dollars out** to a bank account. Your agent can open both, and retrieve the resulting bank details, through ordinary authenticated calls.

One step is deliberately not automatable. Identity verification has to be completed by the person who owns the account. Everything around it, including the rest of the bank application, is something your agent can do on its own.

<Info>
  These calls are Firebase callables at `https://laso.finance/<name>`,
  authorized with the `id_token` from sign-in. Arguments are wrapped in a `data`
  object and replies in a `result` object, the same convention as the [managed
  wallet](/guides/managed-agent-wallet). The examples write the token as
  `$LASO_ID_TOKEN`; export it from your saved credentials as shown in the
  [skill's session-start recipe](https://laso.finance/SKILL.md).
</Info>

## The two account types

<CardGroup cols={2}>
  <Card title="On-ramp: dollars in" icon="building-columns">
    A virtual US bank account with real ACH and wire details. Dollars sent to it
    are converted and delivered as USDC to the managed wallet. Use it to get
    paid, or to fund the agent from a normal bank transfer.
  </Card>

  <Card title="Off-ramp: dollars out" icon="arrow-right-arrow-left">
    A Solana deposit address. USDC sent to it is paid out automatically to a
    bank account you registered beforehand. Use it to pay someone in dollars.
  </Card>
</CardGroup>

## Step 1: open the banking profile

```bash theme={null}
curl https://laso.finance/createBankingProfile \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"usr_..."}}'
```

If the owner has not verified their identity yet, this returns a link rather than a profile:

```json theme={null}
{ "result": { "kycRequired": true, "kycUrl": "https://..." } }
```

<Warning>
  **This is the one step your agent cannot do.** Give `kycUrl` to your human,
  wait for them to finish, then call again. Never attempt to complete an
  identity check on someone else's behalf.
</Warning>

Once they have verified, the same call returns `profileId`, `applicationStatus`, and an `applicationUrl`. Identity carries over automatically, so what remains is a short set of non-identity questions.

## Step 2: complete the application

Your agent can answer the remaining questions itself. Start by reading what is outstanding:

```bash theme={null}
curl https://laso.finance/getBankingApplication \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"usr_..."}}'
```

```json theme={null}
{
  "result": {
    "applicationId": "...",
    "applicationStatus": "in_progress",
    "ready": false,
    "missingFields": ["ssn"],
    "hostedOnly": false
  }
}
```

If `hostedOnly` is `true`, this particular application can only be finished on the partner's own page. Give the human `applicationUrl` and skip ahead to step 3.

Otherwise submit the details:

```bash theme={null}
curl https://laso.finance/updateBankingApplicationDetails \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{
        "userId":"usr_...",
        "firstName":"Jane","lastName":"Doe",
        "dateOfBirth":"1990-04-17",
        "nationalities":["US"],
        "emailAddress":"jane@example.com",
        "address":{"street1":"1 Main St","city":"Austin","region":"TX","postal_code":"78701","country":"US"},
        "employmentStatus":"employed",
        "purposeOfAccount":["sending_and_receiving_payments"],
        "sourceOfWealth":["employment"],
        "ssn":"123456789"
      }}'
```

| Field              | Rule                                                                                                                                                                                                                                                               |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `dateOfBirth`      | ISO `YYYY-MM-DD`. The person must be 18 or older.                                                                                                                                                                                                                  |
| `nationalities`    | Non-empty array of ISO 3166-1 alpha-2 codes, e.g. `["US"]`.                                                                                                                                                                                                        |
| `employmentStatus` | `employed`, `self_employed`, `unemployed`, `student`, `retired`.                                                                                                                                                                                                   |
| `purposeOfAccount` | Non-empty array: `investing`, `sending_and_receiving_payments`, `storage_of_funds_or_digital_assets`, `making_online_payments`, `trading_on_other_platforms`.                                                                                                      |
| `sourceOfWealth`   | Non-empty array: `investments`, `employment`, `court_settlement`, `lottery_winnings`, `retirement_income`, `savings`, `sale_of_assets`, `family_funds`, `gambling_winnings`, `gift`, `inheritance`, `insurance_claim`, `loan`, `redundancy_severance`, `benefits`. |
| `ssn`              | Required for US persons. Nine digits, no hyphens. Reported in `missingFields` when needed.                                                                                                                                                                         |

<Warning>
  These are the account owner's real personal details on a real bank
  application. Send only values the owner actually gave you. Do not invent,
  guess, or infer them: a wrong answer is a compliance problem for your human,
  not a retryable error.
</Warning>

Then submit for approval:

```bash theme={null}
curl https://laso.finance/submitBankingApplication \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"usr_..."}}'
```

The required legal attestations (e-sign, terms of service, privacy policy, funds transfer agreement) are accepted on the owner's behalf as part of this call, so only make it once they have agreed to those terms. Retrying is safe: attestations already recorded are not sent again.

Poll `getBankingProfileStatus` with the same body until `applicationStatus` shows approval.

## Step 3: open the account

For an on-ramp:

```bash theme={null}
curl https://laso.finance/createBankingAccount \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"usr_...","accountType":"onramp"}}'
```

For an off-ramp, first register who gets paid, then point the account at them:

```bash theme={null}
# 1. The person or company being paid. `address` is required for a bank account.
curl .../createBankingRecipient -d '{"data":{"userId":"usr_...","name":"Jane Doe","address":{"street1":"1 Main St","street2":"Apt 2","city":"Austin","region":"TX","postal_code":"78701","country":"US"}}}'

# 2. Their bank account, returns destinationId. `nickname` is optional and the
#    only field that can be edited later.
curl .../addBankingDestination -d '{"data":{"userId":"usr_...","recipientId":"...","nickname":"Rent account","destination":{"destination_type":"fiat_us","name":"Jane checking","aba_routing_number":"021000021","account_number":"123456789","account_type":"checking","account_holder_name":"Jane Doe","bank_name":"Chase"}}}'

# 3. The off-ramp account
curl .../createBankingAccount -d '{"data":{"userId":"usr_...","accountType":"offramp","fiatDestinationId":"..."}}'
```

<Warning>
  **A recipient needs an `address` before a bank account can be attached to it.**
  That is the postal address of whoever is being paid, not the bank's address:
  `street1`, optional `street2`, `city`, `region`, `postal_code`, `country`. A
  crypto destination does not need one; `fiat_us` and `fiat_iban` do, and step 2
  fails with `failed-precondition` without it.

  Already created a recipient without an address? Pass `recipientAddress` to
  `addBankingDestination` and it sets the address before attaching the account,
  so you do not have to create a second recipient.
</Warning>

Use only the address and bank details your human actually gave you. Do not guess an address to get past the requirement.

`createBankingAccount` is idempotent. Calling it again returns the account that already exists rather than opening a second one.

### Renaming and deleting recipients

A destination's `nickname` is the only editable field. Set or change it at any time:

```bash theme={null}
curl .../updateBankingDestination -d '{"data":{"userId":"usr_...","destinationId":"...","nickname":"Rent account"}}'
```

An empty string clears the nickname; 40 characters max. `GET /bank-recipients` and the dashboard both show it.

If any bank detail is wrong, delete the recipient and create a new one:

```bash theme={null}
curl .../deleteBankingRecipient -d '{"data":{"userId":"usr_...","recipientId":"..."}}'
```

<Warning>
  Deleting a recipient is irreversible and cascades: its destinations are
  removed, and any off-ramp account paying out to them is closed, including its
  USDC deposit address. Confirm with your human before deleting. Your human can
  also manage recipients on their dashboard; both surfaces use these same
  calls, so changes are visible to both of you.
</Warning>

<Tip>
  **To actually pay someone, you only need steps 1 and 2 of the off-ramp.** Once
  a destination exists, [`GET
      /send-bank-payment`](/guides/send-bank-payment) sends dollars to it over
  x402 in a single call and opens the off-ramp account for you. Create the
  off-ramp account yourself only when you want the deposit address to hand to
  something else.
</Tip>

## Step 4: retrieve your bank details

To read the details back at any time, without creating anything:

```bash theme={null}
curl https://laso.finance/listBankingAccounts \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"data":{"userId":"usr_..."}}'
```

Each entry carries `accountId`, `accountType`, and `status`, plus whichever side applies:

* **On-ramp**: `bankAccount` with `account_holder_name`, `account_number`, `aba_routing_number`, `bank_name`, `bank_address`, and `capabilities` such as `["ach","fedwire"]`. These are the details to give whoever is paying.
* **Off-ramp**: the `fiatDestinationId` it pays out to, and `nickname` when your human has named that destination. The off-ramp's internal funding address is deliberately not returned. To pay a destination, call `GET /send-bank-payment`, which opens the off-ramp and handles the funding leg for you.

<Tip>
  When an entry has a `nickname`, lead with it. Your human picked that label, so
  it is how they think of the account: say "Rent account" rather than "off-ramp
  `acct_9f2c...`", and name it in any confirmation before you move money. Keep
  the bank name, last four digits, or `accountId` as the secondary detail that
  tells two similar accounts apart, and fall back to `accountType` and the bank
  details only when there is no nickname.
</Tip>

<Warning>
  These are real bank details. Share them only with people who are meant to pay
  the account, and treat the account number like a credential.
</Warning>

## Following the money

Every ramp transaction is mirrored as it settles, so you can follow one without polling the partner:

```bash theme={null}
curl .../listBankingTransactions -d '{"data":{"userId":"usr_..."}}'
curl .../getBankingTransaction  -d '{"data":{"userId":"usr_...","transactionId":"..."}}'
```

A transaction reports `status` (`pending`, then `completed`, `failed`, or `cancelled`), `direction` (`onramp` or `offramp`), `amount` with `amountAsset`, `sendAmount` with `sendAsset`, and `txHash` once it settles on-chain. Your human is notified automatically at each meaningful step: profile creation, application submission, document review, account provisioning, transfers, payouts, and terminal transaction states.

To receive those same events yourself instead of polling, register a webhook with `POST /register-webhook`: every notification is then also POSTed to your URL with a Standard Webhooks signature. See [receiving notifications by webhook](/guides/agent-webhooks).

<Note>
  A fiat on-ramp settles in two stages. The bank transfer clears first, and the
  USDC arrives in the managed wallet minutes to hours later. Both stages show up
  on your human's dashboard, so a gap between "bank transfer complete" and the
  wallet balance moving is expected rather than an error.
</Note>

## What your agent can and cannot do

| Step                                                        | Agent                      | Human                                     |
| ----------------------------------------------------------- | -------------------------- | ----------------------------------------- |
| Open the banking profile                                    | Yes                        |                                           |
| Identity verification                                       |                            | **Required.** Agent passes `kycUrl` along |
| Read application requirements                               | Yes                        |                                           |
| Submit application details                                  | Yes                        |                                           |
| Accept legal attestations                                   | Yes, on the owner's behalf | Must have agreed to the terms             |
| Open on-ramp / off-ramp account                             | Yes                        |                                           |
| Retrieve bank details                                       | Yes                        |                                           |
| Register recipients, send transfers                         | Yes                        |                                           |
| [Send dollars to a bank account](/guides/send-bank-payment) | Yes                        |                                           |
