Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

PayIn Flow Diagram

This guide illustrates the complete PayIn flow from initialization to completion, including all API calls, user interactions, and webhook events.


Complete Integration Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│ PAYIN INTEGRATION FLOW │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐
│ Your │ │ Cashela │ │ Payment │ │ Your Server │
│ Client │ │ API │ │ Provider │ │ (Webhooks) │
└────┬────┘ └──────┬──────┘ └──────┬──────┘ └────────┬────────┘
│ │ │ │
│ 1. Get Countries │ │
│─────────────────► │ │
│ ◄─────────────── [MEX, BRA, COL] │ │
│ │ │ │
│ 2. Get Payment Methods │ │
│─────────────────► │ │
│ ◄─────────────── [Card, Bank, Cash]│ │
│ │ │ │
│ 3. Get Exchange Rates │ │
│─────────────────► │ │
│ ◄─────────────── FX Rate + Fees │ │
│ │ │ │
│ 4. Create Deposit │ │
│─────────────────► │ │
│ ◄─────────────── Deposit Created │ │
│ (redirect_url) │ │
│ │ │ │
│ 5. Redirect to Payment │ │
│───────────────────────────────────► │ │
│ │ │ │
│ 6. Customer Completes Payment │ │
│ ◄─────────────────────────────────│ │
│ │ │ │
│ │ 7. Payment Result│ │
│ │◄──────────────────│ │
│ │ │ │
│ │ 8. Webhook Notification │
│ │───────────────────────────────────────►│
│ │ │ │
│ │ 9. Acknowledge (200 OK) │
│ │◄───────────────────────────────────────│
│ │ │ │
│ 10. Get Transaction Status │ │
│─────────────────► │ │
│ ◄─────────────── COMPLETED │ │
│ │ │ │

Step-by-Step Process

Step 1: Get Available Countries

Retrieve the list of supported countries to display to your users.

GET /api/v1/pay-in/deposit-creation/countries

Purpose: Determine where payments can be collected from.


Step 2: Get Available Payment Methods

For the selected country and amount, fetch available payment methods with fees.

POST /api/v1/pay-in/deposit-creation/available-payment-methods

Purpose: Show the customer their payment options with accurate pricing.


Step 3: Get Exchange Rates (Optional)

If you need to display converted amounts before creating the deposit.

POST /api/v1/pay-in/deposit-creation/exchange-rate

Purpose: Show the customer the exact amount they’ll pay in their local currency.


Step 4: Create Deposit

Submit the deposit request with customer and payment details.

POST /api/v1/pay-in/deposit-creation

Purpose: Initialize the payment and receive the redirect URL or payment instructions.


Step 5: Customer Payment

Redirect the customer to complete payment or display payment instructions.

Payment TypeUser Experience
CardRedirect to hosted checkout page
Bank TransferDisplay bank details or redirect to bank site
Cash/VoucherDisplay barcode or payment reference number
Digital WalletRedirect to wallet app or show QR code

Step 6-9: Payment Processing & Webhooks

The payment is processed asynchronously. Your server receives webhook notifications for status changes.


Step 10: Verify Transaction Status

Optionally query the transaction status for confirmation.


State Machine

┌─────────────┐
│ CREATED │
└──────┬──────┘
┌──────▼──────┐
│ PENDING │
└──────┬──────┘
┌─────────────────┼─────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ COMPLETED │ │ FAILED │ │ EXPIRED │
└─────────────┘ └─────────────┘ └─────────────┘
┌──────▼──────┐
│ REFUNDED │
└─────────────┘
StatusDescriptionTerminal
CREATEDDeposit initiated, awaiting paymentNo
PENDINGPayment in progressNo
COMPLETEDPayment received successfullyYes
FAILEDPayment failed or declinedYes
EXPIREDPayment window expiredYes
REFUNDEDPayment was refundedYes

Integration Patterns

Pattern 1: Server-Side Redirect

Best for: Web applications with server-side rendering

// Server-side
app.post('/checkout', async (req, res) => {
// 1. Create deposit
const deposit = await cashelaApi.createDeposit({
amount: req.body.amount,
country: req.body.country,
payment_method: req.body.paymentMethod,
callback_url: `${process.env.BASE_URL}/webhooks/payin`,
success_url: `${process.env.BASE_URL}/payment/success`,
cancel_url: `${process.env.BASE_URL}/payment/cancel`
});
// 2. Redirect to payment
res.redirect(deposit.redirect_url);
});
// Webhook handler
app.post('/webhooks/payin', (req, res) => {
// Verify signature first
if (!verifySignature(req)) {
return res.status(401).send();
}
// Process event
const event = req.body;
handlePaymentEvent(event);
res.status(200).send();
});

Pattern 2: Client-Side Modal

Best for: Single-page applications (SPAs)

// Client-side
async function initiatePayment(amount, country) {
// 1. Request deposit from your backend
const response = await fetch('/api/create-deposit', {
method: 'POST',
body: JSON.stringify({ amount, country })
});
const deposit = await response.json();
// 2. Open payment in modal or popup
const paymentWindow = window.open(
deposit.redirect_url,
'cashela_payment',
'width=500,height=700'
);
// 3. Listen for completion
window.addEventListener('message', (event) => {
if (event.data.type === 'payment_complete') {
paymentWindow.close();
handlePaymentComplete(event.data);
}
});
}

Pattern 3: Mobile App Integration

Best for: Native mobile applications

// iOS Swift
func createPayment(amount: Double, country: String) {
// 1. Create deposit via your backend
API.createDeposit(amount: amount, country: country) { result in
switch result {
case .success(let deposit):
// 2. Open payment URL in SFSafariViewController
let safari = SFSafariViewController(url: deposit.redirectUrl)
safari.delegate = self
present(safari, animated: true)
case .failure(let error):
showError(error)
}
}
}
// Handle callback URL
func application(_ app: UIApplication, open url: URL) -> Bool {
if url.scheme == "myapp" && url.host == "payment-callback" {
handlePaymentCallback(url)
return true
}
return false
}

Error Handling Flow

┌─────────────────────────────────────────────────────────────────┐
│ ERROR HANDLING FLOW │
└─────────────────────────────────────────────────────────────────┘
┌──────────────────────┐
│ Make API Request │
└──────────┬───────────┘
┌──────▼──────┐
│ Check Status │
└──────┬──────┘
┌──────┴──────────────────┬──────────────────────┐
│ │ │
┌───▼───┐ ┌─────▼─────┐ ┌──────▼──────┐
│ 2xx │ │ 4xx │ │ 5xx │
│Success│ │Client Err │ │ Server Err │
└───┬───┘ └─────┬─────┘ └──────┬──────┘
│ │ │
│ ┌─────▼─────┐ ┌──────▼──────┐
│ │ Fix Error │ │ Retry │
│ │ & Retry │ │ w/ Backoff │
│ └───────────┘ └─────────────┘
┌───▼───────────┐
│Process Result │
└───────────────┘

Best Practices Checklist

  • Cache country and payment method lists – Refresh every 24 hours
  • Validate amounts client-side – Check min/max before API call
  • Use idempotency keys – Prevent duplicate deposits
  • Implement webhook handlers – Never rely solely on redirects
  • Handle all terminal states – COMPLETED, FAILED, EXPIRED
  • Log all API interactions – Include request_id for support
  • Test in sandbox first – Verify all flows before production