Skip to content

Card issuing infrastructure

Virtual Card API — issue Visa & Mastercard cards to your customers.

ScarabPay Business issues virtual cards to your customers, funded from a merchant wallet you top up. Every movement posts balanced double-entry legs to an insert-only ledger, so the figures you report and the rows we hold are the same rows.

Request POST /v1/cards
// Idempotency-Key: 8f3c1d90-...-b7a2
{
  "product_id":  "01HXYZP4K2M8N6Q1RSTVWXYZ01",
  "customer_id": "01HABCD7F3G9J5K2LMNPQRSTVW",
  "amount_minor": 250000
}

Ledger · insert only

merchant_wallet −250000
card_float +250000
movement total 0
One request, and the entry it posts. Values are demonstration data; the shapes are the documented ones.

01

The money path

How the virtual card API works.

Funding comes first because it has to: an issue request against an unfunded wallet is rejected, not queued. Nothing below is a stage in a marketing diagram — each one is an endpoint you call or an event you receive.

  1. Fund the wallet

    Your merchant wallet holds one balance per currency in integer minor units. Crypto deposits arrive at permanent per-network addresses and credit the wallet once the network confirms them.

    POST /deposit-addresses

  2. Issue a card to a customer

    One POST carries a product, a registry customer and an initial load. The load and the product's issue fee are held against the wallet, the issuing partner is called outside the database transaction, and settlement posts the movement to the ledger. Cards that provision asynchronously return 202 with a pending card.

    POST /cards

  3. Receive activity as it happens

    Authorizations and lifecycle changes reach you as signed webhook events — issued, authorization, recharged, frozen, unfrozen, terminated. The same activity is readable per card, cursor-paginated.

    GET /cards/{card}/transactions

  4. Reconcile against rows, not totals

    Reconciliation is reading the ledger back. Nothing is updated and nothing is deleted, so a figure you reported last quarter still resolves to the entries that produced it.

    GET /deposits

How card products route to licensed issuing partners Your integration sits at the top and connects to a single ScarabPay Business API. Below it, three paths lead to three unnamed licensed issuing partners, each carrying one card product. Your platform ScarabPay Business API Licensed partner 1 Card product 1 Licensed partner 2 Card product 2 Licensed partner 3 Card product 3

02

Issuing partners

One virtual card issuing API in front of several issuers.

You integrate once. Behind that integration each card product is routed to a licensed issuing partner chosen for its region and its product set. Adding a partner, or replacing one, is our migration rather than yours — the request you send does not change.

Partner identities are not published, and no partner name is exposed through the API or in any response you receive.

03

Developers

Virtual card API integration, written to be retried.

A financial API is judged by what happens on the second attempt. Every mutating endpoint requires an Idempotency-Key, the same key travels upstream to the issuer as the client reference, and a replay resolves to the original result rather than a second movement.

Response 201 Created
{
  "data": {
    "id":            "01HKQW2N8V4X6Z9B3D5F7HJKMN",
    "status":        "active",
    "masked_number":  "••••••••••••4417",
    "balance_minor":  250000,
    "currency":      "USD"
  }
}

Delivered to your endpoint

09:41:02 card.issued evt_01HKQW2N8V
09:41:03 card.authorization evt_01HKQW3P1A
11:07:55 card.recharged evt_01HKR4M6T7
18:22:10 card.terminated evt_01HKS9X2C4

Every delivery carries a timestamped HMAC signature you verify with your endpoint secret.

REST and JSON, one envelope

Predictable success, processing and error envelopes. Public identifiers are ULIDs; internal autoincrement ids never leave the system.

Idempotency required, not offered

A mutating request without an Idempotency-Key is rejected. Reusing a key with a different payload is rejected too, rather than silently accepted.

Signed webhooks, retried

Card and funding events are delivered with an HMAC signature over the timestamp and body, and retried on failure.

Integer minor units end to end

No floating-point value exists anywhere in the money path — not in a request, not in a response, not in a ledger row.

