Move money with transfers

Move money between your Wingspan Wallet and a linked bank account, follow the transfer until it settles, and cancel one that hasn't been submitted.

A transfer moves money between two accounts you own. One side is always an internal account, such as your Wingspan Wallet. The other side is another internal account of yours or a bank account you've linked.

A transfer into the Wallet is a Deposit. A transfer out of it is a Withdrawal.

Prerequisites

  • A Wallet. See Internal accounts and balances.
  • For a bank account on the other side, a linked and verified bank account. See Link and verify a bank account.
  • A credential with bookkeeping.business-banking-account:write to create or cancel, and :read to list or retrieve.
  • An Idempotency-Key header on every create.

Create a transfer

Call POST /v3/finance/transfers.

FieldRequiredNotes
amountYesAt least 0.01
currencyYesMust match the currency of the internal account involved
directionYesDeposit or Withdrawal
sourceAccountIdYesThe account the money leaves
destinationAccountIdYesThe account the money enters
transferMethodNoAch, Wire, RealTime, or Internal
scheduledDateNoYYYY-MM-DD
description, metadataNo

Wingspan works out which side is your internal account and checks that direction agrees. For a Deposit, the destination is your internal account. For a Withdrawal, the source is.

curl -X POST "https://api.wingspan.app/v3/finance/transfers" \
  -H "Authorization: Bearer $WINGSPAN_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: fund-wallet-2026-10-20" \
  -d '{
    "amount": 2500.00,
    "currency": "USD",
    "direction": "Deposit",
    "transferMethod": "Ach",
    "sourceAccountId": "Ba7Hn2Qx5Rt8Kw3Lp6Zb9D",
    "destinationAccountId": "Ia4Kq9Wn2Lx7Tz5Bm8Hc3V",
    "description": "Fund Wallet"
  }'
// 201 Created (trimmed)
{
  "id": "Tr3Wn8Qk5Lx2Bz7Mh4Rc9T",
  "status": "Created",
  "amount": 2500.00,
  "currency": "USD",
  "direction": "Deposit",
  "transferMethod": "Ach",
  "sourceAccountId": "Ba7Hn2Qx5Rt8Kw3Lp6Zb9D",
  "destinationAccountId": "Ia4Kq9Wn2Lx7Tz5Bm8Hc3V",
  "events": { "createdAt": "2026-10-20T15:02:11Z" }
}

A 201 means Wingspan accepted the transfer. It doesn't mean the money has moved.

To start from the internal account instead, call POST /v3/finance/internal-accounts/{internalAccountId}/transfers. It takes amount, direction, and description, all required, plus transferMethod, counterpartyAccountId, counterpartyAccountType (InternalAccount or ExternalBankAccount), scheduledDate, and metadata. The currency is the account's own.

Follow a transfer

Read one with GET /v3/finance/transfers/{transferId}, or list them with GET /v3/finance/transfers. The list takes filter[status][eq], filter[direction][eq], sort, and page.

statusMeaning
CreatedAccepted, not yet sent to the payment rail
InProgressSent to the payment rail
CompletedSettled
FailedDidn't settle. statusReason is InternalError, ExternalFailure, BadPayoutMethod, or InsufficientFunds.
CancelledCancelled before it was sent
ReturnedThe bank sent the money back

Subscribe to webhooks instead of polling. Transfer.Created, Transfer.Updated, Transfer.Processed, Transfer.Completed, Transfer.Cancelled, and Transfer.Failed are published. See Webhooks and events.

Cancel a transfer

Call POST /v3/finance/transfers/{transferId}/cancel. It works only on a transfer Wingspan hasn't submitted to the payment rail. A transfer already submitted returns 409. On success the response is the transfer with status: Cancelled.

Permissions and step-up

If you call with a person's login session, creating and cancelling transfers return 403 with code: StepUpMfaRequired until the person completes a HighRiskWriteAction challenge. See Banking and spend.

Errors

StatusMeaning
403Missing scope, or StepUpMfaRequired
404Neither account is an internal account you own, a bank account isn't yours, or the transfer doesn't exist. Wingspan doesn't say whether the other account exists.
409IdempotencyKeyConflict (same key, different body), or the transfer can't be cancelled because it was already submitted
422The amount is below 0.01, direction doesn't match the accounts, currency doesn't match the internal account, or transferMethod isn't supported

Related pages


Did this page help you?