Single-Use Wallets (Corporate Only)

Generate unique, one-time stablecoin deposit addresses so each incoming payment can be matched to a specific invoice, customer, or vendor.

Not yet available on the Stablecoin API. POST /stablecoin/corporate/{corporate_uuid}/single-offramp-wallet has not finished migrating: it validates the request body and returns 200 with an empty object {} — no wallet is created and no address is returned. Do not build against this path yet. The feature is live on the legacy endpoint; contact [email protected] if you need access while the migration completes.

Current behaviour

Verified against sandbox:

RequestResponse
Valid external_reference200 {} — no address, no wallet created
Missing external_reference400 INPUT_VALIDATION_ERROR — external_reference is required
Corporate UUID that does not exist200 {} — not a 404
Malformed corporate UUID400 INPUT_VALIDATION_ERROR — corporate_uuid Invalid UUID

Only body and path validation run today. A 200 from this endpoint does not mean a wallet exists, and the empty response cannot be distinguished from a successful call — so do not treat 200 as confirmation.

The API reference documents a 201 with chain, address, and external_reference, plus 403 for non-whitelisted corporates and 404 for unknown corporates. That is the intended contract, not current behaviour on this path.

What they do

Each wallet is a one-time stablecoin deposit address. When stablecoins arrive, the funds automatically off-ramp to the corporate's main remote bank account — so a corporate can hand a distinct address to each payer instead of reconciling one shared address by amount and timing.

  • A distinct deposit address per request
  • Automatic off-ramp on receipt — no polling for balances
  • Settles to the corporate's main remote bank account
  • Corporates only, and whitelisted

external_reference is retained for backwards compatibility. It is required and echoed back in the response, but it no longer influences the wallet that is created. Keep sending it, and keep your own mapping from the returned address to your invoice or customer — do not rely on the reference to do that for you.

Use cases

The value is the address: give each payer a distinct one and inbound payments become self-identifying.

Use caseWhat you map the address toWhy a unique address helps
Invoice paymentsAn invoice IDKnow which customer paid which invoice without asking them to attach a memo.
Batch settlementsA settlement batchProcess many payments at once, each reconciling independently.
Customer depositsA customer accountGive each customer their own deposit address; auto-convert and sweep to treasury.
Vendor paymentsA purchase orderAttribute inbound vendor settlements to a specific PO.
Marketplace payoutsA seller accountAttribute buyer payments to the correct seller before settlement.
Subscription billingA billing periodSeparate each period so partial or late payments are unambiguous.
Rent or recurring collectionsA unit and monthTie each inbound payment to a property and period.
Escrow / milestone releasesA deal milestoneIsolate funds per milestone so each release is independently auditable.

Without single-use wallets every customer pays into the same corporate address and you reconcile by amount and timing — which breaks the moment two customers pay the same amount on the same day. That ambiguity is what this removes.

Prerequisites

  1. The corporate has completed KYB and is in ACTIVE status — see KYC & KYB.
  2. A main remote bank account is set for the corporate, since that is where funds settle. See Off-Ramp.
  3. The corporate is whitelisted for the feature by Bakkt.

Flow

  1. Create — request a wallet, optionally specifying a chain.
  2. Store the mapping — record the returned address against your invoice, customer, or PO. This mapping is yours to keep.
  3. Share — present the address and chain on the invoice or checkout page.
  4. Customer pays — the customer sends stablecoins to that address.
  5. Auto off-ramp — Bakkt converts and sends fiat to the corporate's main remote bank account.
  6. Reconcile — a cryptoToFiat webhook fires; resolve the address back to your record. See Webhooks.

Chains and address formats

The wallet is created on the requested chain, defaulting to Polygon when omitted.

Tron addresses are returned in base58. For chain: "tron" the address comes back in the user-facing base58 form (TXyTzf3Exu…) rather than the hex form used elsewhere in the API. Present it exactly as returned — a hex address is not usable as a Tron deposit address, and funds sent to a mis-formatted address cannot be recovered.

ChainExample address format
polygon, base, and other EVM chains0x316aD179a8db32EEBA367479596e3c5511f3F093
tronTXyTzf3ExuXrKMEAFM916MraoKB6MGdxgK

Request

This is the contract the endpoint will honour once the migration completes. On the Stablecoin path it returns {} today — see Current behaviour.

// Note the `API-Key ` prefix — the raw key on its own returns 401.
const API_KEY = 'API-Key YOUR_API_KEY';

const response = await fetch(
  `https://sandbox.api.bakkt.com/stablecoin/corporate/${corporateUuid}/single-offramp-wallet`,
  {
    method: 'POST',
    headers: {
      'Authorization': API_KEY,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      external_reference: 'invoice-12345',  // required; echoed back, retained for compatibility
      chain: 'polygon'                      // optional; defaults to polygon
    })
  }
);

const { chain, address, external_reference } = await response.json();
// { chain: 'polygon', address: '0x316aD179…', external_reference: 'invoice-12345' }

// Persist YOUR mapping — the reference does not drive the wallet.
await db.saveDepositAddress({ invoiceId: 'invoice-12345', chain, address });

Authenticated with your merchant API key only — no bakkt-session-id required.

While the migration completes

If you need this today, contact [email protected] — the feature is available on the legacy endpoint. Otherwise, the options for attributing inbound payments are:

ApproachHowTrade-off
Corporate off-ramp address per bank accountGET /corporate/{corporate_uuid}/wallet/{chain} — see Off-RampOne address for all payers; reconcile by amount and timestamp.
Per-payer remote bank accountsCreate a remote bank account per destinationSeparates settlement, not inbound attribution.
Off-chain referenceAsk payers to quote an invoice ID out of bandRelies on the payer; not enforceable on-chain.

Did this page help you?