Create a virtual account
Creates a US_BANK virtual account for a VERIFIED, product-eligible user. US_BANK is the only supported type today; choose fiat (a USD-balance account funded by inbound wire/ACH) or crypto (an on-chain stablecoin deposit address) via mode, and select the bank/provider rail with bank (or its provider alias).
⚠️ bank is REQUIRED for US_BANK VAs — including crypto. Omitting it returns 400 "bank is required for US_BANK virtual accounts". (An earlier support answer that said to remove bank for crypto was incorrect.)
The bank value is environment-scoped:
- Sandbox (this collection): use
slovak_savings_bank(the international/crypto rail). Sendingportagehere returns400 "Invalid bank"—portageis only authorized in production. - Production: the same crypto rail is
portage.
bank selects the provider/rail; mode: "crypto" + destination make it a crypto VA — both are needed, they are not redundant. Note: Tron (tron) is accepted on slovak_savings_bank in sandbox even though the destination.network enum historically documented only solana | polygon.
Production variant — change one line: "bank": "portage" (everything else stays the same). slovak_savings_bank and portage are both international/crypto-capable banks; the value is just environment-scoped. Precondition: the user must be status: VERIFIED and eligible for the product.
Not-ready marker: this VA type shows account_number: null until provisioned (the "PENDING-ACT-ACCOUNT" sentinel is ACT-only). Funds-ready = account_number non-null AND != "PENDING-ACT-ACCOUNT".
You can also pass an optional description (string) — a human-readable label for the account. When provided, it is echoed back on the create response and on GET /v1/virtual-accounts/{id}.
Fiat vs crypto mode. Omit destination and send mode: "fiat" to create a USD-balance account (no automatic crypto conversion); provide a destination for crypto mode. Mode is fixed at creation and cannot be changed. mode: "fiat" must omit destination, and fiat mode is not supported on certain banks (returns 400 "Fiat mode (omitting destination) is not supported for this bank.").
Required-for-VA fields (product eligibility). The user must satisfy the product’s pre-submission required fields before a virtual account can be created: expected_monthly_volume and expected_transaction_count (the sponsor-bank rule), plus every product-specific field and document the user’s missing_fields map reports for the product on GET /v1/users/{id}. If any is absent, this call returns 422 with code: "missing_required_fields" and a top-level missing_fields array naming exactly which are missing — the account is not created in a silently-ineligible state and no virtual_account.created webhook is emitted. Supply the fields on POST /v1/users (bucketed enums that differ for individuals vs businesses — see Creating users) or backfill with PUT /v1/users/{id}, then retry — the same idempotency-key may be reused after a 422.
Authorizations
Access token from POST /auth (the data.access_token value).
API key issued by Kira. Required on every request, including /auth.
Headers
Optional. The date-versioned API version to apply for this request (e.g. 2026-04-14). When sent it always wins, even over your pinned account default. When omitted, the API uses your account's pinned version if set, otherwise a baseline default.
"2026-06-01"
"{{idempotency_key}}"
Body
Request body for POST /v1/virtual-accounts. bank is required for US_BANK unless provider is supplied. destination is required for crypto mode and must be omitted for mode: "fiat". A Idempotency-Key (UUID) request header is also required.
A user with status: VERIFIED, eligible for the product.
Virtual-account product. The US_BANK path is the documented golden path.
US_BANK Selects the provider/rail for US_BANK. Recommended default: the international/crypto rail — slovak_savings_bank (sandbox) / portage (production). Environment-scoped: sandbox accepts slovak_savings_bank, austin_capital_trust; production accepts portage, austin_capital_trust. Required for US_BANK unless provider is given.
portage, slovak_savings_bank, austin_capital_trust Alias that selects a bank (act → austin_capital_trust). Provide this instead of bank to satisfy the bank requirement for US_BANK.
act Fixed at creation and cannot be changed. fiat must omit destination; crypto requires it.
fiat, crypto Crypto payout target. Omit entirely for fiat mode.
Human-readable label, echoed back on create and on GET /v1/virtual-accounts/{id}.
Stripe-style key/value map: up to 50 keys; key ≤ 40 chars (no [ or ]); value ≤ 500 chars.
Optional per-VA fee-markup overrides (decimal strings).
Response
Created. Returns the new virtual account.
Response for POST /v1/virtual-accounts (HTTP 201).
Raw internal status on the 2026-06-01 pin: typically activating immediately after creation while the account provisions. activating does not mean funds-ready — poll until active (or confirm readiness via account_number and the virtual_account.activated webhook) before use.
pending, activating, active, failed, deactivated Virtual-account product type — US_BANK for the US virtual accounts documented in this reference.
US_BANK Funding mode echoed back. crypto accounts return a populated destination (wallet address); fiat accounts return destination: null.
fiat, crypto ISO 8601.
Present for US_BANK; the effective bank (after any provider alias is resolved).
portage, slovak_savings_bank, austin_capital_trust Null for fiat virtual accounts.
Provider deposit details; null while the VA is still activating.
Present only when supplied on create.
Present only when a non-empty markup was supplied on create.
Your own key/value metadata, echoed back verbatim. {test_key: "test_value"} sent on create was returned unchanged.