# XO wallet API

You are an AI agent. This API gives you a self-custodial Solana wallet that holds XO Cash (mint `xoUSDq85Rjsb6SbUwJyreFgeWQvxdkT7R3c3g7s6p5Y`, 6 decimals, network `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`). Your human funds it and can claim it later.

Vocabulary: "money", "cash", "bucks", "dollars", "funds" and "XO" all mean XO Cash. One XO is one dollar. Every send and payment is sponsored: this wallet never needs SOL. Sends are final; confirm recipient and amount with your human before sending unless they already stated both. This wallet pays only in XO Cash; if a service does not take it, tell your human so.

Machine-readable description: `GET https://agent-api-production-a7b7.up.railway.app/openapi.json`.

## If you run on a hosted platform

Store `clientId` and `clientSecret` in your platform's secure credential store (in Muse, the secure credentials prompt; as a ChatGPT dot, your own files, never the conversation) and never repeat the secret in chat. If you lose it the funds stay safe but you cannot spend them; ask your human to claim the wallet.

Your host may ask your human to approve a send or payment. Wait for that answer. Do not retry around the prompt or split an amount to avoid it.

`fundingUrl` and `claimUrl` are safe to show your human.

`GET https://agent-api-production-a7b7.up.railway.app/openapi.json` describes this API for connector builders.

## 1. Create a wallet

`POST https://agent-api-production-a7b7.up.railway.app/wallets` with an empty body. No auth. Response: `{ walletId, solanaAddress, clientId, clientSecret, fundingUrl, claimUrl, mint }`. Keep `clientId` and `clientSecret`; they are your credentials. Show `fundingUrl` to your human when you need money. Show `claimUrl` when they want control of the wallet.

## 2. Check the wallet

`GET https://agent-api-production-a7b7.up.railway.app/wallets/{walletId}` (HTTP Basic auth `clientId:clientSecret`). Response: `{ walletId, solanaAddress, balance: { atomic, ui }, claimed }`.

`GET https://agent-api-production-a7b7.up.railway.app/wallets/{walletId}/transactions?limit=10` lists recent XO movements. `limit` must be an integer from 1 to 50 and defaults to 10; anything else answers `400 unsupported_requirements`.

## 3. Send money

`POST https://agent-api-production-a7b7.up.railway.app/wallets/{walletId}/transfers` with `{ "to": "<Solana address or wallet id>", "amount": "2.50" }`. Response: `{ signature, amount, to: { address, walletId? } }`. The recipient gets XO even if they never held it; we create their token account.

If your human gives you a pay-me link (`.../pay/<id>`), add `?amount=<XO>` and fetch it with the x402 flow in section 4 instead.

## 4. Pay an x402 resource

When a server answers `402` with a `PAYMENT-REQUIRED` header, base64-decode it to JSON and POST that JSON to `POST https://agent-api-production-a7b7.up.railway.app/wallets/{walletId}/payments` (Basic auth). Response: `{ paymentSignature }`. Retry the original request with header `PAYMENT-SIGNATURE: <paymentSignature>`. The 402 must offer XO Cash on Solana mainnet.

## Errors

JSON `{ code, message, ... }`:

- `insufficient_funds` (402): includes `required`, `balance` and `fundingUrl`. Show the funding URL to your human, wait, then retry.
- `invalid_recipient` (400): not a Solana address or wallet id, or this wallet's own address.
- `policy_rejected` (403): the wallet owner's spending rules refused this.
- `wallet_frozen` (403): the owner froze the wallet. Stop spending.
- `unsupported_requirements` (400): a malformed amount, or a 402 that does not offer XO Cash on Solana mainnet.
- `unauthorized` (401), `not_found` (404), `payment_failed` (502, retry later).