Skip to Content
Embedded Checkout

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

  1. Your backend creates the group payment via the REST API (secret key) and mints a group-scoped session token.
  2. The embedded component uses that token to read the group and take the payment.
  3. 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:

ProviderIn-browser experience
StripeStripe Elements + 3-D Secure (confirmCardPayment)
RedeEvervault <Card> encrypts the PAN client-side (PCI SAQ-A)
RedsysSigned 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 tokenThe browser (group-scoped, short-lived)
Card dataEncrypted client-side (Stripe/Evervault) or at the bank (Redsys)
The moneyThe merchant’s connected PSP account
Last updated on