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

# Use a reloadable card with your AI agent

> Link the card issuer once, create reusable cards against the account holder's balance, top it up from Base, Solana, or the Laso account balance, read spend history, and withdraw unspent funds.

The reloadable card is the Laso card an agent keeps. One card serves many purchases: the account holder's balance sits with the card issuer, the agent creates cards against it, and either of them tops the balance up when it runs low. Use it for recurring spend such as ad platforms, subscriptions, and listing fees. For a one-off purchase where nothing should be left over, the non-reloadable [USA prepaid card](https://docs.laso.finance/guides/usa-prepaid-card.md) or [international prepaid card](https://docs.laso.finance/guides/international-prepaid-card.md) is simpler.

Creating a card is free, and topping up adds no fee: the full amount lands on the balance.

## Tell your agent

```
Use my Laso Finance reloadable card for this. Check
https://laso.finance/get-card-data?card_type=Reloadable for an open card
whose balance covers the total. If there is none, top up the balance with
https://laso.finance/fund-card-balance and create one with
POST https://laso.finance/create-reloadable-card. If the card number needs
my approval, tell me to check my email, then retry with the approval_id.
Enter the billing address exactly as returned.
```

## What the account holder sets up

Three steps belong to the human, once per account. An agent can report where each one stands and hand the human the right link, but it cannot complete them.

