Want a working virtual card issuing API example you can copy and run? You are in the right place.
This page shows the real requests and responses for our card API. You will create a card, fund it, control it, and catch its events. Every snippet is copy-paste ready.
You can test the whole flow in our sandbox first, with no real money.
In short: To issue a card with the Gpaynow API, send a POST /v1/cards request with your API key, a card type, and a spend limit. You get back a card token, and, if allowed, the PAN, CVV, and expiry. Then fund the card, control it, and read its transactions through simple REST calls. This page gives the full example.
Key takeaways
✅ Issue a virtual card with one POST /v1/cards call, and read the card details from the JSON response.
✅ Fund, freeze, unfreeze, and cancel cards with clear REST endpoints.
✅ Listen to webhooks to track each transaction in real time.
✅ Test everything in the sandbox before you go live.
Before you start
You need two things to run this example: a Gpaynow account and your API key. Both take a minute to set up.
Sign up, then open your dashboard to find your keys. Use your test key (it starts with sk_test_) so no real money moves.
The base URL for all calls is:
https://api.gpaynow.com/v1
All requests use JSON. All responses come back as JSON too.
Step 1: Authenticate
You authenticate by sending your API key as a Bearer token. Add it to the Authorization header on every request.
Authorization: Bearer sk_test_51H8x...
Content-Type: application/json
Keep your secret key safe. Never put it in front-end code or a public repo.
Step 2: Create a virtual card
To create a card, send a POST /v1/cards request with the card type and a spend limit. The card is issued in under a second.
Request:
curl https://api.gpaynow.com/v1/cards \
-H "Authorization: Bearer sk_test_51H8x..." \
-H "Content-Type: application/json" \
-d '{
"cardholder_id": "ch_123",
"type": "virtual",
"brand": "visa",
"currency": "usd",
"spend_limit": 5000,
"spend_limit_interval": "per_authorization",
"single_use": false,
"allowed_categories": ["software", "advertising"]
}'
Response:
{
"id": "card_9f2a1",
"object": "card",
"type": "virtual",
"brand": "visa",
"state": "open",
"last_four": "4242",
"pan": "4242424242424242",
"cvv": "123",
"exp_month": 12,
"exp_year": 2029,
"currency": "usd",
"spend_limit": 5000,
"created": "2026-07-18T10:00:00Z"
}
The spend_limit is in the smallest unit (cents), so 5000 means $50.00. Store the id; you use it for every call after this.
Step 3: Fund the card
To fund a card, send a POST /v1/cards/{id}/fund request with an amount. The balance is ready to spend right away.
Request:
curl https://api.gpaynow.com/v1/cards/card_9f2a1/fund \
-H "Authorization: Bearer sk_test_51H8x..." \
-H "Content-Type: application/json" \
-d '{ "amount": 5000, "currency": "usd" }'
Response:
{
"id": "card_9f2a1",
"balance": 5000,
"currency": "usd",
"state": "open"
}
Step 4: Check the card balance
To read a card’s balance, send a GET /v1/cards/{id}/balance request. You get the current and available amounts.
curl https://api.gpaynow.com/v1/cards/card_9f2a1/balance \
-H "Authorization: Bearer sk_test_51H8x..."
{
"card_id": "card_9f2a1",
"balance": 4200,
"available": 4200,
"currency": "usd"
}
Step 5: List transactions
To see spend on a card, send a GET /v1/transactions request with the card id. You get each charge with its status.
curl "https://api.gpaynow.com/v1/transactions?card_id=card_9f2a1" \
-H "Authorization: Bearer sk_test_51H8x..."
Response:
{
"object": "list",
"data": [
{
"id": "txn_51",
"card_id": "card_9f2a1",
"amount": 800,
"currency": "usd",
"merchant": "OpenAI",
"status": "approved",
"created": "2026-07-18T11:00:00Z"
}
],
"has_more": false
}
Control a card: freeze, unfreeze, cancel
You control a card’s state with three calls. Freeze to pause it, unfreeze to resume, and cancel to close it for good.
curl https://api.gpaynow.com/v1/cards/card_9f2a1/freeze \
-H "Authorization: Bearer sk_test_51H8x..." -X POST
{ "id": "card_9f2a1", "state": "paused" }
Unfreeze the card with POST /v1/cards/card_9f2a1/unfreeze. It returns "state": "open".
Cancel the card for good:
curl https://api.gpaynow.com/v1/cards/card_9f2a1 \
-H "Authorization: Bearer sk_test_51H8x..." -X DELETE
{ "id": "card_9f2a1", "state": "closed" }
Want to go deeper on limits and rules? See our spending controls docs.
Handle webhooks
Webhooks tell your app about card events as they happen. We send a POST to your URL for each event, so you do not have to poll.
A transaction.created event looks like this:
{
"id": "evt_8890",
"type": "transaction.created",
"created": "2026-07-18T11:00:00Z",
"data": {
"id": "txn_51",
"card_id": "card_9f2a1",
"amount": 800,
"currency": "usd",
"merchant": "OpenAI",
"status": "approved"
}
}
Always check the signature before you trust an event. We sign each webhook with your secret, and send the signature in the Gpaynow-Signature header. Compare it with an HMAC-SHA256 hash of the raw body.
Common event types: card.created, card.updated, transaction.created, transaction.declined, transaction.refunded, and card.expired.
Handle errors
When a call fails, we return a clear JSON error with a code and a message. Read the code to decide what to do next.
{
"error": {
"code": "insufficient_funds",
"message": "The card balance is too low for this charge.",
"type": "card_error"
}
}
Common error codes:
| HTTP |
Code |
What it means |
| 401 |
authentication_error |
The API key is missing or wrong. |
| 400 |
invalid_request |
A field is missing or the wrong type. |
| 402 |
insufficient_funds |
The card balance is too low. |
| 404 |
card_not_found |
No card with that ID. |
| 429 |
rate_limit |
Too many requests. Slow down. |
To make a request safe to retry, send an Idempotency-Key header with a unique value. If the call repeats, we return the first result instead of making a second card.
Use an SDK
You can skip raw HTTP and use an SDK. Here is the same card creation in three languages.
Node.js:
import Gpaynow from "gpaynow";
const gp = new Gpaynow("sk_test_51H8x...");
const card = await gp.cards.create({
type: "virtual",
brand: "visa",
currency: "usd",
spend_limit: 5000
});
console.log(card.pan);
Python:
import gpaynow
gp = gpaynow.Client("sk_test_51H8x...")
card = gp.cards.create(
type="virtual",
brand="visa",
currency="usd",
spend_limit=5000,
)
print(card.pan)
PHP:
$gp = new \Gpaynow\Client('sk_test_51H8x...');
$card = $gp->cards->create([
'type' => 'virtual',
'brand' => 'visa',
'currency' => 'usd',
'spend_limit' => 5000,
]);
echo $card->pan;
We also ship SDKs for Laravel, Java, Go, and .NET. Grab them from your dashboard.
Frequently asked questions
How do I get an API key?
Sign up for Gpaynow, then open your dashboard. Your test and live keys are on the API keys page. Use the test key to build safely.
What is the base URL for the API?
The base URL is https://api.gpaynow.com/v1. All requests and responses use JSON.
Is there a sandbox to test in?
Yes. Your test key runs in a full sandbox with test cards and fake transactions, so you can build the flow with no real money.
How do I create a virtual card with the API?
Send a POST /v1/cards request with a card type and a spend limit. You get back the card token, and, if allowed, the PAN, CVV, and expiry. See the example above.
How do I handle webhooks safely?
Check the Gpaynow-Signature header on each event. Compare it with an HMAC-SHA256 hash of the raw body, using your secret, before you trust the data.
How do I make a request safe to retry?
Send an Idempotency-Key header with a unique value. If the same call repeats, we return the first result, so you never create two cards by mistake.
What are the rate limits?
Each key has a request limit per second. If you go over, you get a 429 rate_limit error, so add a short backoff and retry.
Why was a card charge declined?
Common reasons are a low balance, a spend limit hit, or a blocked merchant type. Read the transaction.declined webhook for the exact reason.
Start building with the Gpaynow card API
You have the full example. Now make it yours.
Sign up, grab your test key, and issue your first virtual card in minutes. When you are ready, switch to your live key and go.