Skip to main content

Quickstart

This is the fast path: from zero to a settled USDC payment in under 30 minutes, entirely in sandbox (no real funds). Every step shows what you should get back.

You will:

  1. Get a sandbox API key and log in with the CLI.
  2. Create a wallet.
  3. Fund it from the faucet.
  4. Claim a payable handle and send a payment.
Prerequisites

Node.js 20+. For the SDK: pnpm add @safebank/sdk. For the CLI, build it once with pnpm --filter @safebank/cli build (see the CLI guide).

1. Get a key

API keys are minted per tenant. Grab a sandbox key (sb_test_…) from the SafeBank developer dashboard, then save it to a local CLI profile:

sb login sb_test_...
# validates the key by resolving your tenant, then writes ~/.safebank/config.json

Expected output confirms the tenant and masks the key:

Logged in · sandbox
tenant Acme Robotics (acme-robotics)
key sb_test_Ab12Cd34Ef56_…
profile sandbox → ~/.safebank/config.json

For the SDK and curl, keep the key in an env var instead:

export SAFEBANK_API_KEY=sb_test_...
note

The base URL is inferred from the key prefix — sb_test_https://api.sandbox.safebank.ai. See Environments.

2. Create a wallet

A wallet is a Safe multisig. Create one owned by a signer address you control. In sandbox the CLI generates and stores a demo signer for you on first use.

curl -X POST https://api.sandbox.safebank.ai/v1/wallets \
-H "X-SafeBank-Api-Key: $SAFEBANK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Treasury",
"owners": [{ "address": "0xYourSignerAddress", "role": "ADMIN_OWNER" }],
"threshold": 1,
"chainId": 84532
}'

You get back a Wallet. The address is a predicted Safe address at first; status moves PENDING_DEPLOYMENT → DEPLOYING → DEPLOYED.

{
"id": "w_1a2b3c",
"address": "0x7Fb2…c41A",
"status": "PENDING_DEPLOYMENT",
"chainId": 84532,
"threshold": 1,
"predictedAddress": true,
"name": "Acme Treasury",
"owners": [{ "address": "0xYourSignerAddress", "role": "ADMIN_OWNER", "label": null }],
"createdAt": "2026-08-09T12:00:00.000Z"
}

Keep the id — you need it for the next steps.

3. Fund it from the faucet

Sandbox only. The faucet drips test USDC (default 250, capped at 1000 per drip).

curl -X POST https://api.sandbox.safebank.ai/v1/wallets/w_1a2b3c/fund \
-H "X-SafeBank-Api-Key: $SAFEBANK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "asset": "usdc", "amount": "250" }'

You get back a Drip. status is SUBMITTED and becomes CONFIRMED once the transfer lands on-chain:

{
"id": "d_9z8y",
"walletId": "w_1a2b3c",
"asset": "usdc",
"amount": "250",
"chainId": 84532,
"status": "SUBMITTED",
"txHash": null,
"failureReason": null,
"createdAt": "2026-08-09T12:00:05.000Z"
}

4. Claim a handle

Payments can target a @handle. Give your recipient wallet a payable handle via the directory (do this for a second wallet that will receive funds):

curl -X PUT https://api.sandbox.safebank.ai/v1/directory/handle \
-H "X-SafeBank-Api-Key: $SAFEBANK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "handle": "volt-components", "walletId": "w_recipient" }'

Returns a HandleInfo:

{ "handle": "volt-components", "displayName": null, "address": "0x…", "chainId": 84532, "verified": true }

5. Send a payment

A payment is proposed → signed → executed. The API proposes it (screening

  • calldata), you sign the returned safeTxHash locally with a raw secp256k1 signature, and submitting the signature auto-executes once the wallet's threshold is met.
# 1. Propose — returns a payment with a safeTxHash to sign.
curl -X POST https://api.sandbox.safebank.ai/v1/payments \
-H "X-SafeBank-Api-Key: $SAFEBANK_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceWalletId": "w_1a2b3c",
"destination": { "type": "handle", "handle": "volt-components" },
"amount": { "value": "25.00" }
}'

# 2. Sign the safeTxHash locally (raw secp256k1 — NOT personal_sign), then:
curl -X POST https://api.sandbox.safebank.ai/v1/payments/p_abc/sign \
-H "X-SafeBank-Api-Key: $SAFEBANK_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "signature": "0x<signature-over-safeTxHash>" }'

After signing, the payment settles. status goes to COMPLETED and executedTxHash is populated:

{
"id": "p_abc",
"sourceWalletId": "w_1a2b3c",
"destinationType": "handle",
"destinationHandle": "volt-components",
"destinationAddress": "0x…",
"destinationChainId": 84532,
"asset": "usdc",
"amount": "25.00",
"status": "COMPLETED",
"safeTxHash": "0x…",
"executedTxHash": "0x…",
"memo": null,
"failureReason": null,
"createdAt": "2026-08-09T12:01:00.000Z"
}

That's the whole loop. 🎉

Next steps