Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.useveil.co/llms.txt

Use this file to discover all available pages before exploring further.

This page walks through a complete Veil offramp from inside a chat. Each step names the tool the assistant calls and shows what to expect. The OTP confirmation step in this flow applies to every programmatic offramp surface, not only MCP — CLI and direct API use the same confirm gate. The dashboard uses session re-verification instead. See Offramp lifecycle for the full picture.

Prerequisites

  • The Veil MCP connector is added and authorized in your client (see Connect)
  • Your Veil account has completed KYC and has a bank account added
  • Your wallet holds USDC or USDT
If any of those aren’t in place, the onboarding steps below cover them.

Running an offramp

1

Check session

The assistant calls veil_get_session_status to see whether you are already logged in. If status is authenticated, skip to the account status step. If unauthenticated, continue to the next step.
You: Send 50 USDC to my bank.
Assistant: Let me check your Veil session first.
[calls veil_get_session_status]
→ status: "unauthenticated"
Assistant: You are not logged in. What email address should I use?
2

Request an OTP

The assistant calls veil_request_otp with your email. Veil sends a six-digit code to that address.
You: you@example.com
[calls veil_request_otp with email="you@example.com"]
→ status: "sent", requestId: "req_abc123"
Assistant: A code was sent to you@example.com. Please share it when you receive it.
3

Verify the OTP

When you share the code, the assistant calls veil_verify_otp. On success, your session is active and the assistant has your user profile.
You: 482910
[calls veil_verify_otp with requestId="req_abc123", otp="482910"]
→ status: "logged_in", user.email: "you@example.com"
Assistant: Logged in. Let me check your account status.
4

Check account status

The assistant calls veil_get_account_status. This tells it whether KYC is approved and a bank account is present. If stage is ready, skip to the wallet step.
[calls veil_get_account_status]
→ stage: "ready", kyc.status: "approved", bankAccount.present: true
If stage is needs_kyc, the assistant calls veil_kyc_start and shares a link for you to open in a browser. After you complete the form, it polls veil_kyc_check_status until status is approved.If stage is needs_bank_account, the assistant calls veil_bank_account_get_form_url and shares a link. You fill in your bank details in the browser, then return to the chat.
5

List wallets

The assistant calls veil_wallets_list to find your wallets and their USDC/USDT balances.
[calls veil_wallets_list]
→ wallets: [{ id: "wal_xyz", name: "Base wallet", chain: "base", balance: { USDC: "120.00" } }]
6

Get a quote

The assistant calls veil_offramp_quote with the amount, asset, wallet, and destination bank. The quote is non-binding — you can adjust the amount and re-quote as many times as you like.
Assistant: Your Base wallet holds 120 USDC. How much would you like to send?
You: 50 USDC
[calls veil_offramp_quote with amount=50, assetIn="USDC", walletId="wal_xyz"]
→ amountOut: 46.23, currencyOut: "EUR", exchangeRate: 0.9246, totalFee: 0.46
Assistant: You will receive approximately €46.23 after fees. Shall I proceed?
7

Execute the offramp

After you confirm the quote, the assistant calls veil_offramp_execute. This creates a pending transaction and sends a six-digit confirmation code to your email.
You: Yes, go ahead.
[calls veil_offramp_execute with walletId="wal_xyz", amount=50, assetIn="USDC", userConfirmed=true]
→ status: "ok", transactionId: "txn_123", requestId: "req_456", maskedEmail: "y***@example.com"
Assistant: A confirmation code was sent to y***@example.com. Please share it to release the funds.
The assistant requires userConfirmed=true before calling veil_offramp_execute. It will not proceed without your explicit approval.
8

Confirm with the code

Share the six-digit code from your email. The assistant calls veil_offramp_confirm. This step is irreversible — once confirmed, the crypto is converted and the fiat is sent to your bank.
You: 719302
[calls veil_offramp_confirm with transactionId="txn_123", requestId="req_456", code="719302"]
→ status: "ok", transaction.status: "processing"
Assistant: Confirmed. The offramp is processing. EUR settlement typically arrives the same day.
9

Track status (optional)

To check progress later, the assistant calls veil_offramp_get_transaction with the transaction ID, or veil_transactions_list to see recent activity.
You: What happened to my offramp?
[calls veil_offramp_get_transaction with transactionId="txn_123"]
→ transaction.status: "completed", settledAt: "2026-05-14T14:22:00Z"
Assistant: Your offramp completed and the fiat was sent to your bank.

Sending to a Veil user by @handle

If the recipient has a Veil username, you can send directly to their @handle. The assistant calls veil_username_beneficiary_preview first to confirm the recipient is ready, then passes the binding token to veil_offramp_quote and veil_offramp_execute.
You: Send 30 USDC to @alice.
[calls veil_username_beneficiary_preview with handle="alice"]
→ status: "ready", displayUsername: "@alice", bindingHint: "Use bindingToken=..."
[calls veil_offramp_quote with amount=30, assetIn="USDC", beneficiaryUsername="alice", bindingToken=...]
→ amountOut: 27.71, currencyOut: "EUR"
The sender never sees the recipient’s bank details. See Usernames.

Switching modes

To switch between sandbox and live, ask the assistant to switch or call veil_set_mode explicitly:
You: Switch to live mode.
[calls veil_set_mode with mode="live"]
→ status: "switched", activeMode: "live"

See also