04

What exists today

Virtual card API features: fourteen operations, no roadmap.

Fourteen documented operations across eleven paths, covering issuing, the cardholder registry and funding. Anything not on this list is not something you can call.

Cards
POST /cards Issues a card against a product, to a registry customer, with an initial load. Charges the load plus the product issue fee through hold → provider → settle. Returns 202 with a pending card when the issuer provisions asynchronously.
GET /cards/{card} Returns the card's current state. Poll it while a new card provisions — pending resolves to active.
POST /cards/{card}/recharge Loads more funds onto a live card from the wallet, as a new balanced movement.
POST /cards/{card}/freeze Blocks spend on a card without moving money. Reversed by /unfreeze.
POST /cards/{card}/terminate Ends a card permanently and returns its residual balance to the wallet.
GET /cards/{card}/transactions Provider-reported activity for one card, cursor-paginated.
Cardholders
POST /customers Registers a cardholder identity once. Stored encrypted at rest and submitted to the issuer inside an issue request.
GET /customers/{customer} Reads a registry customer. PAN and security code are never exposed and never persisted.
Funding
POST /deposit-addresses Creates a permanent per-network address that credits the merchant wallet on receipt.
GET /deposits Received deposits, reconciled against the ledger.

Unfreeze, list customers, update a customer and list deposit addresses complete the fourteen.

Every movement resolves to legs that sum to zero.

An authorization does not mutate a balance. It places a hold on the merchant wallet, calls the issuer outside the database transaction, and posts the movement as equal and opposite legs to an insert-only ledger. Corrections are posted as new entries, never as edits.

The ledger is the source of truth for every figure the platform reports, including the ones in the merchant's own dashboard.

ScarabPay Business active

Card number ending 4417

Cardholder
A. HADDAD
Expires
04/29

Ledger excerpt · demonstration data

auth · card_float −2480
auth · settlement_due +2480
movement total 0

05

Shape of the work

Virtual cards for fintechs and businesses.

There is no limit field, no merchant-category rule and no channel switch in this API, and building around one would be building around something that does not exist. What you control is how much a card is funded with — set at issue, changed by recharge, swept back on terminate. Three patterns follow from that.

01

A card per customer

Your platform holds one wallet; each end customer holds a card funded from it. Their exposure is the balance you loaded, and their identity is a record in the cardholder registry rather than a payload you re-send.

02

Payouts issued as cards

Pay a seller or a contractor by issuing a card carrying the amount owed. Add to it with a recharge, and terminate it when the engagement ends — the residual returns to your wallet as a balanced movement.

03

One card per vendor

Issue a separate card per supplier or subscription and fund it with what that relationship is worth. Spend beyond the load does not authorize, and every card's activity is readable on its own.

Frequently asked questions

What is a virtual card API?

It is a REST API your platform calls to issue virtual Visa and Mastercard cards to your own customers, load them with funds, and manage them — freeze, unfreeze, recharge and terminate — without building card issuing yourself.

How the platform works

How are the cards funded?

Each merchant holds a USD wallet. You fund it with stablecoin deposits sent to permanent per-network addresses, credited once the network confirms them. A card's initial load and its issue fee are drawn from that wallet.

How do I control what a card can spend?

Through its balance. You set the amount when you issue the card, add to it with a recharge, block spending with a freeze, and terminate it to return the remaining balance to your wallet.

Read the API reference

How do I know what happens on a card?

Card and funding events are delivered to your endpoint as webhooks signed with HMAC-SHA256 and retried on failure. The same activity can be read per card through the API.

Is ScarabPay a bank?

No. We are not a bank and do not hold a banking licence. Cards are issued through licensed issuing partners.

About us

How do I get started?

Contact us to request access. Your business is verified before live use; sandbox API keys let you integrate with play money in the meantime.

Contact us

Every claim on this page resolves to an operation.

Read what the API does, or write to us with what you are building and we will tell you plainly whether it fits.