Embedded Checkout (white-label)
Embed Payylo’s group-payment flow directly in your own checkout — your brand, your domain. Your secret API key stays on your backend; the browser only ever holds a short-lived, group-scoped token.
There are two API-only ways to take a group payment without writing a card form:
- Hosted checkout — create the group payment, redirect the payer to the
returned
checkout_url. Zero front-end work. - Embedded widget — mount the slot picker + card form inside your own page
with the vanilla
<script>loader (js.payylo.com/v1.js).
Both render the card form (Stripe Elements, Rede via Evervault, or Redsys hosted 3-D Secure) depending on the merchant’s connected provider.
Hosted checkout (simplest)
Create the group payment server-side and redirect the payer to checkout_url:
curl https://api.payylo.com/v1/group-payments \
-H "Authorization: Bearer $PAYYLO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"group_name": "Flight SkyHop 123",
"total_amount": 240.00,
"currency": "EUR",
"expires_at": "2026-06-22T18:00:00Z",
"distribution": { "type": "equally", "number_of_slots": 3 }
}'
# → { "group_payment": { "id": "…" }, "checkout_url": "https://checkout.payylo.com/g/…" }Redirect the customer to checkout_url. You’re notified of completion via
webhooks (group_payment.paid, etc.).
How the embedded widget works
- Your backend creates the group payment via the REST API (secret key) and mints a group-scoped session token.
- The embedded component uses that token to read the group and take the payment.
- Capture and state transitions are driven server-side; you receive
webhooks (
group_payment.paid, etc.).
The secret key never reaches the browser. The session token can only read/pay its own group — never refund, never another group.
Backend session endpoint
Expose an endpoint on your server that (1) creates the group payment and (2) mints a session token, then returns the token to the browser. Both calls use your secret key:
# 1. Create the group payment (secret key, server-side)
curl https://api.payylo.com/v1/group-payments \
-H "Authorization: Bearer $PAYYLO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"group_name": "Flight SkyHop 123",
"total_amount": 240.00,
"currency": "EUR",
"expires_at": "2026-06-22T18:00:00Z",
"distribution": { "type": "equally", "number_of_slots": 3 }
}'
# → { "group_payment": { "id": "<group_payment_id>", … }, … }
# 2. Mint a browser-safe, group-scoped session token for that group
curl -X POST \
https://api.payylo.com/v1/group-payments/<group_payment_id>/session \
-H "Authorization: Bearer $PAYYLO_SECRET_KEY"
# → { "token": "…", "group_payment_id": "…", "expires_in": 3600 }Your endpoint (e.g. POST /api/payylo/session) should return
{ token, groupPaymentId } to the browser — that’s all the widget needs.
Exact request/response shapes for these and every other endpoint are in the interactive API Reference .
Vanilla JS (any site, no framework)
Load the script, then create and mount the widget programmatically. This is the recommended approach — same shape as Stripe/Adyen/PayPal: a factory with callbacks, and you control where/when it mounts.
<div id="payylo"></div>
<script type="module" src="https://js.payylo.com/v1.js"></script>
<script>
const widget = Payylo.create({
createSession: () =>
fetch('/api/payylo/session', { method: 'POST' }).then(r => r.json()),
payerEmail: 'user@example.com',
theme: { accentColor: '#0ea5e9' },
onComplete: group => location.assign(`/booking/${group.id}/confirmed`),
onError: err => console.error(err),
});
const handle = widget.mount('#payylo'); // selector or HTMLElement
// handle.unmount(); ← e.g. when closing a modal / leaving the page (SPAs)
</script>No-code shortcut (data attributes)
For landing pages or no-code setups, add data-payylo-group-pay to a container
and it auto-mounts on load (only data-session-url is required):
<div
data-payylo-group-pay
data-session-url="/api/payylo/session"
data-redirect-url="/booking/{id}/confirmed"
></div>
<script type="module" src="https://js.payylo.com/v1.js"></script>Completion and errors are emitted as DOM events on the container:
const el = document.querySelector('[data-payylo-group-pay]');
el.addEventListener('payylo:complete', e => console.log('paid', e.detail));
el.addEventListener('payylo:error', e => console.error(e.detail.message));Payment methods
The card form rendered depends on the merchant’s active gateway:
| Provider | In-browser experience |
|---|---|
| Stripe | Stripe Elements + 3-D Secure (confirmCardPayment) |
| Rede | Evervault <Card> encrypts the PAN client-side (PCI SAQ-A) |
| Redsys | Signed redirect to the bank’s hosted 3-D Secure page |
Use the sandbox test cards to try each one.
Need another provider? Payylo’s gateway layer is built on a PSP-adapter pattern, so new providers can be onboarded on demand. If you need a specific gateway, contact us and we’ll confirm timelines.
Security model recap
| Where it lives | |
|---|---|
Secret API key (sk_…) | Your backend only |
| Session token | The browser (group-scoped, short-lived) |
| Card data | Encrypted client-side (Stripe/Evervault) or at the bank (Redsys) |
| The money | The merchant’s connected PSP account |