Developer documentation
Create payments, share hosted checkouts, and receive verified payment updates.
Introduction
Use the REST API at https://merchant.fvnsmmpanel.shop/api/v1. Requests and responses use JSON. Currency is PHP and amounts are integer centavos. For example, 10000 represents ₱100.00.
Getting started
- Register and verify your email. Wait for sandbox access approval.
- Create a scoped test key at Dashboard → API keys.
- Call
POST /api/v1/paymentsand open the returnedcheckout_url. - Confirm the test payment through the selected simulator and verify the gateway webhook.
Authentication
Send Authorization: Bearer gw_test_… on merchant requests. GET /health is public. Deploy merchant code on your server.
Sandbox mode
Set source to mock for local simulation or provider for PayMongo test credentials and an enabled method. Local scenarios change only their own mock records.
Never scan a provider sandbox QR with a financial app. Use the official simulator link shown by checkout when available.
Live mode
LockedLive keys, merchant acquisition, live checkouts, fund custody, platform fees, settlement funding and payouts require a separately reviewed and authorized release. Test credentials cannot change environments.
API keys
Keys support payments:read, payments:write, refunds:read, refunds:write, webhooks:read and webhooks:write. A newly issued secret is displayed once. Rotation revokes the previous key.
Payment methods
GET /api/v1/payment-methods lists the merchant’s test availability, provider limits and default checkout expiry. Codes are qrph, gcash, maya, grabpay, shopeepay, card, and banking.
Create payment
POST /api/v1/payments requires payments:write and an Idempotency-Key. Use a unique merchant reference per order. Reusing the same key and equivalent request returns the existing resource with HTTP 200. A changed request or a reused reference returns HTTP 409.
{
"amount": 10000,
"currency": "PHP",
"payment_method": "qrph",
"source": "mock",
"reference": "ORDER-1001",
"description": "Order payment",
"success_url": "https://merchant.example/success",
"cancel_url": "https://merchant.example/cancel"
}{
"data": {
"id": "pay_0123456789abcdef01234567",
"reference": "ORDER-1001",
"amount": 10000,
"currency": "PHP",
"payment_method": "qrph",
"status": "created",
"environment": "test",
"source": "mock",
"checkout_url": "https://merchant.fvnsmmpanel.shop/checkout/{token}",
"expires_at": "2026-11-14T04:30:00Z",
"created_at": "2026-11-14T04:00:00Z",
"fees": null
}
}Optional expires_in accepts 60–1800 seconds. Optional callback URLs use a public HTTPS hostname. The merchant checkout token expires independently of provider confirmation. Any returned fees are estimates in centavos.
Retrieve payment
Use GET /api/v1/payments/{id}, GET /api/v1/payments or GET /api/v1/transactions. Lists accept page, limit (1–50), q, status, source, method_code, from, through and sort=oldest. Dates use UTC in YYYY-MM-DD format.
Use the authoritative status field or your verified payment webhook when fulfilling orders.
Hosted checkout and payment links
POST /api/v1/checkout-sessions and POST /api/v1/payment-links use the create payment fields and return the checkout or link ID together with a payment_id. Retrieve either resource through its own GET …/{id} endpoint. Links are single use and bound to the original order.
QRPh integration
Select qrph and open the branded checkout. Provider sandbox checkout initializes a dynamic QRPh payment and points to PayMongo’s official test URL when returned by the upstream response. Local mock generates no provider transaction and displays a downloadable, non-payable PNG after checkout starts.
E-wallet and card integration
For an enabled test account, the branded page hands off to PayMongo’s hosted test authorization. Customers return to the same checkout for server-confirmed status. Card PAN and CVV are entered only on the authorized hosted page. Online banking uses the documented direct online banking channel when enabled in the provider test account.
Webhook integration
POST /api/v1/webhooks accepts url and events. It returns the signing secret once. Use GET /api/v1/webhooks or GET /api/v1/webhooks/{id} to inspect configuration. PATCH accepts enabled or events, and DELETE disables and removes the endpoint from listings.
Verify X-Gateway-Signature, which carries t and v1. Compute a SHA-256 HMAC of t + "." + rawBody, reject timestamps older than five minutes, use a constant-time comparison, and persist the event ID uniquely before acting. Return a 2xx response after safely recording it. Delivery is at least once.
Events include payment.created, payment.pending, payment.paid, payment.failed, payment.expired, payment.cancelled and refund.completed. Each payload includes id, type, environment, created_at and data.
Refunds
POST /api/v1/refunds receives payment_id, amount and reason with an idempotency header. GET /api/v1/refunds/{id} returns the current result. Treat succeeded or a verified refund.completed as confirmation. Provider test support depends on account eligibility.
Errors and limits
Expect 400 for invalid format or missing idempotency, 401 for invalid credentials, 403 for disabled access, 404 for missing or inaccessible resources, 409 for conflicts, 422 for invalid fields, 429 for rate limits, and 5xx for temporary service errors. API requests are limited to 120 per minute per key and 240 per minute per IP.
{
"error": {
"code": "invalid_amount",
"message": "Use integer centavos between 1 and 99999999.",
"request_id": "req_example"
}
}Security
Use HTTPS and server-side secret storage. Restrict gateway scopes, rotate or revoke credentials after exposure, and keep checkout URLs out of analytics and public logs. Verify webhook signatures against raw bytes and reconcile against the payment API.
SDK-free examples
curl -sS https://merchant.fvnsmmpanel.shop/api/v1/payments \
-H "Authorization: Bearer $GATEWAY_TEST_KEY" \
-H 'Idempotency-Key: order-1001-payment' \
-H 'Content-Type: application/json' \
--data '{"amount":10000,"currency":"PHP","payment_method":"qrph","source":"mock","reference":"ORDER-1001","description":"Order payment","success_url":"https://merchant.example/success","cancel_url":"https://merchant.example/cancel"}'<?php
$key = getenv('GATEWAY_TEST_KEY');
$base = getenv('GATEWAY_BASE_URL');
$payload = ['amount' => 10000, 'currency' => 'PHP',
'payment_method' => 'qrph', 'source' => 'mock', 'reference' => 'ORDER-1001'];
$curl = curl_init($base . '/api/v1/payments');
curl_setopt_array($curl, [
CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 12,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json',
'Authorization: Bearer ' . $key, 'Idempotency-Key: order-1001-payment']
]);
$result = curl_exec($curl);
if ($result === false) { throw new RuntimeException('Gateway connection failed.'); }
$status = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE);
$data = json_decode($result, true);
if ($status >= 300) { throw new RuntimeException($data['error']['code'] ?? 'gateway_error'); }
echo $data['data']['checkout_url'];const response = await fetch(process.env.GATEWAY_BASE_URL + '/api/v1/payments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + process.env.GATEWAY_TEST_KEY,
'Idempotency-Key': 'order-1001-payment'
},
body: JSON.stringify({ amount: 10000, currency: 'PHP',
payment_method: 'qrph', source: 'mock', reference: 'ORDER-1001' })
});
const result = await response.json();
if (!response.ok) throw new Error(result.error.code);
console.log(result.data.checkout_url);