Virtual Card API: How to Automate Card Issuance with Code

A virtual card API lets you issue, fund, freeze and close cards from your own code. See how the card issuing API works, with real endpoints and webhooks.

  • Published
  • 9 min read
Short answer

A virtual card API lets your software issue, fund, freeze and close payment cards over HTTPS instead of clicking through a dashboard. With the USDT Crypto Card REST API, you authenticate with a secret sk_live_ key, create Visa or Mastercard cards loaded from your USDT balance, read transactions, and receive signed webhooks when something happens. It's built for teams that issue many cards, such as ad agencies, SaaS operators and finance tools.

What a card issuing API is for

Issuing a handful of cards by hand is fine. Issuing a card for every new client, campaign or vendor, and keeping each one funded, quickly becomes repetitive. A card issuing API turns those steps into code:

  • Create a card per entity automatically, for example when a new client signs up in your CRM.
  • Top up cards on a schedule or when their balance drops.
  • Freeze cards instantly when a budget is hit or a contract ends.
  • Sync transactions into your accounting or reporting tools.
  • React to events in real time through webhooks instead of polling.

The API does what the dashboard does, from your server. Every card you issue and every load you make is paid from your account balance, which you fund with crypto deposits and which is always held in USDT.

Getting access to the virtual card API

Access takes three steps:

  1. Create a key. Open API access in your dashboard and generate a key. Keys start with sk_live_.
  2. Get it switched on. Confirm your email and make a first deposit, then ask support (through a ticket in the dashboard) to enable the API for your account.
  3. Make a call. Check your balance, then issue your first card.

Until your account is ready, a valid key gets a 403 response. You'll see the error code onboarding_incomplete until your email is confirmed and you've made a first deposit, then api_not_enabled until API access is switched on.

There is no separate sandbox environment and no official SDK packages. You call the REST API directly with any HTTP client, which keeps integration simple but means every call is live. Test with small amounts.

Basics: base URL, auth and format

  • Base URL: https://usdtcryptocard.com/api/v1
  • Authentication: send your key as a Bearer token in the Authorization header of every request.
  • Format: JSON over HTTPS. Amounts are in US dollars with two decimals. Timestamps are ISO 8601 in UTC.
  • Pagination: list endpoints take page and per_page.

Keep the key on your server. Anyone holding it can move money on your account, so load it from an environment variable and never ship it in browser or mobile code.

Your first call

Checking your balance is a safe first request:

curl https://usdtcryptocard.com/api/v1/wallet/balance \
  -H "Authorization: Bearer sk_live_..."

The response shows your USDT balance, pending deposits and what's sitting on your cards:

{
  "balance": 1312.5,
  "currency": "USDT",
  "pending_deposits": 500.0,
  "cards_active": 8,
  "cards_total_balance": 2450.0
}

The endpoints

The API has 15 endpoints across six resources.

Resource Method and path What it does
Cards POST /cards Issue a card and load it in one call
Cards GET /cards List cards, filterable by status and BIN
Cards GET /cards/{card_id} Card summary without number or CVV
Cards GET /cards/{card_id}/details Full card number, CVV and expiry
Cards POST /cards/{card_id}/freeze Temporarily suspend a card
Cards POST /cards/{card_id}/unfreeze Re-enable a frozen card
Cards DELETE /cards/{card_id} Permanently terminate a card
Funding POST /cards/{card_id}/fund Move money from your balance onto a card
Funding POST /cards/{card_id}/withdraw Move a card's balance back to your wallet
Transactions GET /transactions Authorizations, settlements, refunds and declines
Wallet GET /wallet/balance Balance and card totals
Wallet GET /wallet/deposit-address Crypto deposit addresses
BINs GET /bins The BIN catalog
3D Secure GET /3ds Pending 3D Secure challenges with codes
Webhooks POST /webhooks Register an endpoint for events

Full parameters and example responses are in the API reference.

Issuing a card from code

Creating a card picks a BIN and loads the card from your balance in the same request. The fields are:

  • bin_id (required): the BIN to issue on. List the options with GET /bins.
  • amount (required): the initial load in USD, taken from your balance. The minimum is $50, and the $1 issuance fee is charged on top.
  • label: your own name for the card.
  • spending_limit: a spending limit in USD.
  • allowed_categories: merchant categories the card may be used in, such as advertising or software. Anything else is declined.
  • auto_freeze_at: freeze the card automatically when its balance drops below this amount.
  • metadata: key-value pairs for your own tracking.

