All amounts are in minor units (centavos, cents). For example, to charge 1,000.00 ARS, pass amount: 100000. Passing 1000 would create a payment for only 10.00 ARS.
PayID uses Australia’s New Payments Platform (NPP) for near-instant settlement. The customer sends funds to the provided PayID identifier (email, phone, or ABN) through their banking app. PayID deposits typically settle within minutes.
Pass ipay.payment_method to restrict the checkout to a single scheme. If omitted, all available schemes are shown to the customer.
iPay deposits use a redirect or form-based flow. After creating the payment, submit a form to ipay_checkout.form_action with ipay_checkout.checkout_params, or redirect the customer to ipay_checkout.checkout_url. The customer completes payment on the hosted checkout page, and status updates are delivered via webhooks.
Create a payment via POST /payments with method: "ipay" and currency: "LKR"
The response includes an ipay_checkout object — submit a form to ipay_checkout.form_action with ipay_checkout.checkout_params, or redirect to ipay_checkout.checkout_url
The customer completes payment on the iPay hosted checkout page (Visa, Mastercard, LankaQR, or iPay App)
iPay sends a server-to-server callback to confirm payment status
You receive a webhook (payment.completed or payment.failed) with the final status
iPay reports three transaction statuses via server-to-server callback:
iPay Status
Code
LuxCore Status
Description
Accepted
A
completed
Payment successful, funds transferred
Pending
P
processing
Funds deducted, transfer pending (end-of-day settlement)
Declined
D
failed
Payment declined by iPay or card issuer
Pending (P) status: In rare cases, iPay may report a “Pending” status, meaning the customer’s funds have been deducted but the transfer to the merchant is scheduled for end-of-day batch settlement. The system monitors these payments and auto-cancels them if unresolved after 24 hours.
For MXN/SPEI withdrawals, the response returns clabe instead of bank_account in the payout object. This matches the Mexican banking convention where the 18-digit account identifier is called CLABE.
HTTPS URL to receive webhook events for this payment (max 2048 characters)
webhook_events
string[]
No
Events to subscribe to. Defaults to ["payment.created", "payment.completed", "payment.failed", "payment.refunded"]
In-request webhooks are signed using your merchant’s default webhook secret. See the Webhooks Guide for details on signature verification and secret management.
The payment page URL is dynamically generated and may vary based on the selected currency, payment method, and region. Always use the exact URL returned in the API response.
Redirect your customer to this URL to complete the payment.
Payment is being processed, awaiting customer action
❌
-
completed
Payment was successful, funds transferred
✅
payment.completed
failed
Payment failed due to error or rejection
✅
payment.failed
cancelled
Payment was cancelled by merchant or system
✅
payment.cancelled
expired
Payment expired before completion
✅
payment.failed
refunded
Payment was fully refunded
✅
payment.refunded
partial_refund
Payment was partially refunded
✅
payment.refunded
Terminal statuses (completed, failed, cancelled, expired, refunded, partial_refund) are final states - the payment cannot transition to non-terminal status.
The payment has been created in the system but has not yet been assigned to a payment provider or requisite. This is a transient status that typically transitions quickly to pending or processing.Next possible statuses:pending, processing, failed
pending_approval
The payment requires manual approval before it can be processed. This may apply to high-value transactions or flagged payments that need review.Next possible statuses:processing, cancelled
pending
The payment has been created and is waiting to be processed. For withdrawals, this means the payout is queued and awaiting approval or processing by the payment provider.Next possible statuses:processing, cancelled, expired
processing
The payment is actively being processed. For deposits, this means the customer has been given payment instructions (bank details, payment page URL) and we are waiting for them to complete the transfer.Next possible statuses:completed, failed, cancelled, expired
completed
The payment was successful. For deposits, the funds have been received and credited to your merchant balance. For withdrawals, the funds have been sent to the beneficiary.This is a terminal status. You will receive a payment.completed webhook.
failed
The payment could not be completed. This can happen due to various reasons: bank rejection, invalid account details, insufficient funds (for withdrawals), or technical issues.This is a terminal status. You will receive a payment.failed webhook with an error_code and error_message.
cancelled
The payment was cancelled before completion. This can be initiated by the merchant via API, by an admin, or automatically by the system.This is a terminal status. You will receive a payment.cancelled webhook.
expired
The payment was not completed within the allowed time window. Deposits typically expire after 1-60 minutes (configurable per merchant).This is a terminal status. You will receive a payment.failed webhook with error_code: TTL_EXPIRED.
refunded
The payment was fully refunded after completion. The refunded amount has been deducted from your merchant balance.This is a terminal status. You will receive a payment.refunded webhook.
partial_refund
The payment was partially refunded. Part of the original amount has been returned to the customer.This is a terminal status. You will receive a payment.refunded webhook with the refunded amount.
Always use webhooks to track payment status changes. Polling the API is not recommended as it adds latency and may hit rate limits.
// Example: Handling status in your webhook handlerswitch (payment.status) { case 'completed': // Update order to paid, deliver goods/services await markOrderAsPaid(payment.merchant_reference); break; case 'failed': case 'expired': // Notify customer, allow retry await notifyPaymentFailed(payment.merchant_reference, payment.error_message); break; case 'cancelled': // Clean up pending order await cancelOrder(payment.merchant_reference); break; case 'refunded': case 'partial_refund': // Process refund in your system await processRefund(payment.merchant_reference, payment.refunded_amount); break;}
Payments are automatically linked to customers in your account. You can optionally pass an existing customer ID to link a payment to a specific customer.
Your unique customer identifier from your system. Used to link payments to your internal customer records
All customer fields are optional. However, providing at least email or phone is recommended for automatic customer matching and communication.
external_id is your own customer reference (e.g., user ID from your database). It is stored on the customer record and is unique per merchant. Use it for reconciliation and analytics without relying on LuxCore internal IDs.
external_id must be unique per merchant. If you attempt to create a new customer with an external_id that is already assigned to another customer within the same merchant account, the request will fail.
When customer_id is provided, the system validates that the customer exists and belongs to your merchant account. The customer object fields (name, email, phone, external_id) are not updated in this case — only the link to the existing customer is used.
Use unique merchant_reference values for idempotency. If you submit a payment with a reference that was already used, the API will return the existing payment instead of creating a duplicate.