API v1 · TEST

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

  1. Register and verify your email. Wait for sandbox access approval.
  2. Create a scoped test key at Dashboard → API keys.
  3. Call POST /api/v1/payments and open the returned checkout_url.
  4. 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

Locked

Live 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.

JSON request
{
    "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"
}
HTTP 201 example
{
    "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 response
{
  "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

Create a payment with cURL
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 server request
<?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'];
JavaScript server request
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);

Confirm this action