POST https://mybundlepay.com/ng/api/v2/virtual-card/create
KEY USAGE POLICY
Important: Always begin your integration using your
test_secret_key. This allows you to simulate virtual card creation without affecting live data.
- Use
test_secret_keyfor development and sandbox testing. - Switch to
live_secret_keyafter approval. - Test calls return simulated responses.
- Live calls create real virtual cards linked to real users.
⚠️ Do not go live without prior testing to avoid failed or blocked API requests.
HEADERS
Authorization * string
Send your {secret_key} as a Bearer token in the header.
Content-Type * application/json
All requests must use JSON body format.
IP WHITELISTING
Your server IP must be whitelisted in your MyBundlePay dashboard for security.
CF-Connecting-IPX-Forwarded-For$request->ip()(fallback)
BODY PARAMS
| Parameter | Required | Description |
|---|---|---|
customerEmail |
✅ | Customer’s registered email address on MyBundlePay enrolled. |
cardBrand |
✅ | Card brand. Example: VisaCard or MasterCard. |
cardType |
✅ | Type of card to be created. Example: virtual. |
reference |
✅ | Unique reference for the card creation request (must be unique per card). |
firstName |
⚠️ Optional | First name of customer. Only allowed in test mode. |
lastName |
⚠️ Optional | Last name of customer. Only allowed in test mode. |
<?php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://mybundlepay.com/ng/api/v2/virtual-card/create',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS =>'{
"customerEmail": "johnsmith@example.com",
"cardBrand": "VisaCard",
"cardType": "virtual",
"reference": "MBP-TEST-0001",
"firstName": "John",
"lastName": "Smith"
}',
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: Bearer {secret_key}'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
const axios = require('axios');
const data = {
customerEmail: "johnsmith@example.com",
cardBrand: "VisaCard",
cardType: "virtual",
reference: "MBP-TEST-0001",
firstName: "John",
lastName: "Smith"
};
axios.post("https://mybundlepay.com/ng/api/v2/virtual-card/create", data, {
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer {secret_key}"
}
})
.then(res => console.log(res.data))
.catch(err => console.error(err.response ? err.response.data : err.message));
Success Response
{
"status": "success",
"message": "MyBundlePay virtual card creation successful.",
"data": {
"id": "xxxxx-ef96-4e07-96e4-xxxxx",
"balance": 200,
"cardNumber": "4334510956482605",
"last4": "2605",
"cardName": "John Smith",
"cardType": "virtual",
"cardBrand": "VisaCard",
"cvv2": "069",
"expiry": "2028-11-01T00:00:00",
"status": "active",
"reference": "MBP-TEST-0001",
"customerEmail": "johnsmith@example.com"
},
"mode": "test"
}
Error Response (Validation)
{
"status": "failed",
"message": "Missing or invalid parameters.",
"errors": {
"customerEmail": ["The customerEmail field is required."]
}
}
Error Response (IP Not Authorized)
{
"status": "failed",
"code": "IP_NOT_AUTHORIZED",
"message": "Your IP is not authorized for API access.",
"ip": "54.86.50.139",
"mode": "live"
}
Error Response (Duplicate Reference)
{
"status": "failed",
"message": "A card with this reference MBP-TEST-0001 exist",
"details": {
"message": "A card with this reference MBP-TEST-0001 exist",
"statusCode": 400
},
"mode": "test"
}
Error Response (Already Exists)
{
"status": "failed",
"message": "A virtual card already exists for this user email.",
"mode": "live"
}