Issuing
Getting Started with PayMongo Issuing
PayMongo Issuing lets you create and manage Mastercard prepaid cards, funded by your PayMongo Wallet, entirely through the API. Issue virtual cards to your team or your customers, control them by program, and freeze, unfreeze, or cancel them in real time.
This guide walks you through the full flow — setting up a card program, creating cardholders, issuing cards, retrieving card credentials, and managing the card lifecycle — along with every constraint you need to know.
Currently in this releaseIssuing currently supports virtual cards only, billed in PHP, funded by your PayMongo Wallet. Physical cards are on our roadmap.
How Issuing fits together
Issuing is built around three resources, created in this order:
| Resource | What it is |
|---|---|
| Card Program | A grouping mechanism for your cards. Programs let you organize sets of cards for different uses (e.g. "Marketing team", "Customer rewards") and apply the same settings across them. |
| Cardholder | The individual who owns a card — their name, contact details, and address. A cardholder can have one or more cards. |
| Card | The Mastercard prepaid card itself, linked to one cardholder, one card program, and the PayMongo Wallet that funds it. |
So the flow is: create a card program → create a cardholder → create a card under that program for that cardholder.
Prerequisites
- An activated PayMongo Wallet — cards are funded by your wallet, and the wallet must be in a transactable (active) state.
- Your API secret key. All Issuing endpoints use Basic authentication: pass your secret key as the username with a blank password.
Step 1: Create a card program
curl -X POST https://api.paymongo.com/v1/issuing/card-programs \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing Team Cards",
"description": "Virtual cards for the marketing team ad spend"
}'{
"data": {
"id": "card_prog_xxxxxxxx",
"merchant_id": "org_xxxxxxxx",
"name": "Marketing Team Cards",
"description": "Virtual cards for the marketing team ad spend",
"created_at": "2026-08-31T10:45:48.828Z",
"updated_at": "2026-08-31T10:45:48.828Z"
}
}Parameters and constraints
| Parameter | Type | Required | Constraints |
|---|---|---|---|
name | string | Yes | The program's name. |
description | string | Yes | Details about the program. |
You can retrieve a single program with GET /v1/issuing/card-programs/{id} and list all programs with GET /v1/issuing/card-programs (see Pagination below). Card programs can't be updated or deleted through the API — create a new program if your grouping needs change.
Step 2: Create a cardholder
Each card belongs to a person. Register them as a cardholder first:
curl -X POST https://api.paymongo.com/v1/issuing/cardholders \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{
"first_name": "Juan",
"last_name": "Dela Cruz",
"phone": "+639171234567",
"email": "[email protected]",
"address": {
"line1": "123 Ayala Avenue",
"line2": "Unit 4B",
"city": "Makati",
"state": "PH-00",
"postal_code": "1226",
"country": "PH"
}
}'{
"data": {
"id": "ch_xxxxxxxx",
"merchant_id": "org_xxxxxxxx",
"first_name": "Juan",
"last_name": "Dela Cruz",
"phone": "+639171234567",
"email": "[email protected]",
"address": {
"line1": "123 Ayala Avenue",
"line2": "Unit 4B",
"city": "Makati",
"state": "PH-00",
"postal_code": "1226",
"country": "PH"
},
"created_at": "2026-08-31T10:50:12.000Z",
"updated_at": "2026-08-31T10:50:12.000Z"
}
}Parameters and constraints
| Parameter | Type | Required | Constraints |
|---|---|---|---|
first_name | string | Yes | Cardholder's given name. |
last_name | string | Yes | Cardholder's family name. |
phone | string | Yes | Philippine mobile number in +639XXXXXXXXX format. |
email | string | Yes | Must be a valid email address. |
address.line1 | string | Yes | Primary address line. |
address.line2 | string | No | Secondary address line. |
address.city | string | Yes | City. |
address.state | string | No | Province, per ISO 3166-2:PH (e.g. PH-00 for NCR). |
address.postal_code | string | Yes | Postal code. |
address.country | string | Yes | Exactly 2 letters, ISO 3166-1 alpha-2 (e.g. PH). |
A cardholder can hold multiple cards. Cardholders can't be updated or deleted through the API — if a cardholder's details change, create a new cardholder and issue their next card against it. Retrieve one with GET /v1/issuing/cardholders/{id} or list them with GET /v1/issuing/cardholders.
Step 3: Create a card
Issue a virtual card under a program, for a cardholder, funded by your wallet:
curl -X POST https://api.paymongo.com/v1/issuing/cards \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{
"cardholder": "ch_xxxxxxxx",
"card_program": "card_prog_xxxxxxxx",
"type": "virtual",
"account_number": "000001234567"
}'{
"data": {
"id": "card_xxxxxxxx",
"account_number": "000001234567",
"cardholder": "ch_xxxxxxxx",
"card_program": "card_prog_xxxxxxxx",
"name": "Juan Dela Cruz",
"currency": "php",
"type": "virtual",
"status": "active",
"last4": "4242",
"exp_month": 8,
"exp_year": 2031,
"livemode": true,
"created_at": "2026-08-31T11:02:33.000Z",
"updated_at": "2026-08-31T11:02:33.000Z"
}
}Parameters and constraints
| Parameter | Type | Required | Constraints |
|---|---|---|---|
cardholder | string | Yes | An existing cardholder ID belonging to your organization. |
card_program | string | Yes | An existing card program ID belonging to your organization. |
type | string | Yes | Only virtual is supported. |
account_number | string | Yes | The PayMongo Wallet account number that funds the card. Numeric only. The wallet must be active and transactable. |
name | string | No | The name printed on the card. Defaults to the cardholder's full name. |
note | string | No | A free-form internal note. |
currency | string | No | 3-letter code. Defaults to php (the only supported billing currency at this time). |
Constraints to be aware of:
- Card limit per organization. By default you can have a maximum of 5 cards (cancelled cards don't count toward the limit). Attempting to create more returns an error. If you need a higher limit, contact your PayMongo account manager.
- The funding wallet must be transactable. If your wallet is not yet activated, or is frozen or restricted, card creation is rejected with
wallet is not transactable. - Expiry is set automatically. Cards are valid for 5 years from issuance;
exp_monthandexp_yearare returned on the card object. - New cards are typically
activeimmediately and ready to transact.
Step 4: Retrieve card credentials
For security, the card number (PAN) and CVC are never returned by default — not on create, list, or plain retrieve. To get them, retrieve the card with the expand query parameter:
curl -G https://api.paymongo.com/v1/issuing/cards/card_xxxxxxxx \
-u sk_live_xxxxxxxx: \
-d "expand[]=number" \
-d "expand[]=cvc"{
"data": {
"id": "card_xxxxxxxx",
"...": "...",
"last4": "4242",
"number": "5200000000004242",
"cvc": "123"
}
}The only accepted expand values are number and cvc — anything else returns a 400 with invalid expand field.
Handle card credentials with careOnly request
numberandcvcat the moment you need to display them to the cardholder, transmit them over TLS only, and never log or store them on your servers. Everywhere else, uselast4for display.
Step 5: Manage the card lifecycle
A card is always in one of five statuses:
| Status | Meaning | Can transact? |
|---|---|---|
pending | Just issued, not yet usable. | No |
active | Fully functional. | Yes |
locked | Temporarily restricted — e.g. suspected loss or theft. Reversible. | No |
suspended | Restricted due to suspected fraud. | No |
cancelled | Permanently deactivated. Terminal — cannot be undone. | No |
Change a card's status with PATCH /v1/issuing/cards/{id}:
# Freeze a card
curl -X PATCH https://api.paymongo.com/v1/issuing/cards/card_xxxxxxxx \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{ "status": "locked" }'
# Unfreeze it
curl -X PATCH https://api.paymongo.com/v1/issuing/cards/card_xxxxxxxx \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{ "status": "active" }'
# Cancel it permanently
curl -X PATCH https://api.paymongo.com/v1/issuing/cards/card_xxxxxxxx \
-u sk_live_xxxxxxxx: \
-H "Content-Type: application/json" \
-d '{ "status": "cancelled" }'Constraints:
- Accepted
statusvalues on update:active,locked,suspended,cancelled. (pendingcannot be set manually.) - Cancellation is permanent. Once a card is
cancelled, any further update attempt is rejected with422 card is cancelled. Uselockedif you may want to re-enable the card later. - Updating a card to its current status is a no-op and simply returns the card.
- A request with no fields to update returns
400 no fields to update. - Cancelled cards free up room under your card limit — they don't count toward the maximum.
Listing cards
GET /v1/issuing/cards supports filters on top of pagination:
| Query parameter | Description |
|---|---|
status | Filter by status: active, locked, cancelled, pending, or suspended. |
cardholder | Filter by cardholder ID. |
card_program | Filter by card program ID. |
account_number | Filter by funding wallet account number (numeric). |
curl -G https://api.paymongo.com/v1/issuing/cards \
-u sk_live_xxxxxxxx: \
-d "card_program=card_prog_xxxxxxxx" \
-d "status=active" \
-d "limit=20"The list response also includes status_counts — a tally of your cards by status (with all for the total and frozen as the combined count of locked and suspended cards), handy for building a dashboard view:
{
"data": [ { "id": "card_xxxxxxxx", "...": "..." } ],
"has_more": false,
"status_counts": { "all": 3, "active": 2, "locked": 1, "suspended": 0, "cancelled": 0, "pending": 0, "frozen": 1 }
}Pagination
All three list endpoints (card-programs, cardholders, cards) use cursor-based pagination:
| Parameter | Description |
|---|---|
limit | Number of resources to return: 1–100, default 10. |
after | A resource ID; returns results after this cursor (next page). |
before | A resource ID; returns results before this cursor (previous page). |
Use the last resource ID of the current page as after to fetch the next page; has_more tells you whether another page exists.
Error reference
Errors follow the standard PayMongo envelope:
{
"errors": [
{
"code": "domain_error",
"detail": "card creation limit exceeded for this merchant"
}
]
}| HTTP | Code | Detail | Cause / what to do |
|---|---|---|---|
| 400 | invalid_request_body | field-specific message | A required field is missing or a value fails validation (e.g. type not virtual, malformed email, country not 2 letters). |
| 400 | invalid_request_body | no fields to update | A card update was submitted with an empty body. |
| 400 | invalid_query_parameters | invalid expand field | An expand value other than number or cvc. |
| 401 | unauthorized | — | Missing or invalid API key. |
| 404 | not_found | card program not found / cardholder not found / card not found | The ID doesn't exist or doesn't belong to your organization. |
| 422 | domain_error | card creation limit exceeded for this merchant | You've reached your card limit (default 5, excluding cancelled). Cancel unused cards or request a higher limit. |
| 422 | domain_error | card is cancelled | Attempted to update a cancelled card. Cancellation is permanent. |
| 422 | domain_error | wallet is not transactable | The funding wallet isn't active. Activate your wallet or resolve its restriction first. |
| 422 | domain_error | account_number is required | Card creation without the funding wallet's account number. |
FAQ
Which card network are the cards on?
Mastercard. Cards are prepaid and draw on your PayMongo Wallet balance.
Can I issue physical cards?
Not yet — only virtual is accepted today. Physical card support is in development.
How many cards can I create?
Up to 5 non-cancelled cards per organization by default. Contact your account manager if you need more.
Can I update a cardholder's details or a card program?
Not via the API in this release. Create a new cardholder or program instead. Card updates are limited to status changes.
Where do card transactions settle?
Card spend is deducted from the PayMongo Wallet whose account_number funds the card.
What happens when a card expires?
Cards are valid for 5 years from issuance. Issue a new card before exp_month/exp_year passes to keep the cardholder transacting.
Updated 1 day ago
