TL;DR
The iPay API enables developers to integrate payment processing, invoicing, and financial transactions programmatically. It uses OAuth 2.0 and API key authentication, RESTful endpoints for payments, refunds, transactions, and reconciliation, with PCI DSS compliance requirements and industry-standard rate limits. This guide covers authentication setup, payment processing, webhook integration, security compliance, and production deployment strategies.
Introduction
Digital payment processing handles over $8 trillion annually worldwide. For developers building e-commerce platforms, SaaS applications, or marketplace solutions, payment API integration is essential for accepting customer payments securely and compliantly.
Businesses can lose 5โ10% of revenue to failed payments, manual reconciliation, and payment fraud. A solid payment API integration automates payment processing, reduces failures with retry logic, enables automatic reconciliation, and supports fraud detection.
This guide walks through payment API integration end to end: authentication, payment processing, refunds, customer management, webhooks, PCI DSS requirements, and production deployment.
๐ก Apidog simplifies payment API testing. Test payment endpoints in sandbox mode, validate webhook signatures, inspect transaction responses, and debug integration issues in one workspace. Import API specifications, mock responses, and share test scenarios with your team.
Note: This guide covers general payment API integration patterns applicable to iPay and similar payment processors. Specific endpoint URLs and authentication details may varyโalways refer to official iPay documentation for implementation details.
What Is the iPay API?
Payment APIs like iPay provide RESTful interfaces for processing financial transactions. Typical capabilities include:
- Payment authorization and capture
- Refunds and chargebacks
- Transaction history and reporting
- Customer tokenization (vault)
- Subscription and recurring billing
- Invoice generation and management
- Reconciliation and settlement
- Fraud detection and prevention
Key Features
| Feature | Description |
|---|---|
| RESTful API | JSON-based endpoints |
| OAuth 2.0 + API Keys | Secure authentication |
| Webhooks | Real-time payment notifications |
| Tokenization | Secure card storage |
| 3D Secure | SCA compliance |
| PCI DSS | Level 1 compliance required |
| Multi-Currency | 100+ currencies supported |
| Fraud Tools | Risk scoring and velocity checks |
Payment Flow Overview
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ Customer โโโโโถโ Merchant โโโโโถโ Payment โ
โ (Browser) โ โ (Server) โ โ Gateway โ
โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ
โ โ โ
โ 1. Enter Card โ โ
โโโโโโโโโโโโโโโโโโโโโถโ โ
โ โ โ
โ 2. Tokenize โ โ
โโโโโโโโโโโโโโโโโโโโโถโ 3. Create Intent โ
โ โโโโโโโโโโโโโโโโโโโโโถโ
โ โ โ
โ โ 4. Confirm Paymentโ
โ โโโโโโโโโโโโโโโโโโโโโถโ
โ โ โ
โ โ 5. Result โ
โ โโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โ 6. Receipt โ โ
โโโโโโโโโโโโโโโโโโโโโโ โ
Keep sensitive card data on the client. Your server should receive a token or payment method ID, then create or confirm the payment through the provider API.
API Environments
| Environment | URL | Use Case |
|---|---|---|
| Sandbox | https://sandbox.ipay.com/api |
Development and testing |
| Production | https://api.ipay.com/api |
Live transactions |
Getting Started: Authentication Setup
Step 1: Create an iPay Account
Before accessing the API:
- Visit iPay merchant registration.
- Complete business verification (KYB).
- Submit the required documents:
- Business registration
- Bank account details
- Government ID
- Wait for approval, which may take 1โ3 business days.
Step 2: Generate API Credentials
In the iPay Merchant Dashboard:
- Go to Settings > API Keys.
- Create a new API key.
- Copy the key and secret into your secret manager or local environment file.
# .env file โ NEVER commit this file to git
IPAY_API_KEY="live_xxxxxxxxxxxxxxxxxxxx"
IPAY_API_SECRET="secret_xxxxxxxxxxxxxxxxxxxx"
IPAY_WEBHOOK_SECRET="whsec_xxxxxxxxxxxxxxxxxxxx"
Use separate credentials for sandbox and production.
Step 3: Choose an Authentication Method
| Method | Best For | Security Level |
|---|---|---|
| Basic Auth | Server-to-server integrations | High |
| OAuth 2.0 | Multi-tenant applications | Higher |
| JWT | Microservices | High |
Step 4: Create a Reusable API Client
Centralize authentication, JSON headers, idempotency keys, and error handling in one function.
const IPAY_BASE_URL = process.env.IPAY_SANDBOX
? 'https://sandbox.ipay.com/api'
: 'https://api.ipay.com/api';
const ipayRequest = async (endpoint, options = {}) => {
const apiKey = process.env.IPAY_API_KEY;
const apiSecret = process.env.IPAY_API_SECRET;
// Basic authentication (Base64 encoded)
const authHeader = Buffer.from(`${apiKey}:${apiSecret}`).toString('base64');
const response = await fetch(`${IPAY_BASE_URL}${endpoint}`, {
...options,
headers: {
Authorization: `Basic ${authHeader}`,
'Content-Type': 'application/json',
'Idempotency-Key': options.idempotencyKey || generateIdempotencyKey(),
...options.headers
}
});
if (!response.ok) {
const error = await response.json();
throw new Error(`iPay API Error: ${error.message}`);
}
return response.json();
};
function generateIdempotencyKey() {
return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
}
// Usage
const account = await ipayRequest('/account');
console.log(`Merchant: ${account.business_name}`);
Payment Processing
Create a Payment Intent
Create payments from your server, using amounts in the smallest currency unit. For USD, $29.99 becomes 2999.
const createPayment = async (paymentData) => {
const payment = {
amount: paymentData.amount,
currency: paymentData.currency || 'USD',
customer: paymentData.customerId,
payment_method: paymentData.paymentMethodId,
confirm: true,
description: paymentData.description,
metadata: {
orderId: paymentData.orderId,
customerId: paymentData.customerId
},
capture_method: paymentData.captureMethod || 'automatic',
statement_descriptor: paymentData.statementDescriptor || 'MYCOMPANY'
};
return ipayRequest('/payments', {
method: 'POST',
body: JSON.stringify(payment),
idempotencyKey: paymentData.idempotencyKey
});
};
// Usage
const payment = await createPayment({
amount: 2999, // $29.99
currency: 'USD',
customerId: 'cus_12345',
paymentMethodId: 'pm_67890',
description: 'Order #ORD-001',
orderId: 'ORD-001',
statementDescriptor: 'MYCOMPANY INC'
});
console.log(`Payment status: ${payment.status}`);
console.log(`Payment ID: ${payment.id}`);
Generate and persist one idempotency key per checkout attempt. Reuse it if your application retries the same payment request.
Payment Status Flow
requires_payment_method โ requires_confirmation โ requires_action
โ processing โ requires_capture โ succeeded
โ failed
โ canceled
Your application should treat payment status as asynchronous. Do not mark an order as paid only because the initial API request returned successfullyโuse the resulting payment status and verified webhook events.
Payment Methods
| Method | Type | Use Case |
|---|---|---|
card |
Credit/Debit | Standard payments |
bank_transfer |
ACH, SEPA | Low-fee transfers |
digital_wallet |
Apple Pay, Google Pay | Mobile checkout |
buy_now_pay_later |
Klarna, Afterpay | Installment payments |
Tokenize Card Details
Do not send raw card details to your server. Tokenize payment details in the browser or mobile app, then send only the resulting token ID to your backend.
const tokenizeCard = async (cardData) => {
// NEVER send raw card data to your server.
// Use client-side tokenization instead.
const response = await fetch(`${IPAY_BASE_URL}/tokens`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${CLIENT_PUBLISHABLE_KEY}`
},
body: JSON.stringify({
card: {
number: cardData.number,
exp_month: cardData.expMonth,
exp_year: cardData.expYear,
cvc: cardData.cvc
}
})
});
const token = await response.json();
return token; // Send token.id to your server
};
On the server, exchange the token for a payment method:
const createPaymentMethod = async (tokenId, customerId) => {
return ipayRequest('/payment_methods', {
method: 'POST',
body: JSON.stringify({
type: 'card',
token: tokenId,
customer: customerId
})
});
};
Handle 3D Secure Authentication
For Strong Customer Authentication (SCA), your server may need to return a client secret and let the client complete the challenge.
const createPaymentWith3DS = async (paymentData) => {
const payment = await createPayment({
...paymentData,
confirmation_token: true // Return client secret for 3DS
});
if (payment.status === 'requires_action') {
return {
requiresAction: true,
clientSecret: payment.client_secret,
nextAction: payment.next_action
};
}
return { success: true, payment };
};
On the client, use iPay.js or the mobile SDK to present the authentication challenge when requiresAction is true.
Refund Management
Process a Full Refund
Use the original payment ID when creating a refund.
const refundPayment = async (paymentId, reason = null) => {
const refund = {
payment: paymentId,
reason: reason || 'requested_by_customer'
};
return ipayRequest('/refunds', {
method: 'POST',
body: JSON.stringify(refund),
idempotencyKey: `refund_${paymentId}_${Date.now()}`
});
};
// Usage
const refund = await refundPayment('pay_12345', 'duplicate');
console.log(`Refund status: ${refund.status}`);
console.log(`Refund ID: ${refund.id}`);
Process a Partial Refund
Include an amount when refunding only part of a payment.
const partialRefund = async (paymentId, amount, reason = null) => {
const refund = {
payment: paymentId,
amount, // Smallest currency unit
reason: reason || 'requested_by_customer'
};
return ipayRequest('/refunds', {
method: 'POST',
body: JSON.stringify(refund),
idempotencyKey: `refund_${paymentId}_${amount}_${Date.now()}`
});
};
// Usage โ refund $15.00 of a $29.99 payment
const refund = await partialRefund('pay_12345', 1500, 'partial_ship');
console.log(`Refunded: $${refund.amount / 100}`);
Refund Reasons
| Reason Code | Description |
|---|---|
duplicate |
Duplicate charge |
fraudulent |
Fraudulent transaction |
requested_by_customer |
Customer request |
order_canceled |
Order cancellation |
product_not_received |
Item not delivered |
product_not_as_described |
Item differs from description |
Customer Management
Create a Customer
Store customer records so you can support recurring payments and saved payment methods.
const createCustomer = async (customerData) => {
const customer = {
email: customerData.email,
name: customerData.name,
phone: customerData.phone,
metadata: {
internalId: customerData.internalId,
tier: customerData.tier
}
};
return ipayRequest('/customers', {
method: 'POST',
body: JSON.stringify(customer)
});
};
// Usage
const customer = await createCustomer({
email: 'customer@example.com',
name: 'John Doe',
phone: '+1-555-0123',
internalId: 'USR-12345',
tier: 'premium'
});
console.log(`Customer created: ${customer.id}`);
Attach a Payment Method
const attachPaymentMethod = async (paymentMethodId, customerId) => {
return ipayRequest(`/payment_methods/${paymentMethodId}/attach`, {
method: 'POST',
body: JSON.stringify({
customer: customerId
})
});
};
// Usage
await attachPaymentMethod('pm_67890', 'cus_12345');
List Saved Payment Methods
const getCustomerPaymentMethods = async (customerId) => {
return ipayRequest(`/customers/${customerId}/payment_methods`);
};
// Usage
const methods = await getCustomerPaymentMethods('cus_12345');
methods.data.forEach((method) => {
console.log(`${method.card.brand} ending in ${method.card.last4}`);
console.log(`Expires: ${method.card.exp_month}/${method.card.exp_year}`);
});
Webhooks
Configure Webhooks
In the iPay Dashboard:
- Go to Developers > Webhooks.
- Click Add Endpoint.
- Enter your HTTPS endpoint URL.
- Select the events your integration needs.
- Store the webhook signing secret in your environment configuration.
Webhook Events
| Event | Trigger |
|---|---|
payment.succeeded |
Payment completed |
payment.failed |
Payment declined |
payment.refunded |
Refund processed |
payment.disputed |
Chargeback filed |
customer.created |
New customer |
customer.subscription.updated |
Subscription changed |
Verify and Handle Webhooks
Use the raw request body for signature verification. Parsing JSON before verification can change the payload and invalidate the signature.
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post(
'/webhooks/ipay',
express.raw({ type: 'application/json' }),
async (req, res) => {
const signature = req.headers['ipay-signature'];
const payload = req.body;
const isValid = verifyWebhookSignature(
payload,
signature,
process.env.IPAY_WEBHOOK_SECRET
);
if (!isValid) {
console.error('Invalid webhook signature');
return res.status(401).send('Unauthorized');
}
const event = JSON.parse(payload.toString());
switch (event.type) {
case 'payment.succeeded':
await handlePaymentSucceeded(event.data);
break;
case 'payment.failed':
await handlePaymentFailed(event.data);
break;
case 'payment.refunded':
await handlePaymentRefunded(event.data);
break;
case 'payment.disputed':
await handlePaymentDisputed(event.data);
break;
default:
console.log('Unhandled event type:', event.type);
}
return res.status(200).send('OK');
}
);
function verifyWebhookSignature(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSignature, 'hex')
);
}
Update your internal order state from webhook events:
async function handlePaymentSucceeded(data) {
console.log(`Payment succeeded: ${data.id}`);
await db.orders.update(data.metadata.orderId, {
status: 'paid',
paymentId: data.id,
paidAt: new Date()
});
await sendOrderConfirmation(data.metadata.orderId);
}
async function handlePaymentFailed(data) {
console.log(`Payment failed: ${data.id} - ${data.failure_code}`);
await sendPaymentFailedEmail(data.customer, data.failure_message);
await db.orders.update(data.metadata.orderId, {
status: 'payment_failed',
failureReason: data.failure_message
});
}
Make webhook handlers idempotent as well. Payment providers can retry an event when your endpoint times out or returns a non-success response.
Security and Compliance
PCI DSS Requirements
| Requirement | Implementation |
|---|---|
| Secure Network | Use HTTPS, firewalls, and secure configurations |
| Cardholder Data Protection | Never store CVV; encrypt PAN |
| Vulnerability Management | Apply regular security updates and anti-virus |
| Access Control | Use least privilege, MFA, and unique IDs |
| Monitoring | Enable logging and intrusion detection |
| Security Policy | Maintain documented policies and regular training |
Security Practices to Implement
// 1. Use tokenization โ NEVER handle raw card data
const token = await tokenizeCard(cardData); // Client-side
// 2. Add idempotency to every payment operation
const idempotencyKey = `pay_${orderId}_${Date.now()}`;
// 3. Validate amounts on the server
if (req.body.amount !== calculatedAmount) {
throw new Error('Amount mismatch - possible tampering');
}
// 4. Log payment operations without sensitive data
logger.info('Payment attempted', {
orderId,
amount,
currency,
customerId,
timestamp: new Date().toISOString()
// NEVER log card numbers, CVV, or full payment method details
});
// 5. Load secrets from environment variables
const apiKey = process.env.IPAY_API_KEY;
// 6. Rate-limit payment endpoints
const paymentLimiter = rateLimit({
windowMs: 60000,
max: 10 // 10 payment attempts per minute
});
Production Deployment Checklist
Before processing live payments:
- [ ] Complete the PCI DSS Self-Assessment Questionnaire.
- [ ] Use HTTPS for all endpoints.
- [ ] Store API keys in secure secret management.
- [ ] Implement webhook signature verification.
- [ ] Add idempotency for all payment operations.
- [ ] Set up comprehensive logging without sensitive data.
- [ ] Configure fraud detection rules.
- [ ] Test refund and dispute flows.
- [ ] Create a runbook for payment failures.
- [ ] Set up monitoring and alerting.
- [ ] Implement a backup payment processor.
Real-World Use Cases
E-commerce Checkout
An online retailer integrates payments:
- Challenge: Manual payment processing and high abandonment.
- Solution: One-page checkout with tokenized cards.
- Result: 35% conversion increase and instant payments.
SaaS Subscription Billing
A software company automates billing:
- Challenge: Manual invoice generation and collection.
- Solution: Recurring payments with automatic retry.
- Result: 95% on-time payment and 80% admin time savings.
Marketplace Escrow
A platform handles multi-party payments:
- Challenge: Complex split payments between vendors.
- Solution: Payment intents with transfer scheduling.
- Result: Automated vendor payouts and reduced fraud.
Conclusion
Payment API integration requires careful attention to security, compliance, and error handling. The implementation priorities are:
- Never handle raw card dataโuse tokenization.
- Add idempotency to every payment operation.
- Verify webhook signatures before processing events.
- Comply with PCI DSS requirements.
- Test payment, refund, dispute, and failure paths in sandbox before production.
- Use Apidog to streamline API testing and team collaboration.
FAQ Section
How do I authenticate with iPay API?
Use Basic authentication with an API key and secret, or OAuth 2.0 for multi-tenant applications.
Can I store customer card details?
Yes, but you must be PCI DSS compliant. Use tokenization to store cards securely in iPayโs vault.
How do I handle failed payments?
Implement retry logic with exponential backoff, notify customers, and provide alternative payment methods.
What is idempotency and why is it important?
Idempotency ensures duplicate requests with the same key produce the same result, preventing duplicate charges.
How do I test payments without charging cards?
Use sandbox mode with test card numbers provided in iPay documentation.
What are webhook signatures?
They are cryptographic signatures that verify webhooks came from iPay rather than a malicious actor.
Top comments (0)