Wallet QR

Use a QR code to receive money into your PayMongo Wallet or send money out — no account number required.

How Wallet QR works

Wallet QR lets you move money to and from your PayMongo Wallet using QR Ph-standard codes. There are two directions:

  • Receive — generate a QR code that anyone with a QR Ph-compatible app (GCash, Maya, any Philippine bank) can scan to send money directly into your Wallet.
  • Send — scan a recipient's QR code via the API to push money out of your Wallet into theirs.

Both flows run on the QR Ph standard, which means they settle in real time over InstaPay.

Not the same as Payment Acceptance QR Ph. Payment Acceptance QR Ph is for accepting customer payments against a payment intent — it's a checkout flow. Wallet QR is a money-movement tool: it moves funds into or out of your Wallet balance, the same way a bank transfer would. If you're building a checkout, see QR Ph under Payment Acceptance instead.


QR types

Every QR you generate is either static or dynamic.

TypeAmountExpiryBest for
StaticSupplied by the scanner at the time of paymentNone — valid indefinitelyShareable QRs, top-up flows, recurring senders
DynamicEncoded in the QR at generation timeYes — 60 to 9,000 seconds (default: 1,800)One-time requests for a specific amount

Static QRs are convenient for display (a printed QR, a UI element your users scan repeatedly). Dynamic QRs give you precise control over the transaction amount and automatically expire after a set window.


Receiving money: generate a QR

To receive money into your Wallet, generate a QR code and share it. The sender scans it with any QR Ph-compatible app and sends funds directly to your Wallet.

For the full API reference, see Generate an MPM QR.

Required parameters

ParameterTypeValue
nationstringph
modestringp2p
typestringstatic or dynamic
transaction_currencystringPHP

Optional parameters

ParameterTypeNotes
transaction_amountintegerRequired for dynamic QRs. In centavos — ₱100.00 = 10000. Must not be set for static QRs.
expiry_secondsintegerDynamic QRs only. Seconds until expiry, between 60 and 9,000. Defaults to 1,800 (30 minutes).
qr_imagebooleanSet to true to receive a base64-encoded PNG of the QR alongside the QR string. Defaults to false.

Examples

Static QR — sender supplies the amount on scan:

curl --request POST \
  --url https://api.paymongo.com/v3/qr/mpm/generate \
  --header 'Authorization: Basic <base64-encoded-secret-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "nation": "ph",
    "mode": "p2p",
    "type": "static",
    "transaction_currency": "PHP"
  }'

Dynamic QR — amount fixed at ₱500.00, expires in 10 minutes:

curl --request POST \
  --url https://api.paymongo.com/v3/qr/mpm/generate \
  --header 'Authorization: Basic <base64-encoded-secret-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "nation": "ph",
    "mode": "p2p",
    "type": "dynamic",
    "transaction_currency": "PHP",
    "transaction_amount": 50000,
    "expiry_seconds": 600,
    "qr_image": true
  }'

Response

The response includes a qr_string — the raw QR Ph-standard string — and, if qr_image was true, a base64-encoded PNG you can render directly in your UI.

Use the qr_string to render the QR yourself (any standard QR library works), or display the qr_image directly.


Sending money: scan a QR

To send money out of your Wallet, supply the QR string from a scanned QR code. Your Wallet is debited and the encoded recipient's account is credited in real time.

For the full API reference, see Execute Transfer QR.

Required parameters

ParameterTypeNotes
transaction_reference_numberstringA unique identifier you generate for this transaction.
qr_stringstringThe raw QR string decoded from the scanned QR code.
amountfloatRequired if the scanned QR is static (no amount was encoded). In pesos — e.g. 100.50. Not required for dynamic QRs.

Optional parameters

Some QR strings contain placeholder values (***) in their Additional Data Fields. These indicate that the QR generator is requesting the scanner to supply those values. Only fields marked with *** in the original QR can be supplied — any field you pass for a tag that was not present in the original QR will be ignored.

FieldTagNotes
bill_number62/01Arbitrary string, 1–35 characters.
mobile_number62/02Must match +[country code]-[number] format.
store_label62/03Arbitrary string, 1–35 characters.
loyalty_number62/04Arbitrary string, 1–35 characters.
reference_label62/05Arbitrary string, 1–35 characters.
customer_label62/06Arbitrary string, 1–35 characters.
terminal_label62/07Arbitrary string, 1–35 characters.
purpose_of_transaction62/08Arbitrary string, 1–35 characters.

Example

curl --request POST \
  --url https://api.paymongo.com/v2/qr/transfer \
  --header 'Authorization: Basic <base64-encoded-secret-key>' \
  --header 'Content-Type: application/json' \
  --data '{
    "transaction_reference_number": "TXN-20240625-001",
    "qr_string": "00020101021127580012com.p2pqrpay...",
    "amount": 500.00,
    "purpose_of_transaction": "Supplier payment"
  }'

QR lifecycle

Static QRs

Static QRs do not expire. The same code can be scanned and paid multiple times. Each successful scan creates a new inward transfer and a corresponding ledger entry on your Wallet.

Dynamic QRs

Dynamic QRs have a defined expiry window set at generation time (expiry_seconds). Once expired, the QR cannot be paid — the scanner's app will reject it. Generate a new dynamic QR for each transaction where you need to control the amount.

StateMeaning
ActiveWithin the expiry window — can be scanned and paid
ExpiredPast the expiry window — payment will be rejected
PaidSuccessfully paid — the corresponding transfer is recorded on your ledger

Webhooks

Register a webhook endpoint via the Webhooks API to receive real-time notifications on QR activity.

EventTrigger
qr.paidA QR code was successfully paid. Fires for both static and dynamic QRs.
qr.expiredA QR code has expired. For dynamic QRs, fires when the expiry_seconds window elapses. For static QRs, fires only when the QR is explicitly expired via the expire endpoint.

For the payload structure shared across webhook events, see Payload structure.


Limits

QR Ph transfers count against your Wallet's daily outward limit (when sending) and daily inward limit (when receiving). For the QR Ph-specific limits on consumer wallets, see the limits table on the Wallets page.

Per-transaction limits follow the QR Ph network standard. Contact [email protected] for your account's specific limits.

Note: Hitting a wallet limit fails the transfer at submission. Check your Wallet's running totals before issuing high-volume scans.


Related reading