Deposited USDC Credits

Deposit USDC once, spend it like credit, and withdraw whatever you did not use. It is the only funded balance on Surplus that can leave again. (Elsewhere in the API and the dashboard this is called prefunded USDC — same thing.)

Card top-ups create credit — an internal ledger balance that can be spent and never withdrawn. Prefunded USDC is the other half: you send USDC to a deposit address owned by your workspace, it becomes a spendable balance, and the unspent remainder can go back to your wallet.

This is live. Prefunded USDC and deposit intake are both enabled in production. If an endpoint below returns 404 rather than 401/403, that is a feature gate rather than a wrong URL — but on production today, it is on.

The distinction that matters

Both balances add up to one spendable number in the dashboard. Underneath they are not interchangeable.

Prefunded USDC
Deposited on chain. Spendable, and you can withdraw whatever you do not use.
Card credit
Bought with a card. Spendable, but it can never leave — so it is spent first.

That is also why the spend order is what it is: card credit is spent first, prefunded USDC second. Spending the non-withdrawable money first preserves the withdrawable money for as long as possible. If the order were reversed, every request would quietly convert money you could get back into money you could not.

Deposit, spend, withdraw
  1. Get a deposit address
    GET /v1/payments/deposit-address
  2. Send USDC on Base
    From any wallet
  3. Confirmations
    Credited once final
  4. Spend or withdraw
    POST /v1/payments/withdraw
Deposits need on-chain confirmations before they are spendable. Withdrawals go only to a wallet the account has registered.

Depositing

bash
curl -s https://api.surplusintelligence.ai/v1/payments/deposit-address \
  -H "Authorization: Bearer inf_..."

The address is per workspace and stable — reuse it. Send USDC on Base to it from any wallet. The balance is not spendable the moment the transaction lands: it is credited after the configured minimum confirmations, which exists so a reorg cannot spend money that never settled.

Requires billing.manage.

Withdrawing

bash
curl -s -X POST https://api.surplusintelligence.ai/v1/payments/withdraw \
  -H "Authorization: Bearer inf_..." \
  -H "Idempotency-Key: $(uuidgen)" \
  -H 'Content-Type: application/json' \
  -d '{ "destination": "0xYourWallet", "amount_micro": "25000000" }'
  • Name
    destination
    Type
    string
    Description

    Where the USDC goes. Not a free-text field — it must be your own account wallet or a wallet the org has registered. An address that is neither is rejected, so a leaked key cannot drain funds to an attacker.

  • Name
    amount_micro
    Type
    string
    Description

    Integer microdollars as a string (1 USD = 1000000). Omit to withdraw everything available. A string because a JSON number silently accepts 1.5, and a fractional microdollar is not a representable amount of USDC.

Idempotency-Key is required and becomes the withdrawal's permanent identity, so a retried request can never withdraw twice. Requires wallets.manage — deliberately a different capability from billing.manage, because taking money out is a different decision from putting money in.

For a signed, multi-step withdrawal there is also POST /v1/wallet/withdraw/prepare, POST /v1/wallet/withdraw and GET /v1/wallet/withdraw/:id. Those require a signed-in session rather than an API key.

What you can withdraw

Only the prefunded USDC portion. Card credit is never withdrawable, and a withdrawal request cannot reach it.

If either ledger row is frozen, both are frozen — the balances are one funding decision, so a hold on one side stops spending from the other too. That is intentional, not a bug.

Auto top-up

Keep a floor under the balance rather than watching it:

MethodPathDoes
GET/v1/payments/auto-topupRead the current rule
PUT/v1/payments/auto-topupSet a threshold and amount
DELETE/v1/payments/auto-topupTurn it off

Writes require billing.manage and are idempotent.