POST/v1/cards/issue

Issue a card

Creates a virtual card and loads it in one call. The load is debited from your wallet at this store, and the card is only created after the issuer accepts — a refusal refunds automatically.

Required scope: cards.writeRate limit: 10 rps

Idempotent by design: send the same Idempotency-Key and you get the original result back with 200 and no second charge. Changing the body while reusing a key is refused outright rather than silently issuing a second card.

Parameters

tierstringrequired

"basic" or "plus". The tier decides the programme and the fees, not the design.

countrystringrequired

Two-letter ISO country code of the card programme, e.g. "US". Must be exactly 2 characters.

load_usdstringrequired

Amount to load, as a STRING in US dollars (e.g. "50.00"), up to 4 decimals, greater than 0 and at most 100000. A number instead of a string is a validation_failed, on purpose: JSON floats are not how money travels here.

cardholder_namestringoptional

Optional name printed on the card, 2–60 characters.

Idempotency-Keystringrequired

Required, at least 8 characters. Reuse it to retry safely; never reuse it for a different request.

Code samples

curl -X POST "https://samaprime.com/api/v1/cards/issue" \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 0e7f5c1e-2b3a-4f6d-9c8b-1a2b3c4d5e6f" \
-d '{"tier":"example","country":"example","load_usd":"example","cardholder_name":"example"}'

Response

→ 201
{
"data": {
"id": "cm_card_01J8Z1A2BBCCDD",
"last4": "1234",
"status": "active"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-08-06T12:00:00Z"
}
}

Errors

StatusCode
400validation_failed

The body is malformed, or carries a field this endpoint does not accept — the schema is strict, so provider or BIN choices cannot be sent from here.

400invalid_amount

load_usd is not a plain amount. It must be a string like "20.00" with at most 2 decimal places of value ("20.0000" is fine, "20.005" is not) — a JSON number, or anything finer than a cent, is refused before any money is quoted. Nothing is rounded.

400idempotency_key_required

There is no Idempotency-Key header, or it is shorter than 8 characters. Nothing was charged: issuance debits money, so this endpoint will not run at all without a key to replay against.

403test_key_not_allowed

A test key (sk_test_) cannot move money: card writes need a live key. Nothing was reserved and the wallet was not touched.

403cards_not_enabled_for_store

Card issuing through the API is not enabled for this store. A platform administrator must enable it. Nothing was charged, and this Idempotency-Key was not used up: the same key may be sent again once issuing is enabled.

409cards_unavailable

Card issuing is temporarily unavailable: the card provider cannot serve right now (issuing paused, provider under maintenance, or its balance known to be exhausted). Refused before anything was claimed or charged — the wallet was not touched and no order is waiting. This Idempotency-Key was not used up: retry later with the same key.

400country_unavailable

No selectable card programme exists for that country and tier. This is how the platform is configured, not something a rewritten body can fix.

400no_provider

No issuer is configured for that tier at all, so no card of it can be bought. Retrying cannot change the answer.

400below_minimum

The load is below the minimum this card type accepts. Raise load_usd.

400invalid_input

The request passed the body schema and was then refused by the issuance engine's own validation — the tier, the resolved BIN or the amount is not usable as sent.

400tier_unavailable

That card tier is not offered right now.

400bin_not_selectable

The BIN the platform resolved for that country and tier is disabled, unknown, or belongs to a different issuer. Do not replay the same pair; the platform-side choice is what has to change.

400provider_bin_unavailable

The chosen BIN is temporarily unavailable at the issuer. A different tier or country can succeed where this pair cannot — and you have not been charged.

422insufficient_customer_balance

Your wallet at this store cannot cover the load plus its fees. Fund the wallet; replaying the same request cannot succeed, and this is not a platform outage.

422provider_insufficient_funds

The platform's own float at the issuer is exhausted. Nothing was charged to you — raising it is ours to do, not something you can retry past.

500recording_failed

DO NOT RETRY THIS ONE. The issuer created the card and our write of it failed, so the money is already spent and the card is held for reconciliation. A second attempt is a second card.