1. **Laso identity verification.** This is the one card product that requires it. `GET /get-kyc-status` reports whether the holder has completed it, and `GET /get-kyc-link` returns the link to hand them. The two non-reloadable cards read no verification status at order time.
2. **Linking the card issuer.** The issuer sends the holder a one-time code, which they enter in your interface. See [Linking the card issuer](#linking-the-card-issuer) below.
3. **Accepting the issuer's terms and sharing their verification with it.** The issuer gates card creation on the holder's Laso verification being shared with it, and on the holder accepting its terms. This happens in the dashboard at `https://laso.finance/agent/dashboard/verified/card`, and may ask the holder to type details their verification did not capture. There is no API route for it, by design: identity forms are completed by the human. If card creation keeps failing after the issuer is linked, send the holder to that page.

## Lifecycle

```
Holder sets up        Open                      Topped up            Closed
───────────────►  ──────────────────►   ─────────────────►  ──────────►
 Link issuer          Spendable, reusable       Funds added           No longer
 (human's code)       /get-card-data            Balance goes up       spendable
                      card_type=Reloadable      (no new card needed)
```

The key difference from non-reloadable cards: **one card serves many purchases.** A `multi_use` card (`reusable: true`) stays open across charges until its spend limit is consumed, and the holder can top it up rather than issuing a new card each time. If a holder has a reloadable card, prefer it over ordering a fresh single-load card per checkout.

## Linking the card issuer

The link is a one-time code the card issuer sends to the account holder. **The account holder, never the agent, receives and enters it.** Send your human to their own inbox and have them type the code into your interface. Never try to read their email or messages yourself.

1. `GET /get-card-issuer-status` reports `not_started`, `code_sent`, `linked`, or `kyc_required` (with a `kyc_url` for the human; linking requires Laso identity verification).
2. `POST /start-card-issuer-link` sends the code. An account with an email on file gets it there and sends an empty body; an account with no email sends exactly one of `email` or `phone`. The response names the destination masked, as `sent_to`.
3. `POST /verify-card-issuer-link` with `{"code": "123456", "consent_accepted": true}` completes it. Show the account holder the card issuer's connection disclosure next to the code input before sending `consent_accepted`.

```bash theme={null}
curl -X POST "https://laso.finance/verify-card-issuer-link" \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"code": "123456", "consent_accepted": true}'
```

Codes last 10 minutes and allow 5 wrong entries (`400 invalid_code` with `attempts_left`, then `429 too_many_attempts`). At most 5 codes can be sent per account per hour (`429 rate_limited` with `Retry-After`). Both routes take an `Idempotency-Key`, and both answer `status: "linked"` when the account is already linked, so calling twice is safe.

### Unlinking

`POST /disconnect-card-issuer` removes the link, the same as the disconnect button in the dashboard. The card balance stays with the card issuer, but every reloadable card route and [saved card purchases](https://docs.laso.finance/guides/saved-card-purchases.md) stop working until the holder links again with a fresh code. Confirm with the account holder before calling it.

## Topping up

You can top the balance up yourself. The simplest way is `GET /fund-card-balance?amount=X`, a paid route that loads the balance directly: pay from Base or Solana and Laso bridges the payment to the holder's deposit address at the card issuer, so a managed agent wallet holding USDC on Solana can fund a card without any chain juggling. The price is exactly the amount loaded. If the account already holds USDC in its Laso account balance (for example, a paid request that could not be fulfilled), `POST /fund-card-from-account-balance` with `{"amount": 25}` loads it from there for free, debiting exactly the amount loaded. To move the USDC yourself instead, `GET /get-card-deposit-address` returns the holder's own deposit address at the card issuer, and USDC on Base sent there credits their balance. The holder can also pay in with Apple or Google Pay in the dashboard, which settles against their own payment method. Either way, top up rather than ordering a replacement non-reloadable card.

**Base only, if you send it yourself.** The deposit address takes USDC on Base, and USDC sent on another chain is unrecoverable. A Laso managed agent wallet holds USDC on **Solana**, so do not transfer straight from one to that address. Use `GET /fund-card-balance` instead, which bridges for you. Deposits usually confirm within a couple of minutes; poll `GET /get-card-deposit-address` until `balance` reflects the deposit, then create the card.

> [!TIP]
>
> For an agent that tops up its own card from what it earns, see [Self-funding
> PPC agent](https://docs.laso.finance/how-we-use/self-funding-ppc-agent.md).

## Creating a card

Once the holder has linked their card issuer account, you create cards yourself against a funded balance (see [Topping up](#topping-up) to fund it):

```bash theme={null}
curl -X POST "https://laso.finance/create-reloadable-card" \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"usd_amount": 25}'
```

This is free, with no x402 payment: the card draws on the holder's own balance rather than anything Laso fronts. Cards are reusable by default; pass `"reusable": false` for one that closes after its first approved charge.

A `402` means the balance is short: fund it as in [Topping up](#topping-up), then retry. A `400` means no card issuer account is linked yet, which the holder fixes in the dashboard.

## Finding a card to spend

```bash theme={null}
curl "https://laso.finance/get-card-data?card_type=Reloadable" \
  -H "Authorization: Bearer $LASO_ID_TOKEN"
```

Each card returns `card_id`, `last4`, `expiry`, `balance`, `spend_limit`, `reusable`, and `status` (`open`, `paused`, or `closed`). Spend against a card whose `status` is `open` and whose `balance` covers the purchase.

If the wallet has no card issuer account linked, the list comes back empty with a `note`. That is not an error. It means the account holder has not set up a reloadable card yet.

## Getting the card number requires the holder's approval

This is the one place a reloadable card differs sharply from the non-reloadable flow. Card numbers are not returned on demand:

```bash theme={null}
curl "https://laso.finance/get-card-data?card_id=cmt0s8kpc00kel10494xurke8" \
  -H "Authorization: Bearer $LASO_ID_TOKEN"
```

If the response contains `details_approval` with `status: "pending"`, the card issuer has emailed the account holder an approve/deny link. There is no way to bypass this, and retrying without an approval only mints another request. Tell your human that an approval is waiting in their email, then retry with the `approval_id` once they have approved:

```bash theme={null}
curl "https://laso.finance/get-card-data?card_id=cmt0s8kpc00kel10494xurke8&approval_id=cmt12pbax000cl804z2a8em1x" \
  -H "Authorization: Bearer $LASO_ID_TOKEN"
```

`card_details` (card number, CVV, expiry) is populated in that second response.

## Spending it

Pay the merchant exactly as you would with any card: enter the number, expiry, and CVV at checkout, and enter the returned `billing_address` **exactly** as given. That address comes from the account holder's identity verification and is AVS-checked at checkout. A mismatch as small as `St` versus `Street` is the most common decline on a card that has enough money on it.

A reloadable card with `reusable: true` stays open after an approved charge, so the same card can be spent again up to its remaining `balance`. Re-read `balance` before each purchase instead of assuming it still covers the total: there are no partial approvals, so a charge larger than the balance is declined in full rather than partly filled.

If a charge is declined, check in order: `status` is still `open`; `balance` covers the full amount including tax and shipping; and the billing address was entered exactly as returned. If all three hold, the decline is merchant-side, some merchants reject prepaid or debit cards, and some non-U.S. merchants decline U.S.-issued cards.

## Reading the history

`GET /list-card-transactions` returns transactions on the holder's reloadable cards, newest first:

```bash theme={null}
curl "https://laso.finance/list-card-transactions?card_id=cmt0s8kpc00kel10494xurke8" \
  -H "Authorization: Bearer $LASO_ID_TOKEN"
```

Omit `card_id` for every reloadable card on the account, and narrow with `limit` and `status`. Each row carries `merchant`, `amount` in US dollars, `status`, and `created_at` in milliseconds. This covers reloadable cards only; non-reloadable history stays in `/get-card-data`.

The same response carries `card_events`, which is the rest of the story. The card issuer reports spends and nothing else, so a list of purchases alone shows money leaving a balance that grows for no visible reason. Each event has an `event_type` of `deposit`, `limitChange`, `cardCreated`, or `withdrawal`, plus `amount` and `balance` for a deposit, `previous_spend_limit`/`new_spend_limit` for a limit change, and `amount`, `withdrawal_id` and `destination_address` for a withdrawal requested through `POST /withdraw-card-balance`. Merge the two lists by `created_at` and you have the account holder's own view of the card. Skip a `deposit` that carries a `top_up_id`: that money is already the final leg of a `top_ups` row below, and counting both doubles it. A third list, `top_ups`, follows each top-up from `GET /fund-card-balance` or `POST /fund-card-from-account-balance` across its legs (`paid`, `bridging`, `delivered`, `credited`, or `failed`) with the transaction hash behind each one, which is the same tracker the holder sees in the dashboard after adding money.

## Withdrawing the balance

Unspent money comes back off the card with `POST /withdraw-card-balance`. The balance behind a reloadable card is held by the card issuer, and this asks the issuer to pay part of it out as USDC on Base to an address you supply:

```bash theme={null}
curl -X POST "https://laso.finance/withdraw-card-balance" \
  -H "Authorization: Bearer $LASO_ID_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"amount": 25, "destination_address": "0x1234567890abcdef1234567890abcdef12345678"}'
```

Both fields are required: `amount` is \$2 to \$10,000 and no more than the balance, and `destination_address` is a Base wallet you control. The response carries the issuer's `withdrawal_id` and a `status` of `requested`.

**Base only, and not instant.** The issuer pays on Base and nowhere else, so a Laso managed agent wallet, which holds USDC on Solana, cannot receive it, and the card deposit address is not a valid destination. The issuer processes payouts manually, usually within 1-3 business days, and emails the account holder when the payout is sent. There is no status route: the request shows up as a `withdrawal` event in the history below, and `balance` from `GET /get-card-deposit-address` drops once it is paid. Withdrawals the issuer has not paid yet still count against the balance, so a second request can only take what remains. A refusal is a `400` whose `code` says why (`insufficient_card_balance` names how much can be withdrawn right now). Confirm the amount and destination with the account holder before calling this.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.