API reference
Every endpoint, generated from the same source as the OpenAPI spec. Base URL: https://www.primcard.io/api/partner/v1 · auth: Authorization: Bearer sk_… · amounts in cents.
Account
Key check and balance.
get/pingCheck your key
Responses
200— The key works.401— Unknown, revoked, or malformed API key.
get/balanceYour funding balance
Responses
200— Balance for the key's mode.401— Invalid key.
Products
The card BINs you may issue on.
get/productsYour available BINs
The card products (BINs) enabled for your account. Use a product_code from here as the optional `product_code` on POST /cards; omit it to use the one marked is_default.
Responses
200— Your allowed products.
Cards
Create and manage virtual cards.
get/cardsList cards
Parameters
limit(query)starting_after(query) — Card id to paginate after.external_ref(query)status(query)
Responses
200— Newest first.
post/cardsCreate a card
Creates AND funds a USD virtual card in one call. The card receives `amount`; your balance is debited `amount` + issuance fee + top-up fee (see POST /quotes). 201 = active immediately; 202 = the network accepted it and it activates within minutes — poll GET /cards/{id} or listen for the card.issued webhook.
Parameters
Idempotency-Key(header, required) — Required on every money-moving POST. Reuse the SAME key when retrying the same request — the stored response is replayed instead of moving money twice. A new request needs a new key.
Request body
object amount*: integer — Cents to land on the card. Example: 10000 = a $100.00 card. external_ref*: string — Your id for this card — unique per account, lets you key cards by your own system. product_code: string — Optional. The BIN/product to issue on — must be one of your GET /products entries. Omit to use your default. card_name: string — Display label. cardholder_first_name: string cardholder_last_name: string email: string
Responses
201— Card active and funded.202— Accepted — card is funding_pending.400— Validation problem or missing Idempotency-Key.402— insufficient_funds or provider_declined.409— external_ref_taken, idempotency_in_flight, or no_product_configured.422— limit_exceeded, idempotency_conflict, or product_not_allowed.
get/cards/{cardId}Card details (polling target)
Parameters
cardId(path, required)
Responses
200— The card.404— Not on this account (or wrong mode).
post/cards/{cardId}/topupsTop up a card
Adds `amount` to an active card; your balance is debited `amount` + the top-up fee. 202 means the network is completing it asynchronously — the topup.succeeded webhook (or card polling) confirms.
Parameters
cardId(path, required)Idempotency-Key(header, required) — Required on every money-moving POST. Reuse the SAME key when retrying the same request — the stored response is replayed instead of moving money twice. A new request needs a new key.
Request body
object amount*: integer
Responses
201— Funded.202— Accepted, completing asynchronously.402— insufficient_funds or provider_declined.409— invalid_state — only active cards top up.
post/cards/{cardId}/freezeFreeze (reversible)
Parameters
cardId(path, required)
Responses
200— Frozen — authorizations decline until unfrozen.409— invalid_state.
post/cards/{cardId}/unfreezeUnfreeze
Parameters
cardId(path, required)
Responses
200— Active again.409— invalid_state.
post/cards/{cardId}/blockBlock (PERMANENT)
Irreversible. Remaining card balance is released back to your PrimCard balance. Cancel recurring subscriptions first — merchants can keep submitting debits after a block, and those still generate fees.
Parameters
cardId(path, required)
Responses
200— Blocked; balance released.409— invalid_state.
get/cards/{cardId}/transactionsSettled transactions
Parameters
cardId(path, required)limit(query)
Responses
200— Newest first.
get/cards/{cardId}/secure-detailsFull card number + CVV (restricted)
Returns PAN, CVV and expiry, fetched live from the card network. DISABLED by default — PrimCard enables it per account after review. Hard limits: 3/minute and 20/day, fail-closed. Never store what this returns; request it again when needed.
Parameters
cardId(path, required)
Responses
200— Sensitive — response is never cached or logged.403— secure_details_disabled — not enabled for this account.429— Reveal limit reached.
Funding
Move money into your PrimCard balance (live mode).
post/funding/deposit-addressGet a USDT deposit address (live keys)
Fresh USDT (TRC-20) address for the stated amount. Send exactly that amount; your balance credits automatically on confirmation (deposit.confirmed webhook / GET /funding/deposits). Addresses expire in ~8 hours — request a new one per deposit.
Request body
object amount*: integer — Intended deposit in cents.
Responses
201— The deposit instruction.403— test_key_not_allowed — use POST /test/credit in sandbox.
get/funding/depositsDeposit history / status
Parameters
limit(query)
Responses
200— Newest first.
Pricing
Preview fees before committing.
post/quotesPreview fees
Exactly what a card creation or top-up would cost right now, including any negotiated rates on your account. Read-only.
Request body
object type*: string (card_issue | card_topup) amount*: integer — Cents to land on the card.
Responses
200— The fee breakdown.400— Invalid type or amount.
Test mode
sk_test_ only — sandbox helpers.
post/test/creditSandbox faucet
Credits pretend money to your TEST balance (sk_test_ keys only, max $100,000 per call, 60/hour).
Parameters
Idempotency-Key(header, required) — Required on every money-moving POST. Reuse the SAME key when retrying the same request — the stored response is replayed instead of moving money twice. A new request needs a new key.
Request body
object amount*: integer
Responses
201— New test balance.403— live_key_not_allowed.
post/test/cards/{cardId}/simulate-transactionSimulate card spend
Fakes a purchase or decline on a TEST card and runs the real settlement pipeline — fees post, the transaction appears in GET /cards/{id}/transactions, and the card.transaction.created webhook fires.
Parameters
cardId(path, required)
Request body
object type*: string (purchase | decline) amount*: integer
Responses
201— Simulated and processed.403— live_key_not_allowed.409— invalid_state — card must be active.