Getting Started
Universal Pay provides a unified API to accept payments through mobile wallets, bank transfers, and cards in Pakistan. This documentation covers everything you need to integrate payments into your application.
Create a Merchant Account
Sign up and complete your merchant profile in the dashboard.
Generate API Keys
Create API keys with appropriate scopes for your integration.
Create Payment Intents
Use the API to create payment intents and redirect customers to checkout.
Handle Webhooks
Configure webhooks to receive real-time payment status updates.
Base URL
https://api.universalpay.pk/v1Authentication
All API requests must include your API key in the Authorization header. API keys can be created and managed in your merchant dashboard.
API Key Format
API keys follow the format: upk_live_xxxxxxxxxxxxxxxx for production or upk_test_xxxxxxxxxxxxxxxx for sandbox.
Request Header
Authorization: Bearer upk_live_your_api_key_hereAPI Key Scopes
payments:readRead payment informationpayments:writeCreate and modify paymentswebhooks:manageConfigure webhook endpointsPayments
Payment Intents represent a customer's intent to pay. Create a payment intent, redirect the customer to checkout, and handle the result via webhooks.
/v1/payment-intents{
"amount": 150000,
"currency": "PKR",
"merchant_order_id": "order_123456",
"customer_email": "[email protected]",
"customer_name": "John Doe",
"return_url": "https://yoursite.com/payment/complete",
"allowed_methods": ["WALLET", "BANK", "CARD"],
"metadata": {
"product_id": "prod_abc",
"customer_id": "cust_xyz"
},
"idempotency_key": "unique_request_id_123"
}amount (required): Amount in smallest currency unit (paisa for PKR)
currency (required): Three-letter ISO currency code
merchant_order_id: Your internal order reference
return_url (required): URL to redirect after payment
idempotency_key: Unique key to prevent duplicate payments
/v1/payment-intents/:idcurl -X GET https://api.universalpay.pk/v1/payment-intents/pi_abc123def456 \
-H "Authorization: Bearer upk_live_your_api_key"/v1/payment-intents/:id/cancelcurl -X POST https://api.universalpay.pk/v1/payment-intents/pi_abc123def456/cancel \
-H "Authorization: Bearer upk_live_your_api_key"Payment Status Flow
Webhooks
Webhooks notify your server about payment events in real-time. Configure webhook endpoints in your dashboard to receive these notifications.
Webhook Events
payment.createdPayment intent createdpayment.pendingCustomer initiated paymentpayment.succeededPayment completed successfullypayment.failedPayment failedrefund.createdRefund initiatedrefund.succeededRefund completedWebhook Payload
{
"id": "evt_abc123",
"type": "payment.succeeded",
"created_at": "2024-01-15T12:30:00Z",
"data": {
"payment_intent_id": "pi_abc123def456",
"amount": 150000,
"currency": "PKR",
"status": "succeeded",
"provider": "easypaisa",
"provider_payment_id": "EP1234567890"
}
}Signature Verification
All webhooks include an HMAC-SHA256 signature in the X-Webhook-Signature header. Always verify this signature before processing the webhook.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}Security
We take security seriously. Here are the security measures in place and best practices for your integration.
Code Examples
Create a Payment Intent
const axios = require('axios');
async function createPaymentIntent(orderData) {
const response = await axios.post(
'https://api.universalpay.pk/v1/payment-intents',
{
amount: orderData.amount * 100, // Convert to paisa
currency: 'PKR',
merchant_order_id: orderData.orderId,
customer_email: orderData.customerEmail,
return_url: 'https://yoursite.com/payment/complete',
idempotency_key: `order_${orderData.orderId}`,
},
{
headers: {
'Authorization': `Bearer ${process.env.UNIVERSAL_PAY_API_KEY}`,
'Content-Type': 'application/json',
},
}
);
return response.data;
}
// Usage
const payment = await createPaymentIntent({
amount: 1500, // PKR 1,500
orderId: 'order_123',
customerEmail: '[email protected]',
});
// Redirect customer to checkout
res.redirect(payment.checkout_url);