API Documentation
Generate EMVCo-compliant Singapore PayNow QR codes via REST API.
Quick Start
1. Create a free account and generate an API key from the dashboard.
2. Include your key in the X-API-Key header.
curl -X POST https://developers.sgpaynowqr.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: sgpn_your_key_here" \
-d '{
"payment_type": "uen",
"uen": "201234567A",
"merchant_name": "My Company",
"amount": 25.00
}'Or use the TypeScript SDK:
npm install @alexhalfborg/sgpaynowqr
import { createClient } from "@alexhalfborg/sgpaynowqr";
const client = createClient("sgpn_your_key_here");
const { data } = await client.generate({
payment_type: "uen",
uen: "201234567A",
merchant_name: "My Company",
amount: 25.00,
});Rate Limits
| Tier | Monthly Limit |
|---|---|
| Free | 50 |
| Starter | 200 |
| Pro | 2,000 |
| Enterprise | 10,000 |
API Reference
Authentication
All requests (except /health) require an API key in the X-API-Key header.
X-API-Key: sgpn_<32 hex characters>Base URL: https://developers.sgpaynowqr.com/api/v1
Get a free API key at developers.sgpaynowqr.com/register
/generateGenerate an EMVCo-compliant PayNow QR code for Singapore payments. Supports UEN, mobile number, and VPA payment types.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| payment_type | string | Required | Type of PayNow paymentValues: uen, mobile, vpa |
| uen | string | Conditional | UEN number (required if payment_type is "uen")Max length: 25 |
| merchant_name | string | Conditional | Merchant name (required if payment_type is "uen")Max length: 25 |
| mobile_number | string | Conditional | Singapore mobile number (required if payment_type is "mobile")Pattern: ^(\+65)?[89]\d{7}$ |
| vpa | string | Conditional | Virtual Payment Address (required if payment_type is "vpa") |
| amount | number | Required | Payment amount in SGDMin: 0.01 · Max: 999999.99 |
| reference | string | Optional | Optional alphanumeric referenceMax length: 25 · Pattern: ^[a-zA-Z0-9]*$ |
| expiry | string | Optional | QR code expiry durationValues: 1h, 2h, 6h, 12h, 24h, none · Default: 24h |
| qr_color | string | Optional | QR code color as 6-digit hex (withoutPattern: ^[0-9a-fA-F]{6}$ · Default: 7d1979 |
| qr_size | integer | Optional | QR code image size in pixelsValues: 200, 300, 400 · Default: 300 |
| include_image | boolean | Optional | Whether to include base64-encoded PNG image in responseDefault: true |
Conditional Requirements
uen— UEN number (required if payment_type is "uen")merchant_name— Merchant name (required if payment_type is "uen")mobile_number— Singapore mobile number (required if payment_type is "mobile")vpa— Virtual Payment Address (required if payment_type is "vpa")
Examples
UEN payment
curl -X POST https://developers.sgpaynowqr.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: sgpn_your_key_here" \
-d '{
"payment_type": "uen",
"uen": "201234567A",
"merchant_name": "My Company",
"amount": 25,
"reference": "INV001"
}'Mobile payment
curl -X POST https://developers.sgpaynowqr.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: sgpn_your_key_here" \
-d '{
"payment_type": "mobile",
"mobile_number": "+6591234567",
"amount": 10.5
}'VPA payment
curl -X POST https://developers.sgpaynowqr.com/api/v1/generate \
-H "Content-Type: application/json" \
-H "X-API-Key: sgpn_your_key_here" \
-d '{
"payment_type": "vpa",
"vpa": "+6591234567#OCBC",
"amount": 5,
"reference": "DONATION"
}'Success Response
Response Headers
| Header | Type | Description |
|---|---|---|
| X-RateLimit-Limit | integer | Monthly request limit for this API key |
| X-RateLimit-Remaining | integer | Remaining requests this month |
| X-RateLimit-Reset | string | When the rate limit resets (1st of next month, SGT) |
| X-Request-Id | string | Unique request identifier |
Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | Missing required fields for the selected payment_type |
| 400 | INVALID_JSON | Malformed JSON body |
| 401 | UNAUTHORIZED | Invalid API key |
| 429 | RATE_LIMIT_EXCEEDED | Monthly usage limit exceeded |
| 500 | — | Internal server error |
/healthNo auth requiredReturns API health status. No authentication required.
Success Response
CORS
All endpoints return CORS headers allowing cross-origin requests:
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: Content-Type, X-API-Key, Accept Access-Control-Max-Age: 86400
Machine-readable specs: OpenAPI YAML · OpenAPI JSON · LLM Reference
API Playground
Use the interactive explorer below to test API requests directly.
Loading API reference...