Skip to main content
POST
/
Gateway
/
v
{version}
/
Payment
/
initiate-checkout
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"
  }'
{
  "paymentIntentId": "550e8400-e29b-41d4-a716-446655440000",
  "checkoutUrl": "https://checkout.waypay.com/pay/abc123xyz",
  "expiresAt": "2025-12-12T12:00:00Z"
}

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

version
string
required
API version (e.g., “1”)

Request Body

amount
number
required
Payment amount (must be greater than 10)
currency
string
Payment currency (e.g., “PKR”, “USD”)
description
string
required
Payment description (1-200 alphanumeric characters and spaces only)Pattern: ^[A-Za-z0-9 ]{1,200}$
customerRef
object
Customer information (optional object, all fields within are also optional)
orderRef
object
required
Order information
callbackUrl
string
Webhook URL on your server to receive real-time transaction status updatesThis 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 parameter
Best 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"
}
intentType
string
Payment intent type (e.g., “checkout”)
paymentMethod
integer
Preferred payment method:
  • 1: JazzCash
  • 2: Easypaisa
If not specified, customer can choose from all available payment methods
metadataJson
string
Optional JSON string containing additional metadata for the transaction
signature
string
required
Request signature for security verificationA 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: a1b2c3d4e5f6789012345678abcdef12
Never 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

paymentIntentId
uuid
Unique identifier for the payment intent
checkoutUrl
string
URL where customer can complete the payment
expiresAt
datetime
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"
  }'
{
  "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

  1. Create Checkout Session - Call this endpoint with payment details
  2. Receive Checkout URL - Get the checkoutUrl from the response
  3. Redirect Customer - Send customer to the checkout URL
  4. Customer Pays - Customer selects payment method and completes payment
  5. Receive Webhook - You receive webhook notification of payment status
  6. 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

FieldTypeDescription
idstringUnique webhook event ID
typestringEvent type (e.g., “TransactionStatusChanged”)
createdintegerUnix timestamp when webhook was created
livemodebooleanWhether this is a production transaction
data.TransactionIduuidUnique transaction identifier
data.PreviousStatusstringPrevious transaction status
data.CurrentStatusstringNew transaction status
data.AmountdecimalTransaction amount
data.CurrencystringCurrency code (e.g., “PKR”)
data.TransactionReferencestringPayment provider reference number
data.OrderRefstringYour order reference (JSON string)
data.MerchantIduuidYour merchant identifier
data.TimestampdatetimeWhen the status changed

Transaction Statuses

Common status transitions:
  • PendingCompleted - Payment successful
  • PendingFailed - Payment failed
  • PendingCancelled - Payment cancelled by customer
  • PendingExpired - Payment session expired

Webhook Endpoint Requirements

Your webhook endpoint must:
  1. Accept POST requests - Waypay sends webhooks via HTTP POST
  2. Use HTTPS - Must be a secure endpoint (SSL/TLS required)
  3. Be publicly accessible - Waypay servers must be able to reach your endpoint
  4. Respond quickly - Return 200 OK within 5 seconds
  5. Handle idempotency - Same webhook may be sent multiple times
  6. Validate authenticity - Verify the webhook is from Waypay (recommended)

Example Webhook Handler

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

Your webhook endpoint should return a 200 OK response as quickly as possible. Process the webhook data asynchronously if needed.
Use the webhook id or TransactionId to prevent processing the same event multiple times. Store processed webhook IDs in your database.
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:
  1. Use tools like ngrok to expose your local development server
  2. Set the ngrok URL as your callbackUrl
  3. Monitor webhook deliveries in your application logs
  4. 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

Metadata Usage

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

ErrorCauseSolution
400 Bad RequestInvalid field format or missing required fieldCheck all required fields and formats
401 UnauthorizedInvalid API keyVerify API key is correct and active
422 Validation ErrorBusiness logic validation failedCheck amount, currency, duplicate order ref
Expired sessionCustomer took too long to payCreate new checkout session

Next Steps