Set Up Virtual Collection (Static QR)
A Funding Method is a persistent collection method attached to an account — a static QRPH code and/or virtual account number that remains active until you archive it. Use this for:
- A merchant's permanent QR code displayed at their counter
- A subscriber's persistent billing QR (same code every month)
- A kiosk's embedded QR printed on the machine
Unlike Payment Intents (single-use, exact amount), Funding Methods accept any amount from any payer at any time.
Prerequisites
- A merchant and account already created (Wallet Structure)
- Sandbox credentials from /sandbox
Step 1: Create a Funding Method
Two method types are available:
method_type | What it creates | method_provider |
|---|---|---|
qrph_p2m_reference | Static QRPH QR code | ph_netbank |
bank_account_number | Virtual bank account number | ph_netbank |
The examples below use qrph_p2m_reference. To create a virtual account number instead, set method_type: "bank_account_number" — the response will contain account details in payment_instrument.method_details instead of QR data.
- cURL
- Node.js
- Python
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-X POST "https://api.partners.nextpay.world/v2/funding-methods" \
-H "Content-Type: application/json" \
-d '{
"account_id": "YOUR_ACCOUNT_UUID",
"external_id": "merchant-store-qr",
"payment_instrument_options": {
"method_type": "qrph_p2m_reference",
"method_provider": "ph_netbank"
}
}'
const response = await fetch(
'https://api.partners.nextpay.world/v2/funding-methods',
{
method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from('YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').toString('base64'),
'Content-Type': 'application/json',
},
body: JSON.stringify({
account_id: 'YOUR_ACCOUNT_UUID',
external_id: 'merchant-store-qr',
payment_instrument_options: {
method_type: 'qrph_p2m_reference',
method_provider: 'ph_netbank',
},
}),
}
);
const fundingMethod = await response.json();
import requests
import base64
credentials = base64.b64encode(b'YOUR_CLIENT_ID:YOUR_CLIENT_SECRET').decode()
response = requests.post(
'https://api.partners.nextpay.world/v2/funding-methods',
headers={
'Authorization': f'Basic {credentials}',
'Content-Type': 'application/json',
},
json={
'account_id': 'YOUR_ACCOUNT_UUID',
'external_id': 'merchant-store-qr',
'payment_instrument_options': {
'method_type': 'qrph_p2m_reference',
'method_provider': 'ph_netbank',
},
}
)
funding_method = response.json()
Response
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"account_id": "123e4567-e89b-12d3-a456-426614174001",
"external_id": "merchant-store-qr",
"status": "active",
"created_at": "2025-11-15T10:00:00Z",
"payment_instrument": {
"id": "123e4567-e89b-12d3-a456-426614174002",
"method_type": "qrph_p2m_reference",
"method_provider": "ph_netbank",
"method_details": {
"merchant_name": "Your Merchant Name",
"reference_label": "...",
"routing_account": "...",
"resolution": 480
},
"status": "active",
"persistence_mode": "persistent",
"usage_mode": "multiple"
}
}
Key fields:
payment_instrument.method_details— contains the QRPH data for rendering a static QR code client-side; use a QR code library (e.g.qrcode) to display it.
Step 2: Display or print the QR
For a merchant counter display:
Use a QR code library to render the QRPH data from funding_method.payment_instrument.method_details. For a kiosk or printed material, generate the QR image server-side using a QRPH-compatible library and embed it in your design.
The QR is standard QRPH format compatible with all Philippine bank and e-wallet apps.
Step 3: Handle incoming payment webhooks
When someone pays via this Funding Method, NextAPI sends a v2.payment_instrument.payment_received or v2.payment_instrument.payment_settled event:
app.post('/webhooks/nextapi', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-nextpay-signature'];
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Unauthorized');
}
const event = JSON.parse(req.body);
if (event.event === 'v2.payment_instrument.payment_received' || event.event === 'v2.payment_instrument.payment_settled') {
const { funding_method_id, account_id, amount, payer_reference } = event.payload;
// For static QRs, you may need to match by amount or payer_reference
// to know which subscriber or transaction this corresponds to
await handleIncomingPayment({
fundingMethodId: funding_method_id,
accountId: account_id,
amount,
payerReference: payer_reference,
});
}
res.status(200).send('OK');
});
v2.payment_instrument.payment_received fires when the payment is received (uncleared). v2.payment_instrument.payment_settled fires when funds are cleared and credited to the account. For financial actions (crediting users, triggering orders), listen to payment_settled.
Unlike Payment Intents (which carry your external_id), static Funding Methods accept any payment. Use the amount and payer_reference fields in the webhook payload to match incoming payments to specific invoices or subscribers in your system.
Step 4: List and manage Funding Methods
List all Funding Methods for an account:
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/funding-methods"
Get a specific Funding Method by external ID:
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
"https://api.partners.nextpay.world/v2/funding-methods/external/merchant-store-qr"
Archive a Funding Method (stops accepting new payments):
curl -u "YOUR_CLIENT_ID:YOUR_CLIENT_SECRET" \
-X PATCH "https://api.partners.nextpay.world/v2/funding-methods/YOUR_FUNDING_METHOD_UUID/archive"
Funding Method vs Payment Intent: when to use which
| Funding Method (static) | Payment Intent (dynamic) | |
|---|---|---|
| QR type | Static — same code always | Dynamic — new code per transaction |
| Amount | Any amount from payer | Exact amount specified by you |
| Reuse | Permanent (until archived) | Single-use |
| Use case | Counter QR, kiosk, recurring billing | Checkout, invoice, one-time collection |
| Payment matching | Match by amount or payer reference | Matched via external_id |
→ See Collections Lifecycle for the full state machine comparison.