Card issuance
Use Payscribe cards to issue and manage customer or team spend. Card operations are financial state changes: use server-side credentials, stable references for write operations, and provider-confirmed results before changing your own ledger or customer balance.
- 01Prepare customerConfirm the customer is eligible for the card programme.
- 02Issue cardPersist the returned card ID and restrict sensitive details.
- 03Fund or controlUse a unique ref for every value-changing operation.
- 04Confirm provider stateReconcile card and provider data before changing your ledger.
Use a dashboard-issued sandbox API key on your server. Do not enter credentials into this documentation site.
Card lifecycle
| Stage | Operation | Your application should do |
|---|---|---|
| Prepare | Create or select an eligible customer. | Confirm product/KYC requirements for the card programme. |
| Issue | Create a virtual or physical card. | Store the returned card identifier; never expose sensitive card data unnecessarily. |
| Fund | Top up the card from the supported funding source. | Reconcile the confirmed result before displaying a new balance. |
| Control | Freeze, unfreeze, replace, or terminate. | Treat each action as a state change and refresh card details afterward. |
| Recover funds | Withdraw from the card to the issuing wallet. | Supply a unique ref; credit your own wallet only after provider confirmation. |
Create a card
Create cards from your server using a customer ID, card type, currency, initial amount, and a unique reference where required by your integration.
Use the Node.js SDK guide or PHP SDK guide for typed card creation, top-ups, controls, and error handling. Keep card data on your server and follow this guide for lifecycle and reconciliation rules.
- cURL
- Node.js
- Python
- Go
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,
"ref":"card_issue_order_10021"
}'
const response = await fetch('https://sandbox.payscribe.ng/api/v1/cards/create', {
method: 'POST',
headers: {Authorization: `Bearer ${process.env.PAYSCRIBE_API_KEY}`, 'Content-Type': 'application/json'},
body: JSON.stringify({
"customer_id": "cus_abc123",
"currency": "USD",
"type": "virtual",
"amount": 50,
"ref": "card_issue_order_10021"
}),
});
const result = await response.json().catch(() => null);
if (!response.ok) throw new Error(`Payscribe request failed: ${response.status}`);
console.log(result);
import os
import requests
import json
payload = json.loads(r'''{
"customer_id": "cus_abc123",
"currency": "USD",
"type": "virtual",
"amount": 50,
"ref": "card_issue_order_10021"
}''')
response = requests.post(
'https://sandbox.payscribe.ng/api/v1/cards/create',
headers={'Authorization': f"Bearer {os.environ['PAYSCRIBE_API_KEY']}", 'Content-Type': 'application/json'},
json=payload,
timeout=20,
)
response.raise_for_status()
print(response.json())
package main
import (
"strings"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body := strings.NewReader(`{
"customer_id": "cus_abc123",
"currency": "USD",
"type": "virtual",
"amount": 50,
"ref": "card_issue_order_10021"
}`)
request, err := http.NewRequest(http.MethodPost, "https://sandbox.payscribe.ng/api/v1/cards/create", body)
if err != nil { panic(err) }
request.Header.Set("Authorization", "Bearer "+os.Getenv("PAYSCRIBE_API_KEY"))
request.Header.Set("Content-Type", "application/json")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
responseBody, _ := io.ReadAll(response.Body)
if response.StatusCode < 200 || response.StatusCode > 299 { panic(fmt.Sprintf("Payscribe request failed: %s", response.Status)) }
fmt.Println(string(responseBody))
}
Use the Cards API reference for the current supported card types, fields, and response schema.
Fund or withdraw safely
Both operations alter value. Do not rely only on a previously displayed card balance; reconcile confirmed provider/card state before showing a final result to a user.
- cURL
- Node.js
- Python
- Go
# Withdraw USD from a card back to the issuing wallet.
curl -X PATCH https://sandbox.payscribe.ng/api/v1/cards/card_abc123/withdraw \
-H "Authorization: Bearer $PAYSCRIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"amount":25,"ref":"card_withdraw_order_10021"}'
const response = await fetch('https://sandbox.payscribe.ng/api/v1/cards/card_abc123/withdraw', {
method: 'PATCH',
headers: {Authorization: `Bearer ${process.env.PAYSCRIBE_API_KEY}`, 'Content-Type': 'application/json'},
body: JSON.stringify({
"amount": 25,
"ref": "card_withdraw_order_10021"
}),
});
const result = await response.json().catch(() => null);
if (!response.ok) throw new Error(`Payscribe request failed: ${response.status}`);
console.log(result);
import os
import requests
import json
payload = json.loads(r'''{
"amount": 25,
"ref": "card_withdraw_order_10021"
}''')
response = requests.patch(
'https://sandbox.payscribe.ng/api/v1/cards/card_abc123/withdraw',
headers={'Authorization': f"Bearer {os.environ['PAYSCRIBE_API_KEY']}", 'Content-Type': 'application/json'},
json=payload,
timeout=20,
)
response.raise_for_status()
print(response.json())
package main
import (
"strings"
"fmt"
"io"
"net/http"
"os"
)
func main() {
body := strings.NewReader(`{
"amount": 25,
"ref": "card_withdraw_order_10021"
}`)
request, err := http.NewRequest(http.MethodPatch, "https://sandbox.payscribe.ng/api/v1/cards/card_abc123/withdraw", body)
if err != nil { panic(err) }
request.Header.Set("Authorization", "Bearer "+os.Getenv("PAYSCRIBE_API_KEY"))
request.Header.Set("Content-Type", "application/json")
response, err := http.DefaultClient.Do(request)
if err != nil { panic(err) }
defer response.Body.Close()
responseBody, _ := io.ReadAll(response.Body)
if response.StatusCode < 200 || response.StatusCode > 299 { panic(fmt.Sprintf("Payscribe request failed: %s", response.Status)) }
fmt.Println(string(responseBody))
}
If a withdrawal request times out or the provider response is unclear, keep the same reference and reconcile the card/provider state. Do not mark the withdrawal successful or credit a wallet until it is confirmed.
Manage card state
Use the card identifier to retrieve details and transaction history, top up, withdraw, freeze, unfreeze, replace, update contact information, or terminate the card. Refresh details after a successful action instead of assuming a locally cached balance is authoritative.
React to card events
Card authorisation, settlement, decline, refund, and card-status events should be processed through a verified webhook handler. Store the event ID once, use the raw-body signature verification flow, and reconcile material balance changes with the card provider record.
See Webhooks for secure delivery handling and Card error codes for user-facing recovery guidance.
Build the full workflow
Follow Issue your first card for the end-to-end path. Use the Cards API reference for exact endpoint contracts and References and duplicate protection for write recovery.
Was this page helpful?