
travelpay-api-expert
by ianmenethil
SKILL.md
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!
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon