Choose your integration
Pick one of four integration patterns based on how much code you want to write.
There are four ways to take a payment with XPay. All four use the same underlying Checkout Session, so the API call your server makes and the webhook your server receives are identical. What changes is how much frontend code you write, and where the customer fills in their card.
If you're not sure which to pick, start with Payment Links. You can move to a richer integration later without rewriting your backend.
Side by side
| Pattern | Code you write | Customer experience | Pick this if |
|---|---|---|---|
| Payment Links | None | A hosted XPay page reached through your link | You want zero code, or you sell over invoices, social, or chat |
| Hosted Checkout | Server only | A hosted XPay page reached through a redirect | You want zero frontend complexity and the redirect is fine |
| Drop-in | Server + ~10 lines of frontend | A modal on your site, or an inline iframe | You want the customer to stay on your domain with the form still hosted by XPay |
| Elements | Server + custom frontend | A form you build yourself, on your site | You want full control over the checkout UI |
The four patterns
Payment Links
Create a Payment Link in the dashboard or via the API and share the URL. We host the checkout, your customer pays, your server gets the checkout.session.completed webhook. No frontend code at all.
Hosted Checkout
Your server calls POST /checkout/sessions and redirects the customer to the url returned in the response. After payment the customer lands back on the URL you configured in afterCompletion. The simplest path that involves any code.
Drop-in
Your server creates a Checkout Session and your frontend opens it with xpay.checkout({ clientSecret, mode: "modal" }) or embeds it inline with mode: "inline". The customer never leaves your domain.
Elements
Your server creates a Checkout Session and your frontend builds a custom checkout UI around XPay's <PaymentElement />. The most code, the most control.
What's the same across all four
- One API call. Every pattern (except a no-code Payment Link, which still wraps a session under the hood) starts with
POST /checkout/sessions. - One webhook. Every successful payment fires
checkout.session.completedcarrying the same Checkout Session you'd get from the API. - One customer flow. Cards, 3D Secure, and local methods like Valu and Fawry all work identically.
You aren't locking yourself into a pattern when you start. The Checkout Session is the spine; the integration patterns are just different ways of opening it.