Overview
This endpoint creates a payment intent and returns a checkout URL where customers can complete their payment. The checkout session supports multiple payment methods including cards and mobile wallets.
Path Parameters
Request Body
Payment amount (must be greater than 10)
Payment currency (e.g., “PKR”, “USD”)
Payment description (1-200 alphanumeric characters and spaces only) Pattern: ^[A-Za-z0-9 ]{1,200}$
Customer information (optional object, all fields within are also optional) Customer email address (must be valid email format when provided)
Customer CNIC number - must be exactly 13 digits when provided Pattern: ^\d{13}$Example: 3520108345678
Optional shipping address
Order information Order reference (alphanumeric characters) Pattern: ^[A-Za-z0-9]+$
Discount amount or percentage
Webhook URL on your server to receive real-time transaction status updates This should be a publicly accessible HTTPS endpoint in your merchant system that can receive POST requests from Waypay. When a transaction status changes, Waypay will send a webhook notification to this URL with the transaction details. When to use this parameter:
Use this parameter only if you need a dynamic webhook URL that varies per transaction (e.g., session-specific, order-specific URLs)
If your webhook URL is static (same for all transactions), configure it in your Merchant Portal instead. The system will automatically use the portal-configured URL when this parameter is not provided.
Maximum length: 2048 charactersRequired: HTTPS URL that can accept POST requestsExample (Dynamic): https://yoursite.com/api/webhooks/payment?order_id=12345Example (Static): Configure https://yoursite.com/api/webhooks/payment in Merchant Portal and omit this parameterBest Practice: Use the Merchant Portal for static webhook URLs to avoid sending the same URL with every API request. Use this parameter only when you need dynamic, per-transaction webhook URLs.
Webhook Payload Example: {
"id" : "36e98f20908e426fa8a2b67fdfb088f0" ,
"type" : "TransactionStatusChanged" ,
"created" : 1768724277 ,
"livemode" : false ,
"data" : {
"TransactionId" : "829727d1-7193-4177-9da8-9765b18699c3" ,
"PreviousStatus" : "Pending" ,
"CurrentStatus" : "Completed" ,
"Amount" : 20.00 ,
"Currency" : "PKR" ,
"Reason" : null ,
"TransactionReference" : "WPAYTREA51GR85549B81" ,
"CustomerRef" : null ,
"OrderRef" : "{ \" OrderRef \" : \" Abcd12456 \" , \" Discount \" :null, \" Tax \" :null}" ,
"MerchantId" : "dd15c78a-83b0-499f-9e6c-beba37a8f875" ,
"Timestamp" : "2026-01-18T08:17:57.6448041+00:00"
},
"api_version" : "v1"
}
Payment intent type (e.g., “checkout”)
Preferred payment method: If not specified, customer can choose from all available payment methods
Optional JSON string containing additional metadata for the transaction
Request signature for security verification A cryptographic signature generated using MD5 hash algorithm to ensure the integrity and authenticity of the request. The signature is calculated using all request parameters (excluding the signature field itself) combined with your merchant secret key. Format: 32-character lowercase hexadecimal stringExample: a1b2c3d4e5f6789012345678abcdef12Never expose your secret key in client-side code. Always generate signatures on your server.
Learn how to generate signatures: See the complete Signature Generation Guide for step-by-step instructions and implementation examples in C#, Node.js, Python, PHP, and Java.
Response
Unique identifier for the payment intent
URL where customer can complete the payment
Checkout session expiration timestamp
curl --request POST \
--url https://gateway.dev.waypay.live/Gateway/v1/Payment/initiate-checkout \
--header 'SWICH-API-Key: pk_test_xxxxxxxx' \
--header 'Content-Type: application/json' \
--data '{
"amount": 1000,
"currency": "PKR",
"description": "Product Purchase",
"orderRef": {
"orderRef": "ORD123456",
"discount": "10",
"tax": "15"
},
"callbackUrl": "https://yoursite.com/payment/callback",
"intentType": "checkout",
"paymentMethod": 1,
"signature": "a1b2c3d4e5f6789012345678abcdef12"
}'
200 Success
400 Bad Request
401 Unauthorized
422 Unprocessable Content
{
"paymentIntentId" : "550e8400-e29b-41d4-a716-446655440000" ,
"checkoutUrl" : "https://checkout.waypay.com/pay/abc123xyz" ,
"expiresAt" : "2025-12-12T12:00:00Z"
}
Validation Rules
Amount (Required)
Must be a number greater than 10
Format: decimal/double
Description (Required)
Length: 1-200 characters
Pattern: ^[A-Za-z0-9 ]{1,200}$
Only alphanumeric characters and spaces allowed
CNIC (Optional)
Must be exactly 13 digits when provided
Pattern: ^\d{13}$
Example: 3520108345678
Email (Optional)
Must be valid email format when provided
Example: user@example.com
Order Reference (Required)
Alphanumeric characters only
Pattern: ^[A-Za-z0-9]+$
Must be unique per transaction
Required vs Optional Fields
Required Fields
amount - Payment amount
description - Transaction description
orderRef - Order information object
orderRef.orderRef - Unique order reference
signature - Request signature for security verification
Optional Fields
currency - Payment currency (defaults to merchant’s currency)
customerRef - Customer information object
customerRef.name - Customer full name
customerRef.email - Customer email address
customerRef.cnic - Customer CNIC number
customerRef.phone - Customer phone number
customerRef.shippingAddress - Shipping address
customerRef.estimatedDays - Estimated delivery days
orderRef.discount - Discount information
orderRef.tax - Tax information
callbackUrl - Dynamic callback URL for post-payment redirect
intentType - Payment intent type
paymentMethod - Preferred payment method (1: JazzCash, 2: Easypaisa)
metadataJson - Additional metadata
Checkout Session Flow
Create Checkout Session - Call this endpoint with payment details
Receive Checkout URL - Get the checkoutUrl from the response
Redirect Customer - Send customer to the checkout URL
Customer Pays - Customer selects payment method and completes payment
Receive Webhook - You receive webhook notification of payment status
Customer Redirected - Customer is redirected to your callbackUrl with payment status
Checkout sessions expire after a certain period (indicated by expiresAt). After expiration, the customer must initiate a new checkout session.
Callback URL
The callbackUrl parameter specifies a webhook endpoint on your server where Waypay will send real-time transaction status updates.
Static vs Dynamic Webhook URLs
Static Webhook URL (Recommended for most use cases):
Configure once in your Merchant Portal under Webhook Settings
The system automatically uses this URL for all transactions
No need to include callbackUrl in API requests
Easier to manage and update
Best for: Standard integrations where all webhooks go to the same endpoint
Dynamic Webhook URL (Optional):
Provide callbackUrl parameter in each API request
Overrides the portal-configured URL for that specific transaction
Useful for session-specific or order-specific routing
Best for: Multi-tenant systems, session tracking, or custom routing needs
Priority: If both are configured, the callbackUrl parameter in the API request takes precedence over the Merchant Portal setting.
How It Works
When a transaction status changes (e.g., Pending → Completed), Waypay sends a POST request to your callback URL
Your webhook endpoint must accept POST requests and return a 200 OK response
The webhook contains complete transaction details in JSON format
This enables real-time order processing and updates in your system
Webhook Payload Structure
Headers:
Content-Type: application/json
User-Agent: Waypay-Webhook/1.0
Body:
{
"id" : "36e98f20908e426fa8a2b67fdfb088f0" ,
"type" : "TransactionStatusChanged" ,
"created" : 1768724277 ,
"livemode" : false ,
"data" : {
"TransactionId" : "829727d1-7193-4177-9da8-9765b18699c3" ,
"PreviousStatus" : "Pending" ,
"CurrentStatus" : "Completed" ,
"Amount" : 20.00 ,
"Currency" : "PKR" ,
"Reason" : null ,
"TransactionReference" : "WPAYTREA51GR85549B81" ,
"CustomerRef" : null ,
"OrderRef" : "{ \" OrderRef \" : \" Abcd12456 \" , \" Discount \" :null, \" Tax \" :null}" ,
"MerchantId" : "dd15c78a-83b0-499f-9e6c-beba37a8f875" ,
"Timestamp" : "2026-01-18T08:17:57.6448041+00:00"
},
"api_version" : "v1"
}
Webhook Fields
Field Type Description idstring Unique webhook event ID typestring Event type (e.g., “TransactionStatusChanged”) createdinteger Unix timestamp when webhook was created livemodeboolean Whether this is a production transaction data.TransactionIduuid Unique transaction identifier data.PreviousStatusstring Previous transaction status data.CurrentStatusstring New transaction status data.Amountdecimal Transaction amount data.Currencystring Currency code (e.g., “PKR”) data.TransactionReferencestring Payment provider reference number data.OrderRefstring Your order reference (JSON string) data.MerchantIduuid Your merchant identifier data.Timestampdatetime When the status changed
Transaction Statuses
Common status transitions:
Pending → Completed - Payment successful
Pending → Failed - Payment failed
Pending → Cancelled - Payment cancelled by customer
Pending → Expired - Payment session expired
Webhook Endpoint Requirements
Your webhook endpoint must:
Accept POST requests - Waypay sends webhooks via HTTP POST
Use HTTPS - Must be a secure endpoint (SSL/TLS required)
Be publicly accessible - Waypay servers must be able to reach your endpoint
Respond quickly - Return 200 OK within 5 seconds
Handle idempotency - Same webhook may be sent multiple times
Validate authenticity - Verify the webhook is from Waypay (recommended)
Example Webhook Handler
Node.js/Express
Python/Flask
PHP
app . post ( '/api/webhooks/payment' , express . json (), ( req , res ) => {
const webhook = req . body ;
// Validate webhook
if ( webhook . type === 'TransactionStatusChanged' ) {
const { TransactionId , CurrentStatus , Amount , OrderRef } = webhook . data ;
// Parse OrderRef JSON string
const order = JSON . parse ( OrderRef );
// Process based on status
if ( CurrentStatus === 'Completed' ) {
// Update order status in database
// Send confirmation email
// Fulfill order
console . log ( `Payment completed for order ${ order . OrderRef } ` );
} else if ( CurrentStatus === 'Failed' ) {
// Handle failed payment
console . log ( `Payment failed for order ${ order . OrderRef } ` );
}
}
// Always return 200 OK
res . status ( 200 ). send ( 'Webhook received' );
});
Best Practices
Return 200 OK Immediately
Your webhook endpoint should return a 200 OK response as quickly as possible. Process the webhook data asynchronously if needed.
Handle Duplicate Webhooks
Use the webhook id or TransactionId to prevent processing the same event multiple times. Store processed webhook IDs in your database.
Verify Webhook Authenticity
Validate that webhooks are actually from Waypay by checking the source IP or implementing webhook signatures (contact support for details).
Keep logs of all webhook events received for debugging and reconciliation purposes.
The OrderRef field is a JSON string. Always parse it properly to extract your order reference and other data.
Implement handlers for all possible transaction statuses: Completed, Failed, Cancelled, Expired, etc.
Testing Webhooks
In Test Mode:
Use tools like ngrok to expose your local development server
Set the ngrok URL as your callbackUrl
Monitor webhook deliveries in your application logs
Test with various payment scenarios (success, failure, cancellation)
Example ngrok setup:
# Start your local server
npm start # Running on localhost:3000
# In another terminal, start ngrok
ngrok http 3000
# Use the ngrok URL in your callback
# https://abc123.ngrok.io/api/webhooks/payment
Best Practices
Provide Email : Include customer email for payment receipts and notifications
Include Phone : Provide phone number for OTP verification and updates
Set Webhook URL : Configure a reliable callbackUrl webhook endpoint to receive real-time transaction updates
Implement Webhook Handler : Build a robust webhook handler that processes all transaction statuses
Return 200 OK Fast : Your webhook endpoint should respond within 5 seconds
Use Unique Order References : Ensure orderRef is unique per transaction
Store Payment Intent ID : Save the paymentIntentId for future reference
Monitor Expiration : Track expiresAt and handle expired sessions
Process Webhooks Asynchronously : Don’t block webhook responses with long-running tasks
Add Metadata : Use metadataJson for additional context (cart items, customer preferences, etc.)
Validate Before Submit : Pre-validate all data before making the API call
Handle Errors Gracefully : Implement proper error handling and user feedback
The metadataJson field accepts a JSON string with additional information:
{
"metadataJson" : "{ \" cart_items \" : [{ \" id \" : \" PROD123 \" , \" qty \" : 2}], \" promo_code \" : \" SAVE10 \" , \" source \" : \" mobile_app \" }"
}
This metadata is:
Stored with the payment intent
Included in webhook notifications
Retrievable via transaction lookup
Useful for reconciliation and analytics
Security Considerations
Use HTTPS for all callback URLs (webhook endpoints)
Validate webhook authenticity to ensure requests are from Waypay
Verify payment status via the Transaction API for critical operations
Keep API keys secure and never expose in client-side code
Implement CSRF protection on webhook endpoints
Use webhook signatures for verification (contact support for implementation details)
Store webhook IDs to prevent duplicate processing
Sanitize and validate all webhook payload data
Set appropriate expiration times for sessions
Monitor for unusual patterns or abuse
Log all webhook events for audit trail
Testing
Use these test credentials in sandbox mode:
Name : Test User
Email : test@example.com
CNIC : 3520108345678
Phone : 03123456789
Amount : Any amount > 10
Order Reference : TEST-ORD-XXXXX
Common Error Scenarios
Error Cause Solution 400 Bad Request Invalid field format or missing required field Check all required fields and formats 401 Unauthorized Invalid API key Verify API key is correct and active 422 Validation Error Business logic validation failed Check amount, currency, duplicate order ref Expired session Customer took too long to pay Create new checkout session
Next Steps