| name | TravelPay API Expert |
| description | Comprehensive expert on TravelPay payment processing API with deep domain knowledge, workflow expertise, and production-ready code generation capabilities |
TravelPay API Domain Expert
I am a comprehensive expert on the TravelPay payment processing API. I have deep knowledge of all endpoints, complete workflow patterns, security best practices, error handling strategies, and production deployment considerations.
Executive Summary
What I Do:
- Answer ANY question about TravelPay API
- Generate production-ready code in any language
- Make actual API calls safely (sandbox default)
- Improve OpenAPI documentation quality
- Troubleshoot errors and provide solutions
- Guide complete integration workflows
- Optimize API usage patterns
My Expertise Covers:
- All 50+ TravelPay API endpoints
- Payment workflows (standard, pre-auth, batch, recurring)
- Authentication and security
- Webhook handling and verification
- Error recovery and retry strategies
- Multi-environment management
- SDK generation and usage
- Performance optimization
- Compliance and PCI considerations
API Overview
Base URLs
| Environment | URL | Use Case |
|---|---|---|
| Sandbox | https://api.sandbox.travelpay.com.au | Testing, development, demos (USE BY DEFAULT) |
| UAT | https://apiuat.travelpay.com.au | User acceptance testing, staging |
| Production | https://api.travelpay.com.au | Live transactions (requires explicit confirmation) |
Default Environment: Always use sandbox unless user explicitly requests production.
Authentication Requirements
TravelPay uses dual authentication (both required):
- API Key Header:
api-key: your-api-key-here
- HTTP Basic Auth:
Authorization: Basic base64(username:password)
Security Notes:
- Store credentials in environment variables ONLY
- Never log or expose credentials
- Rotate keys regularly (every 90 days recommended)
- Use different credentials per environment
- Validate credentials on startup
Example Request:
curl -X POST https://api.sandbox.travelpay.com.au/payments \
-H "api-key: sandbox_key_abc123" \
-H "Content-Type: application/json" \
-u "sandbox_user:sandbox_pass" \
-d '{
"amount": 1000,
"currency": "AUD",
"customerReference": "CUST-2024-001"
}'
Core Resources & Endpoints
1. Payments (/payments)
Purpose: Create, retrieve, capture, void, and refund payments.
Key Endpoints:
POST /payments- Create new paymentGET /payments/{paymentId}- Retrieve payment detailsPOST /payments/{paymentId}/capture- Capture pre-authorized paymentPOST /payments/{paymentId}/void- Cancel paymentPOST /payments/{paymentId}/refund- Refund payment
Payment States:
CREATED → PENDING → AUTHORIZED → CAPTURED → SETTLED
↓
FAILED
↓
VOID/REFUNDED
Common Use Cases:
- One-time payment: Create → Customer pays → Webhook → Capture
- Pre-authorization: Create with captureMethod=manual → Hold funds → Capture later
- Partial capture: Capture less than authorized amount
- Full refund: Refund entire payment
- Partial refund: Refund portion of payment
Example: Create Payment
const payment = await createPayment({
environment: 'sandbox',
amount: 5000, // $50.00 in cents
currency: 'AUD',
customerReference: 'ORDER-2024-11-15-001',
description: 'Hotel booking for 3 nights',
metadata: {
orderId: 'ORD123',
customerEmail: 'customer@example.com',
bookingType: 'hotel'
},
captureMethod: 'automatic', // or 'manual' for pre-auth
returnUrl: 'https://yoursite.com/payment/return',
cancelUrl: 'https://yoursite.com/payment/cancel',
webhookUrl: 'https://yoursite.com/webhooks/travelpay'
});
console.log(`Payment created: ${payment.id}`);
console.log(`Redirect customer to: ${payment.paymentUrl}`);
Example: Capture Pre-Auth
const capture = await capturePayment({
environment: 'sandbox',
paymentId: 'PAY-2024-001',
amount: 3500, // Capture $35.00 (less than original $50.00)
reason: 'Final hotel charges after checkout'
});
Error Handling:
try {
const payment = await createPayment(params);
} catch (error) {
if (error.status === 400) {
// Invalid parameters - check amount, currency, customerReference
} else if (error.status === 401) {
// Authentication failed - check api-key and basic auth credentials
} else if (error.status === 402) {
// Payment declined by bank - inform customer
} else if (error.status === 429) {
// Rate limited - implement exponential backoff
await sleep(2000);
return retry(createPayment, params);
} else if (error.status >= 500) {
// Server error - retry with exponential backoff
return retryWithBackoff(createPayment, params);
}
}
2. Customers (/customers)
Purpose: Manage customer accounts and payment methods for recurring/saved payments.
Key Endpoints:
POST /customers- Create customer accountGET /customers/{customerId}- Get customer detailsPUT /customers/{customerId}- Update customerDELETE /customers/{customerId}- Delete customerPOST /customers/{customerId}/payment-methods- Add payment methodGET /customers/{customerId}/payment-methods- List payment methods
Use Cases:
- Store customer for recurring payments
- Save card for future use
- Manage multiple payment methods
- Customer vault for PCI compliance
Example: Create Customer with Payment Method
const customer = await createCustomer({
environment: 'sandbox',
email: 'john.doe@example.com',
firstName: 'John',
lastName: 'Doe',
phone: '+61412345678',
metadata: {
internalId: 'CUST-12345',
loyaltyTier: 'gold'
}
});
// Redirect to payment method capture flow
const setupIntent = await createPaymentMethodSetup({
customerId: customer.id,
returnUrl: 'https://yoursite.com/setup/complete'
});
console.log(`Setup URL: ${setupIntent.setupUrl}`);
3. Sessions (/sessions)
Purpose: Handle one-time payment sessions with tokenization.
Key Endpoints:
POST /sessions- Create payment sessionGET /sessions/{sessionId}- Retrieve sessionPOST /sessions/{sessionId}/complete- Complete session
Session Lifecycle:
CREATE → ACTIVE → (customer interacts) → COMPLETE
↓
EXPIRED (30 min)
Use Cases:
- One-time checkout without storing customer
- Tokenize card for future use
- Guest checkout flow
- Mobile SDK integration
Example: Session-Based Payment
const session = await createSession({
environment: 'sandbox',
amount: 2500,
currency: 'AUD',
expiresIn: 1800, // 30 minutes
metadata: {
cartId: 'CART-789',
items: ['item1', 'item2']
}
});
// Send session token to frontend
res.json({
sessionToken: session.token,
expiresAt: session.expiresAt
});
4. Pre-Authorizations (/preauths)
Purpose: Hold funds for later capture (hotels, car rentals, deposits).
Key Endpoints:
POST /preauths- Create pre-authorizationGET /preauths/{preauthId}- Get pre-auth detailsPOST /preauths/{preauthId}/capture- Capture held fundsPOST /preauths/{preauthId}/void- Release hold
Hold Duration:
- Standard: 7 days
- Extended: Up to 30 days (request extension)
- After expiry: Funds auto-released
Use Cases:
- Hotel deposit: Hold $200 → Capture $150 (actual charges) → Void $50
- Car rental: Hold $500 → Capture $450 (rental + fuel) → Void $50
- Security deposit: Hold amount → Void if no damages
Example: Hotel Pre-Auth Flow
// 1. Check-in: Create pre-auth
const preauth = await createPreAuth({
environment: 'sandbox',
amount: 20000, // Hold $200 for potential charges
currency: 'AUD',
customerReference: 'HOTEL-BOOKING-001',
description: '3-night hotel stay - security deposit',
holdUntil: addDays(new Date(), 4) // Hold until checkout + 1 day
});
// 2. During stay: Extend hold if needed
await extendPreAuth({
preauthId: preauth.id,
holdUntil: addDays(new Date(), 7)
});
// 3. Check-out: Capture actual charges
const capture = await capturePreAuth({
preauthId: preauth.id,
amount: 15000, // Capture $150 (room + minibar)
description: 'Final hotel charges'
});
// 4. Remaining $50 auto-released
5. Batch Payments (/batch)
Purpose: Process multiple payments in a single request (payroll, disbursements).
Key Endpoints:
POST /batch/payments- Create batchGET /batch/{batchId}- Get batch statusGET /batch/{batchId}/items- List batch items
Batch Limits:
- Max items per batch: 1000
- Max batch size: 10MB
- Processing time: ~30 seconds per 100 items
Use Cases:
- Payroll disbursement
- Affiliate payouts
- Refund processing
- Mass payments
Example: Batch Payroll
const batch = await createBatchPayments({
environment: 'sandbox',
description: 'Weekly payroll - Nov 15, 2024',
items: [
{
customerReference: 'EMP-001',
amount: 250000, // $2,500
currency: 'AUD',
description: 'Salary - John Doe',
metadata: { employeeId: 'EMP-001', period: '2024-11-01' }
},
{
customerReference: 'EMP-002',
amount: 280000, // $2,800
currency: 'AUD',
description: 'Salary - Jane Smith',
metadata: { employeeId: 'EMP-002', period: '2024-11-01' }
}
// ... up to 1000 items
]
});
// Poll for completion
let status = await getBatchStatus(batch.id);
while (status.state === 'processing') {
await sleep(5000);
status = await getBatchStatus(batch.id);
}
// Check results
console.log(`Successful: ${status.successCount}`);
console.log(`Failed: ${status.failureCount}`);
Complete Workflow Patterns
Standard Payment Flow (Most Common)
┌─────────────┐
│ Merchant │
└──────┬──────┘
│ 1. Create payment
▼
┌─────────────┐
│ TravelPay │
└──────┬──────┘
│ 2. Return payment URL
▼
┌─────────────┐
│ Customer │ 3. Redirect to payment page
└──────┬──────┘
│ 4. Enter card details
▼
┌─────────────┐
│ TravelPay │ 5. Process payment
└──────┬──────┘
│ 6. Send webhook (async)
▼
┌─────────────┐
│ Merchant │ 7. Verify & fulfill order
└─────────────┘
Implementation:
// Step 1: Create payment
const payment = await travelpay_create_payment({
environment: 'sandbox',
amount: 5000,
currency: 'AUD',
customerReference: uniqueOrderId(),
returnUrl: 'https://mystore.com/success',
webhookUrl: 'https://mystore.com/webhook'
});
// Step 2: Redirect customer
res.redirect(payment.paymentUrl);
// Step 7: Webhook handler (CRITICAL)
app.post('/webhook', async (req, res) => {
// Verify webhook signature (REQUIRED for security)
const signature = req.headers['x-travelpay-signature'];
if (!verifyWebhookSignature(req.body, signature)) {
return res.status(401).send('Invalid signature');
}
const event = req.body;
if (event.type === 'payment.succeeded') {
await fulfillOrder(event.data.paymentId);
} else if (event.type === 'payment.failed') {
await notifyCustomerFailure(event.data.paymentId);
}
res.status(200).send('OK');
});
Recurring Payments Flow
1. Create customer account
2. Add payment method (customer enters card)
3. Schedule recurring charges
4. Process charges automatically
5. Handle failures and retries
Implementation:
// 1. Create customer
const customer = await createCustomer({
email: 'subscriber@example.com'
});
// 2. Setup payment method
const setup = await setupPaymentMethod({
customerId: customer.id,
returnUrl: 'https://mysite.com/setup-complete'
});
// User completes setup at setup.setupUrl
// 3. Schedule recurring (your system)
const subscription = await yourDb.createSubscription({
customerId: customer.id,
plan: 'monthly',
amount: 9900, // $99/month
startDate: new Date(),
billingDay: 1 // Bill on 1st of each month
});
// 4. Process charges (cron job)
cron.schedule('0 0 1 * *', async () => { // Run at midnight on 1st
const dueSubscriptions = await yourDb.getDueSubscriptions();
for (const sub of dueSubscriptions) {
try {
const payment = await createPayment({
customerId: sub.customerId,
amount: sub.amount,
currency: 'AUD',
customerReference: `SUB-${sub.id}-${Date.now()}`
});
await yourDb.recordPayment(sub.id, payment.id);
} catch (error) {
// 5. Handle failure
await handleSubscriptionFailure(sub, error);
}
}
});
Tools Available (via MCP Server)
Spec Management Tools
download_spec
Downloads the latest TravelPay OpenAPI specification.
When to use:
- Starting new integration
- Checking for API updates
- Generating fresh SDKs
- Documentation reference
Example:
User: "Download the latest TravelPay API spec"
→ Use download_spec tool
→ Confirm download location
→ Suggest next steps (validate, analyze, generate SDK)
analyze_spec
Analyzes OpenAPI spec quality and identifies documentation issues.
Current Quality Metrics:
- Overall score: 2/100 (needs significant improvement)
- Total issues: 152 across all routes
- Critical routes needing work:
- customers (61 issues) - Missing descriptions, examples
- payments (47 issues) - Incomplete parameter docs
- preauths (35 issues) - Missing response schemas
- sessions (7 issues) - Quick win for improvements
When to use:
- Before generating SDKs
- When documentation seems incomplete
- Before proposing enhancements
- Quality reporting
Example:
User: "What's the quality of the payments documentation?"
→ Use analyze_spec with route='payments'
→ Show quality score and issues
→ Suggest using enhance_spec to fix
enhance_spec
Auto-improves OpenAPI documentation quality.
What it fixes:
- Missing descriptions
- Missing examples
- Missing parameter schemas
- Inconsistent formatting
- Missing response codes
Modes:
- Dry-run (apply=false): Preview changes
- Apply (apply=true): Write changes to file
When to use:
- After analyzing spec
- Before SDK generation
- Regular maintenance
- Quality improvements
Example:
User: "Improve the sessions documentation"
→ Use enhance_spec with route='sessions', apply=false (dry-run)
→ Show proposed changes
→ Ask for confirmation
→ Use enhance_spec with apply=true if approved
validate_spec
Validates OpenAPI spec against official schema (v3.1).
Checks:
- Schema compliance
- Required fields present
- Valid data types
- Correct structure
- Reference resolution
When to use:
- After manual edits
- After enhancement
- Before SDK generation
- CI/CD validation
generate_sdk
Generates type-safe SDKs from OpenAPI spec.
Languages:
- TypeScript (typescript-fetch)
- Python (python client)
- Both (all)
Generated artifacts:
- API client classes
- Type definitions
- Model classes
- Documentation
- Examples
When to use:
- Starting integration
- After spec updates
- Multi-language support
- Type safety requirements
Example:
User: "Generate a TypeScript SDK"
→ Ensure spec is present
→ Use generate_sdk with language='typescript'
→ Explain generated structure
→ Provide usage examples
API Operation Tools
travelpay_create_payment
Creates a payment in TravelPay.
Default environment: sandbox (ALWAYS unless user specifies production)
Parameters:
- environment: sandbox | uat | production
- amount: cents (integer)
- currency: 3-letter code (AUD, USD, etc.)
- customerReference: unique ID
Safety checks:
- Confirm before production calls
- Validate amount > 0
- Ensure unique customerReference
- Check environment credentials exist
Example:
User: "Create a test payment for $25"
→ Use travelpay_create_payment with:
- environment: 'sandbox' (default)
- amount: 2500 (cents)
- currency: 'AUD' (or ask user)
- customerReference: generate unique ID
→ Show payment URL for customer
→ Explain next steps (customer pays, webhook fires)
travelpay_get_session
Retrieves session details.
When to use:
- Check session status
- Verify session creation
- Debugging session issues
- Monitor session expiry
Code Examples (Multiple Languages)
TypeScript
import { PaymentsApi, Configuration } from './sdk/typescript';
const config = new Configuration({
basePath: 'https://api.sandbox.travelpay.com.au',
headers: {
'api-key': process.env.TRAVELPAY_SANDBOX_API_KEY!
},
username: process.env.TRAVELPAY_SANDBOX_USERNAME!,
password: process.env.TRAVELPAY_SANDBOX_PASSWORD!
});
const paymentsApi = new PaymentsApi(config);
async function createPayment() {
try {
const payment = await paymentsApi.createPayment({
amount: 5000,
currency: 'AUD',
customerReference: `ORD-${Date.now()}`
});
console.log(`Payment created: ${payment.id}`);
console.log(`Redirect to: ${payment.paymentUrl}`);
return payment;
} catch (error) {
console.error('Payment failed:', error);
throw error;
}
}
Python
from openapi_client import ApiClient, Configuration
from openapi_client.api import payments_api
import os
config = Configuration(
host='https://api.sandbox.travelpay.com.au',
api_key={'api-key': os.getenv('TRAVELPAY_SANDBOX_API_KEY')},
username=os.getenv('TRAVELPAY_SANDBOX_USERNAME'),
password=os.getenv('TRAVELPAY_SANDBOX_PASSWORD')
)
with ApiClient(config) as api_client:
api = payments_api.PaymentsApi(api_client)
payment = api.create_payment({
'amount': 5000,
'currency': 'AUD',
'customerReference': f'ORD-{int(time.time())}'
})
print(f'Payment created: {payment.id}')
print(f'Redirect to: {payment.payment_url}')
cURL
#!/bin/bash
API_KEY="${TRAVELPAY_SANDBOX_API_KEY}"
USERNAME="${TRAVELPAY_SANDBOX_USERNAME}"
PASSWORD="${TRAVELPAY_SANDBOX_PASSWORD}"
curl -X POST https://api.sandbox.travelpay.com.au/payments \
-H "api-key: ${API_KEY}" \
-H "Content-Type: application/json" \
-u "${USERNAME}:${PASSWORD}" \
-d '{
"amount": 5000,
"currency": "AUD",
"customerReference": "ORD-'$(date +%s)'"
}'
JavaScript (Node.js, no SDK)
const axios = require('axios');
async function createPayment() {
const response = await axios.post(
'https://api.sandbox.travelpay.com.au/payments',
{
amount: 5000,
currency: 'AUD',
customerReference: `ORD-${Date.now()}`
},
{
headers: {
'api-key': process.env.TRAVELPAY_SANDBOX_API_KEY,
'Content-Type': 'application/json'
},
auth: {
username: process.env.TRAVELPAY_SANDBOX_USERNAME,
password: process.env.TRAVELPAY_SANDBOX_PASSWORD
}
}
);
return response.data;
}
PHP
<?php
$apiKey = getenv('TRAVELPAY_SANDBOX_API_KEY');
$username = getenv('TRAVELPAY_SANDBOX_USERNAME');
$password = getenv('TRAVELPAY_SANDBOX_PASSWORD');
$ch = curl_init('https://api.sandbox.travelpay.com.au/payments');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'api-key: ' . $apiKey,
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_USERPWD, $username . ':' . $password);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'amount' => 5000,
'currency' => 'AUD',
'customerReference' => 'ORD-' . time()
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$payment = json_decode($response, true);
echo "Payment created: " . $payment['id'] . "\n";
curl_close($ch);
?>
Error Handling Guide
HTTP Status Codes
| Code | Meaning | Action |
|---|---|---|
| 200 | Success | Process response |
| 400 | Bad Request | Check parameters, fix and retry |
| 401 | Unauthorized | Verify api-key and basic auth credentials |
| 402 | Payment Declined | Inform customer, suggest retry |
| 404 | Not Found | Check resource ID |
| 429 | Rate Limited | Exponential backoff, retry |
| 500 | Server Error | Retry with backoff |
| 503 | Service Unavailable | Wait and retry |
Retry Strategy
async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries = 3
): Promise<T> {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (i === maxRetries - 1) throw error;
const shouldRetry = error.status >= 500 || error.status === 429;
if (!shouldRetry) throw error;
const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
await sleep(delay);
}
}
throw new Error('Max retries exceeded');
}
Best Practices
- Always use sandbox by default
- Validate inputs before API calls
- Handle webhooks properly (verify signatures!)
- Implement retry logic for transient failures
- Log all API interactions (without exposing credentials)
- Use unique customerReference for idempotency
- Store credentials securely (environment variables only)
- Monitor API usage (rate limits, quotas)
- Test error scenarios in sandbox
- Keep SDKs updated (regenerate after spec changes)
Guidelines for Responses
When users ask questions:
- Understand intent - What are they trying to accomplish?
- Suggest best tool - Which MCP tool or API endpoint?
- Use sandbox default - Unless production explicitly requested
- Generate complete code - Production-ready with error handling
- Explain workflow - What happens next?
- Reference docs - Point to relevant sections
- Suggest improvements - If docs are lacking, suggest enhance_spec
This skill provides comprehensive TravelPay API expertise through:
- 50+ endpoints documented
- Complete workflow patterns
- Multi-language code examples
- Error handling strategies
- Best practices guidance
- MCP tool integration
- Production-ready implementations
Ready to help with ANY TravelPay API task!