PayTo Integration Guide
Step-by-step instructions for integrating PayTo recurring payments with Azupay
Azupay PayTo Integration Guide
Overview
This guide provides step-by-step instructions for integrating with Azupay's PayTo payment system. PayTo enables recurring payments through pre-approved payment agreements between payers and merchants, providing a secure and efficient way to collect recurring payments.
Prerequisites
Before you begin, ensure you have:
- Valid Azupay API credentials (Secret Key and Client ID)
- Access to either UAT (
https://api-uat.azupay.com.au/v1
) or Production (https://api.azupay.com.au/v1
) environment - Webhook endpoint configured for receiving payment status updates
- Understanding of your payment flow requirements
- Ability to instruct payers to access their banking app or online banking for PayTo agreement approvals
Authentication
All API calls require authentication using your Secret Key in the Authorization header:
Authorization: SECR_${your-client-id}_${your-secret-key}
You can obtain your API keys from the Azupay Client Dashboard. Navigate to the API Keys section to generate and manage your authentication credentials.
Understanding PayTo Approval Process
PayTo agreements require approval directly in the payer's banking app or online banking portal. This is a regulatory requirement that ensures payers have direct control over payment agreements with their bank.
What Happens During Approval:
- After creating a payment agreement via API, the agreement appears as "pending approval" in the payer's banking interface
- The payer logs into their banking app/website and navigates to the PayTo section
- The payer reviews the agreement details (amount limits, frequency, merchant details)
- The payer approves or rejects the agreement
- Once approved, Azupay receives notification from the bank and sends you a webhook
Instructions for Your Payers:
When you create a payment agreement, inform your payers to:
- Open their banking app or log into online banking
- Look for "PayTo" or "Payment Agreements" section
- Find the pending agreement from your business
- Review and approve the agreement
PayTo Payment Flow
PayTo agreements enable recurring payments by establishing a pre-approved payment mandate between the payer and your business.
sequenceDiagram actor Payer as Payer participant Merchant as Merchant participant API as Azupay API participant Bank as Bank Payer ->> Merchant: start transaction opt Create and Approve Agreement (if it hasn't been created) Merchant ->> API: POST /paymentAgreement<br>{PaymentAgreement: {clientTransactionId...}} API ->> Merchant: 201 CREATED<br>{PaymentAgreementStatus: {paymentAgreementId,...}} Payer -->> Bank: Approve payment Agreement Bank -->> API: agreement approved API -->> Merchant: POST /{webhook}<br>{PaymentAgreementStatus: {status:ACTIVE}} end opt Amend the Agreement (if maximumAmount or frequency need to change) Merchant ->> API: POST /paymentAgreement/amendment<br>{PaymentAgreementAmendment: {clientTransactionId, agreementDetails: {...}}} API ->> Merchant: 201 CREATED<br>{PaymentAgreementAmendmentStatus: {amendmentStatus: PENDING}} Payer -->> Bank: Approve payment Agreement Amendment Bank -->> API: agreement amendment approved API -->> Merchant: POST /{webhook}<br>{PaymentAgreementAmendmentStatus: {status:COMPLETED}} end Merchant ->> API: POST /paymentInitiation<br>{PaymentInitiation: {paymentAmount: 12.33, paymentAgreementId, clientTransactionId...}} API ->> Merchant: 201 CREATED<br>{PaymentInitiationStatus: {status: CREATED}} Bank -->> API: initiation completed API -->> Merchant: POST /{webhook}<br>{PaymentInitiationStatus: {status:SETTLED}} Merchant ->> Payer: product fulfilment<br> or payment confirmation
API Documentation:
Step 1: Create Payment Agreement (Optional - if not exists)
If you don't have an active payment agreement for the customer, create one first.
Endpoint: POST /paymentAgreement
Request Payload:
{
"PaymentAgreement": {
"clientId": "CLIENT1",
"clientTransactionId": "TX-AGR-001-20241201-001",
"contractId": "CONTRACT-12345-MONTHLY",
"payerDetails": {
"name": "Jane Smith",
"type": "Person",
"payIDDetails": {
"payID": "[email protected]",
"payIDType": "EMAIL"
}
},
"paymentAgreementType": "OTHER SERVICE",
"description": "Monthly subscription payment",
"agreementDetails": {
"variableAgreementDetails": {
"startDate": "2024-12-01",
"endDate": "2025-12-01",
"maximumAmount": "100.00",
"frequency": "MONTHLY"
}
},
"agreementExpiryMinutes": 1440
}
}
Response:
{
"PaymentAgreementStatus": {
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"status": "CREATED",
"createdDatetime": "2024-12-01T10:00:00.000+11:00"
}
}
Step 2: Payer Approves Agreement
Once the payment agreement is created, instruct the payer to check their banking app or online banking to approve the PayTo agreement. The payer will see a notification or pending agreement in their banking interface that they need to approve. Once approved, you'll receive a webhook notification.
Webhook Notification (Agreement Approved):
{
"PaymentAgreementStatus": {
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"status": "ACTIVE",
"createdDatetime": "2024-12-01T10:00:00.000+11:00",
"registrationDatetime": "2024-12-01T10:15:00.000+11:00"
}
}
Step 3: Amend Agreement (Optional - if maximum amount needs change)
If you need to modify the agreement (e.g., change maximum amount), create an amendment. The payer will need to approve the amendment in their banking app.
Endpoint: POST /paymentAgreement/amendment
Request Payload:
{
"PaymentAgreementAmendment": {
"clientTransactionId": "TX-AMD-001-20241201-001",
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"agreementDetails": {
"variableAgreementDetails": {
"maximumAmount": "150.00"
}
}
}
}
Response:
{
"PaymentAgreementAmendmentStatus": {
"paymentAgreementAmendmentId": "L+8q3FF1sKoNuqnSgXLXFESi93CoBcpIQ3LxhJQzFJB=",
"amendmentStatus": "PENDING",
"createdDatetime": "2024-12-01T11:00:00.000+11:00"
}
}
Step 4: Initiate Payment
Once the agreement is active, initiate payments against it.
Endpoint: POST /paymentInitiation
Request Payload:
{
"PaymentInitiation": {
"clientId": "CLIENT1",
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"clientTransactionId": "TX-PMT-001-20241201-001",
"paymentAmount": "75.50",
"description": "December subscription payment",
"reference": "SUB-DEC-2024"
}
}
Response:
{
"PaymentInitiationStatus": {
"paymentInitiationId": "M+7r2GG0tLpOvroPhaYYGFTj04DpCdqJR4MyiKRzGKC=",
"status": "CREATED",
"createdDatetime": "2024-12-01T12:00:00.000+11:00"
}
}
Step 5: Receive Settlement Webhook
When the payment settles, you'll receive a webhook notification.
Webhook Notification (Payment Settled):
{
"PaymentInitiationStatus": {
"paymentInitiationId": "M+7r2GG0tLpOvroPhaYYGFTj04DpCdqJR4MyiKRzGKC=",
"status": "SETTLED",
"createdDatetime": "2024-12-01T12:00:00.000+11:00",
"completedDatetime": "2024-12-01T12:05:00.000+11:00",
"nppTransactionId": "FTI202412011205001"
}
}
Payment Status Values
PaymentAgreement Status:
- CREATED - Agreement created, awaiting customer approval in their banking app
- ACTIVE - Agreement approved and active
- SUSPENDED - Agreement temporarily suspended
- CANCELLED - Agreement cancelled
- FAILED - Agreement creation failed
PaymentInitiation Status:
- CREATED - Payment instruction created
- PENDING - Payment processing in progress
- SETTLED - Payment completed successfully
- FAILED - Payment failed
- RETURN_IN_PROGRESS - Refund in progress
- RETURN_COMPLETE - Refund completed successfully
- RETURN_FAILED - Refund failed
Additional PayTo Features
Agreement Management
Search Payment Agreements
Endpoint: POST /paymentAgreement/search
Search for payment agreements based on various criteria such as:
- Payment agreement ID
- Contract ID
- Date range (from/to dates)
Example Request:
{
"PaymentAgreementSearch": {
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA="
}
}
Amend Agreement
Endpoint: POST /paymentAgreement/amendment
Create amendments to existing payment agreements to modify details like maximum amount or frequency.
Example Request:
{
"PaymentAgreementAmendment": {
"clientTransactionId": "TX-AMD-001-20241201-002",
"paymentAgreementId": "K+9p4EE0rJnMtomRfWKWEDRh82BnAboHP2KwgIPyEIA=",
"agreementDetails": {
"variableAgreementDetails": {
"maximumAmount": "200.00",
"frequency": "FORTNIGHTLY"
}
}
}
}
Payment Initiation Management
Search Payment Initiations
Endpoint: POST /paymentInitiation/search
Search for payment initiations based on various criteria like client transaction ID or date range.
Example Request:
{
"PaymentInitiationSearch": {
"clientTransactionId": "TX-PMT-001-20241201-001"
}
}
Refund Payment Initiation
Endpoint: POST /paymentInitiation/refund
Initiate a refund for a completed payment initiation.
Webhook Security
For comprehensive webhook security information, refer to the Azupay Webhooks Documentation.
Validating Webhooks
Always validate webhook authenticity by checking the Authorization header against your configured webhook secret. Consider implementing additional security measures:
// Example webhook validation
function validateWebhook(req) {
const expectedAuth = 'Bearer your-webhook-secret';
const receivedAuth = req.headers.authorization;
return expectedAuth === receivedAuth;
}
IP Whitelisting
Implement IP whitelisting to ensure webhooks only come from trusted Azupay servers. Add these security measures to your webhook endpoint:
// Example IP whitelisting for webhook security
function isValidAzupayIP(clientIP) {
// Contact Azupay support to get the current list of webhook IP addresses
const azupayWebhookIPs = [
// Add Azupay's webhook IP addresses here
// Example: '203.0.113.1', '203.0.113.2'
];
return azupayWebhookIPs.includes(clientIP);
}
function validateWebhookSecurity(req) {
const clientIP = req.connection.remoteAddress || req.socket.remoteAddress;
const authHeader = req.headers.authorization;
// Check both IP and authorization
return isValidAzupayIP(clientIP) &&
authHeader === 'Bearer your-webhook-secret';
}
Important: Contact Azupay support to obtain the current list of webhook source IP addresses for your environment (UAT/Production).
Webhook Retry Logic
Azupay will retry webhook deliveries if your endpoint returns a non-2xx status code. Ensure your webhook endpoint:
- Returns 2xx status codes for successful processing
- Is idempotent to handle duplicate deliveries
- Processes webhooks quickly (< 10 seconds)
Best Practices
1. Idempotency
Always use unique clientTransactionId
values to prevent duplicate transactions. If the same ID is used, the API will return the existing transaction instead of creating a duplicate.
2. Webhook Security
Validate webhook authenticity using the Authorization header you configured. Consider implementing webhook signature verification for additional security.
3. Error Handling
Implement robust error handling for network timeouts, API errors, and invalid responses. Use exponential backoff for retrying failed requests.
4. Status Monitoring
Monitor payment statuses regularly and handle edge cases like expired payments or failed settlements appropriately.
5. Testing
Use the UAT environment (https://api-uat.azupay.com.au/v1
) for thorough testing before production deployment.
6. Logging
Log all API requests and responses (excluding sensitive data) for debugging and audit purposes.
Updated about 3 hours ago