Skip to main content

Issue Your First Card

This recipe walks through creating a customer, issuing a virtual USD card, funding it, and verifying the balance.

Engineering flowBuild, verify, then reconcile
Test this flow in sandbox
  1. 01Create customerCreate or select the customer eligible for a card.
  2. 02Check fundingConfirm the issuing wallet has the required balance.
  3. 03Issue and fundUse a stable reference for every value-changing request.
  4. 04Confirm final stateRefresh provider/card state before showing a balance.

Use a dashboard-issued sandbox API key on your server. Do not enter credentials into this documentation site.

Start in sandbox

The commands below use sandbox values. Replace the placeholder with a ps_pk_test_... key held only in your server environment. Switch both base URL and key together only after the go-live checklist.

Prerequisites

  • A Payscribe business account with approved KYC Level 2
  • Your API key (ps_pk_test_... for sandbox, ps_pk_live_... for production)

Step 1: Create a customer

Every card is linked to a customer. Create one if you don't have a customer ID yet:

curl -X POST https://sandbox.payscribe.ng/api/v1/customers/create \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@example.com",
"phone": "08012345678"
}'

Response:

{
"status": true,
"description": "Customer created successfully.",
"message": {
"details": {
"customer_id": "cus_abc123",
"name": "Jane Doe",
"email": "jane@example.com"
}
},
"status_code": 200
}

Save the customer_id — you'll need it in the next step.

Step 2: Fund your wallet

Cards are funded from your USD wallet. Check your balance first:

curl -X GET https://sandbox.payscribe.ng/api/v1/my-account/balances \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY"

If your USD balance is low, you can:

Step 3: Issue a virtual card

Create a virtual USD card for the customer with an initial top-up amount. The minimum top-up is $1.

curl -X POST https://sandbox.payscribe.ng/api/v1/cards/create \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_abc123",
"currency": "USD",
"type": "virtual",
"amount": 50
}'

Response:

{
"status": true,
"description": "Card created successfully.",
"message": {
"details": {
"event_id": "1e6a0e2b-6f1d-4f2a-9b3e-2c9a6d0f1a2b",
"event_type": "issuing.created.successful",
"trans_id": "3b2f9c7a-4d5e-4a1b-8c6d-9e0f1a2b3c4d",
"ref": "ref_def456",
"card": {
"id": "card_def456",
"card_type": "virtual",
"currency": "USD",
"brand": "VISA",
"name": "JANE DOE",
"first_six": "428852",
"last_four": "3456",
"masked": "428852 **** **** 3456",
"secure_details": {
"alg": "AES-256-GCM",
"iv": "base64-iv",
"tag": "base64-tag",
"data": "base64-ciphertext",
"aad": "bid:123|env:sandbox|card:card_def456"
},
"billing": {
"street": "220 KARAND",
"city": "Yugau",
"state": "JAWA",
"country": "ID",
"postal_code": "8299"
},
"created_at": "2026-07-29T09:15:00.000Z",
"updated_at": "2026-07-29T09:15:00.000Z"
},
"customer": {
"id": "cus_abc123",
"name": "JANE DOE"
}
}
},
"status_code": 201
}

Card number, CVV, and expiry are only available encrypted in card.secure_details (AES-256-GCM, decrypted with your business's Merchant Hash Key from Settings → API Keys) — they are never returned in plaintext.

What's happening:

  • Your wallet is debited the top-up amount
  • The card is issued and activated immediately

Step 4: Verify card balance

Check that the card was created and funded correctly:

curl -X GET "https://sandbox.payscribe.ng/api/v1/cards/card_def456" \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY"

Step 5: Top up the card

Add more funds later:

curl -X PATCH https://sandbox.payscribe.ng/api/v1/cards/card_def456/topup \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount": 100}'

Step 6: Monitor card transactions

Subscribe to these webhook events in the dashboard:

EventWhen it fires
cards.auth.approvedCard used at a merchant (authorization)
cards.auth.settledMerchant captured the authorized amount
cards.adjusted.refundRefund processed
cards.auth.declinedCard declined (check reason in payload)

Full example (Python)

import requests

BASE = "https://sandbox.payscribe.ng/api/v1"
KEY = "ps_pk_test_your_api_key"
HEADERS = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}

# Step 1: Create customer
cust = requests.post(f"{BASE}/customers/create", headers=HEADERS, json={
"first_name": "Jane", "last_name": "Doe",
"email": "jane@example.com", "phone": "08012345678"
}).json()
cid = cust["message"]["details"]["customer_id"]
print(f"Customer: {cid}")

# Step 2: Issue card
card = requests.post(f"{BASE}/cards/create", headers=HEADERS, json={
"customer_id": cid, "currency": "USD", "type": "virtual", "amount": 50
}).json()
card_id = card["message"]["details"]["card"]["id"]
print(f"Card: {card_id}")

# Step 3: Top up
topup = requests.patch(f"{BASE}/cards/{card_id}/topup", headers=HEADERS, json={"amount": 100}).json()
print(f"Top-up — new balance: ${topup['message']['details']['card']['balance']}")

Next steps

Was this page helpful?

Report a docs issue →