Here's the same request in Node.js:

const res = await fetch('https://usdtcryptocard.com/api/v1/cards', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.USDTCC_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    bin_id: '491653',
    amount: 500,
    label: 'Meta Ads - Campaign 12',
    spending_limit: 2000,
    allowed_categories: ['advertising'],
    metadata: { campaign: 'fall_2026' },
  }),
});
const card = await res.json();

A successful call returns 201 with the card object: its id, BIN, network, last four digits, status, balance and your label and metadata. The summary deliberately leaves out the full number and CVV.

Getting the card number safely

GET /cards/{card_id}/details returns the full card number, CVV and expiry. Treat it as sensitive: never log the response or store it unencrypted, and fetch it only when you actually need to hand the details to a person or a checkout. This endpoint has a tighter rate limit than the rest.

Funding, freezing and closing

  • Top up: POST /cards/{card_id}/fund with an amount moves money from your balance onto the card. It's spendable right away.
  • Pull funds back: POST /cards/{card_id}/withdraw returns the card's balance to your wallet.
  • Pause: POST /cards/{card_id}/freeze suspends all transactions while keeping the balance. unfreeze re-enables the card.
  • Close: DELETE /cards/{card_id} terminates the card permanently and returns its remaining balance to your wallet. It can't be undone.

The usual fees apply to API activity, exactly as in the dashboard: $1 per card issued, $0.30 per approved transaction (declines free), and free card top-ups from your balance. Deposits under $300 carry a 2% fee; $300 or more carries none. See the pricing section.

Webhooks

Instead of polling, register an HTTPS endpoint with POST /webhooks, listing the events you want (or ["*"] for all). Available events include:

  • card.created, card.frozen, card.unfrozen, card.terminated, card.funded
  • transaction.authorized, transaction.settled, transaction.declined, transaction.refunded
  • 3ds.challenge
  • deposit.pending, deposit.confirmed

Every delivery is signed with HMAC-SHA256 using your endpoint's secret, which is generated for you if you don't supply one. Recompute the signature over the raw request body and compare in constant time before trusting the payload:

import crypto from 'node:crypto';

export function verify(rawBody, signature, secret) {
  const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}

Parse the JSON only after verification passes, and make your handler idempotent in case an event arrives more than once.

Errors and rate limits

Anything other than a 2xx comes with a JSON body containing a stable error code you can branch on and a human-readable message. The status codes you'll meet are 400 (invalid parameters), 401 (missing or invalid key), 403 (account not ready or API not enabled), 404 (not found) and 429 (rate limit exceeded).

Limits are counted per API key:

Limit Value
Requests per minute 1,000
Card creations per minute 50
Requests per hour 10,000

If you get a 429, wait and retry with exponential backoff.

Design tips for a reliable integration

  • Store the card id, not the card number. Fetch details on demand.
  • Use metadata and label to link cards to your own records, such as a client ID or campaign.
  • Prefer webhooks to polling for transactions and 3D Secure challenges.
  • Keep a buffer on cards that pay recurring charges, or use auto_freeze_at and fund to manage balances automatically.
  • Plan for limits. Account plan limits still apply: the Virtual plan allows $5,000 per transaction and $20,000 per month, while Platinum, unlocked by a single deposit of $300 or more, has no spending limits.

If you're managing cards for a team rather than writing code, see virtual cards for teams. For ad-account use cases, read virtual cards for ads. Ready to start? Create an account.

Frequently asked questions

What is a virtual card API?

It's an interface that lets software create and manage payment cards automatically. With USDT Crypto Card, it's a REST API using JSON over HTTPS, authenticated with a secret sk_live_ key.

Is there a sandbox or SDK?

No. There's no sandbox environment and no official SDK packages. You call the REST API directly with any HTTP client, and every call is live, so test with small amounts.

Why does my new API key return 403?

The account isn't ready yet. onboarding_incomplete means you still need to confirm your email and make a first deposit. api_not_enabled means support still needs to switch API access on.

How are webhooks secured?

Each delivery is signed with HMAC-SHA256 using your endpoint's secret. Recompute the signature over the raw body and compare it in constant time before trusting the payload.

Do API cards cost the same as dashboard cards?

Yes. The same fees apply: $1 per card, $0.30 per approved transaction, free top-ups from your balance, and a 2% deposit fee below $300.

Put your USDT to work

Open an account with a seed phrase, confirm your email, deposit crypto and issue a card in minutes.

Virtual Card API: How to Automate Card Issuance with Code | USDT Crypto Card