Documentation Index Fetch the complete documentation index at: https://docs.caibo.digital/llms.txt
Use this file to discover all available pages before exploring further.
H2H Response Structure
Host-to-Host API responses provide essential information for tracking and completing payment processes. This guide covers response formats, status handling, and implementation patterns.
Response Overview
The API returns a payment response containing essential information for tracking and completing the payment process.
Response Structure
The payment response includes:
Payment Request Identifier : A unique identifier for the created payment request that can be used to pull payment request status
Redirect URL : A URL to complete the payment if necessary (for payment methods requiring customer interaction)
Response Fields
Field Description Type paymentRequestIdCreated payment request identifier string/integer redirectUrlURL to complete payment (if required) string statusInitial payment status string
Response Usage
1. Status Tracking
Use the payment request identifier to check payment status via status endpoints:
// Track payment status
async function checkPaymentStatus ( paymentRequestId ) {
const response = await fetch ( `/api/payment-status/ ${ paymentRequestId } ` , {
headers: {
'X-API-Key' : apiKey
}
});
const status = await response . json ();
return status ;
}
2. Payment Completion
Redirect customers to the provided URL for payment methods requiring user interaction:
// Handle redirect if required
if ( paymentResponse . redirectUrl ) {
// Redirect customer to complete payment
window . location . href = paymentResponse . redirectUrl ;
} else {
// Payment completed directly
handlePaymentComplete ( paymentResponse );
}
3. Transaction Management
Store the identifier for future reference and reconciliation:
// Store payment reference
const paymentRecord = {
paymentRequestId: paymentResponse . paymentRequestId ,
merchantReference: orderData . referenceId ,
amount: orderData . amount ,
currency: orderData . unit ,
status: paymentResponse . status ,
createdAt: new Date (). toISOString ()
};
await savePaymentRecord ( paymentRecord );
Implementation Examples
Basic H2H Payment Processing
// H2H Payment Processing
async function processH2HPayment ( paymentData ) {
const apiEndpoint = "https://api.caibo.com/h2h/payments" ; // From dashboard
const apiKey = "your-api-key-from-dashboard" ;
try {
const response = await fetch ( apiEndpoint , {
method: 'POST' ,
headers: {
'Content-Type' : 'application/json' ,
'X-API-Key' : apiKey
},
body: JSON . stringify ({
amount: paymentData . amount ,
currency: paymentData . currency ,
paymentMethod: {
type: "credit_card" ,
cardNumber: paymentData . cardNumber ,
expiryMonth: paymentData . expiryMonth ,
expiryYear: paymentData . expiryYear ,
cvv: paymentData . cvv ,
cardholderName: paymentData . cardholderName
},
customer: {
email: paymentData . customerEmail ,
phone: paymentData . customerPhone
},
billingAddress: paymentData . billingAddress ,
merchantReference: paymentData . orderId ,
notificationUrl: "https://yoursite.com/webhooks/payment-notification"
})
});
const result = await response . json ();
if ( response . ok ) {
console . log ( 'Payment processed successfully:' , result );
return {
success: true ,
transactionId: result . transactionId ,
status: result . status ,
data: result
};
} else {
console . error ( 'Payment failed:' , result );
return {
success: false ,
error: result . error ,
message: result . message
};
}
} catch ( error ) {
console . error ( 'Network error:' , error );
return {
success: false ,
error: 'NETWORK_ERROR' ,
message: error . message
};
}
}
Multiple Provider Handling
// Handle multiple API endpoints for different providers
const providerEndpoints = {
'provider1' : 'https://api1.caibo.com/h2h/payments' ,
'provider2' : 'https://api2.caibo.com/h2h/payments' ,
'provider3' : 'https://api3.caibo.com/h2h/payments'
};
async function processPaymentWithFailover ( paymentData , preferredProvider = 'provider1' ) {
const providers = [ preferredProvider , ... Object . keys ( providerEndpoints ). filter ( p => p !== preferredProvider )];
for ( const provider of providers ) {
try {
const endpoint = providerEndpoints [ provider ];
const result = await processH2HPayment ({
... paymentData ,
endpoint: endpoint
});
if ( result . success ) {
console . log ( `Payment successful with ${ provider } ` );
return result ;
}
} catch ( error ) {
console . warn ( `Provider ${ provider } failed, trying next...` );
continue ;
}
}
throw new Error ( 'All payment providers failed' );
}
Error Handling
Common Error Codes
INVALID_API_KEY : API key is missing or invalid
INSUFFICIENT_FUNDS : Customer’s account has insufficient funds
CARD_DECLINED : Payment method was declined by issuer
INVALID_CARD : Card number or details are invalid
EXPIRED_CARD : Payment method has expired
NETWORK_ERROR : Communication error with payment provider
Retry Logic
async function processPaymentWithRetry ( paymentData , maxRetries = 3 ) {
let attempt = 0 ;
let lastError ;
while ( attempt < maxRetries ) {
try {
const result = await processH2HPayment ( paymentData );
if ( result . success ) {
return result ;
}
// Check if error is retryable
if ( isRetryableError ( result . error )) {
attempt ++ ;
await delay ( Math . pow ( 2 , attempt ) * 1000 ); // Exponential backoff
continue ;
} else {
// Non-retryable error, fail immediately
return result ;
}
} catch ( error ) {
lastError = error ;
attempt ++ ;
if ( attempt < maxRetries ) {
await delay ( Math . pow ( 2 , attempt ) * 1000 );
}
}
}
throw new Error ( `Payment failed after ${ maxRetries } attempts: ${ lastError . message } ` );
}
function isRetryableError ( errorCode ) {
const retryableErrors = [
'NETWORK_ERROR' ,
'TIMEOUT' ,
'TEMPORARY_UNAVAILABLE' ,
'RATE_LIMITED'
];
return retryableErrors . includes ( errorCode );
}
function delay ( ms ) {
return new Promise ( resolve => setTimeout ( resolve , ms ));
}
Status Management
Payment Status Types
pending : Payment is being processed
completed : Payment was successful
failed : Payment failed
cancelled : Payment was cancelled
expired : Payment request expired
Status Polling
async function pollPaymentStatus ( paymentRequestId , maxAttempts = 30 , interval = 2000 ) {
let attempts = 0 ;
while ( attempts < maxAttempts ) {
try {
const status = await checkPaymentStatus ( paymentRequestId );
// Terminal states
if ([ 'completed' , 'failed' , 'cancelled' , 'expired' ]. includes ( status . status )) {
return status ;
}
// Continue polling for pending status
await delay ( interval );
attempts ++ ;
} catch ( error ) {
console . error ( 'Status check failed:' , error );
attempts ++ ;
await delay ( interval );
}
}
throw new Error ( 'Payment status polling timeout' );
}
Response Validation
Validate Response Structure
function validatePaymentResponse ( response ) {
const requiredFields = [ 'paymentRequestId' , 'status' ];
for ( const field of requiredFields ) {
if ( ! response [ field ]) {
throw new Error ( `Missing required field: ${ field } ` );
}
}
// Validate status values
const validStatuses = [ 'pending' , 'completed' , 'failed' , 'cancelled' , 'expired' ];
if ( ! validStatuses . includes ( response . status )) {
throw new Error ( `Invalid status: ${ response . status } ` );
}
return true ;
}
Response Processing
async function handlePaymentResponse ( response ) {
try {
// Validate response structure
validatePaymentResponse ( response );
// Store payment record
await savePaymentRecord ({
paymentRequestId: response . paymentRequestId ,
status: response . status ,
redirectUrl: response . redirectUrl ,
timestamp: new Date (). toISOString ()
});
// Handle based on status
switch ( response . status ) {
case 'completed' :
await handleSuccessfulPayment ( response );
break ;
case 'pending' :
await handlePendingPayment ( response );
break ;
case 'failed' :
await handleFailedPayment ( response );
break ;
default :
console . warn ( 'Unexpected payment status:' , response . status );
}
return response ;
} catch ( error ) {
console . error ( 'Response handling error:' , error );
throw error ;
}
}
Best Practices
Response Handling
Immediate Validation : Validate response structure immediately
Status Tracking : Always track payment status changes
Error Logging : Log all errors for debugging and monitoring
Timeout Handling : Implement appropriate timeout values
Connection Pooling : Use HTTP connection pooling for better performance
Async Processing : Handle responses asynchronously when possible
Caching : Cache non-sensitive response data appropriately
Monitoring : Monitor response times and success rates
Security
Response Validation : Always validate response data
Sensitive Data : Never log sensitive payment information
Error Messages : Sanitize error messages before displaying to users
Audit Trail : Maintain audit trail of all payment responses
Next Steps
Request Structure Learn about H2H API request format and parameters
Notifications Set up webhook notifications for real-time status updates
Payment Methods Explore available payment methods and implementations