Payments & Money APIs · Money & Payments Fundamentals
PSP Integration Models & PCI Scope
Hosted checkout, embedded fields or direct API — and what each does to compliance.
How card data reaches the PSP determines your PCI DSS scope — the biggest compliance driver. Hosted checkout/redirect (Stripe Checkout, Adyen Hosted Payment Pages) keeps card data entirely off your pages. Embedded fields (Stripe Elements, Adyen Drop-in, Braintree Hosted Fields) render PSP-hosted iframes inside your page — card data still never touches your servers, but your page scripts matter (PCI DSS v4.0 requirements on payment page scripts). Direct API (raw card numbers to your server) puts you in full scope. Most companies should choose hosted or embedded.
Integration models
| Criterion | Hosted checkout / redirect | Embedded fields (iframes) | Direct API (raw PAN) |
|---|---|---|---|
| Card data touches your servers | No | No | Yes |
| Typical PCI self-assessment | SAQ A | SAQ A (iframes) / A-EP (if your page affects payment form) | SAQ D / full assessment |
| UI control | Limited (branding) | High | Full |
| Payment methods & 3DS handled | By PSP | Mostly by PSP SDK | By you |
| Time to integrate | Fastest | Medium | Slowest |
| Best for | Most startups, simple checkouts | Custom checkout UX | Large processors, vaulting providers |
const session = await stripe.checkout.sessions.create(
{
mode: "payment",
line_items: [{ price_data: { currency: "usd", unit_amount: 4999, product_data: { name: "Pro plan (annual)" } }, quantity: 1 }],
success_url: "https://shop.example.com/orders/ord_123/thanks?session_id={CHECKOUT_SESSION_ID}",
cancel_url: "https://shop.example.com/cart",
client_reference_id: "ord_123",
metadata: { order_id: "ord_123" },
},
{ idempotencyKey: `checkout:ord_123:v1` },
);
res.redirect(303, session.url!);
session = stripe.checkout.Session.create(
mode="payment",
line_items=[{"price_data": {"currency": "usd", "unit_amount": 4999,
"product_data": {"name": "Pro plan (annual)"}}, "quantity": 1}],
success_url="https://shop.example.com/orders/ord_123/thanks?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://shop.example.com/cart",
client_reference_id="ord_123",
metadata={"order_id": "ord_123"},
idempotency_key="checkout:ord_123:v1",
)
Common pitfalls
- Collecting card numbers in your own form 'just for now'.
- Treating the success redirect as proof of payment (use webhooks).
- Unmanaged third-party scripts on payment pages.
Key points
- Keep card data off your servers
- Hosted or embedded for most teams
- Fulfil on webhooks, not redirects
Further reading: PCI SSC document library (PCI DSS v4.0.1, SAQs)
Practice questions
Why does the integration model matter so much for PCI compliance?
Answer
If raw card data passes through your systems you're in full PCI DSS scope (SAQ D); hosted/iframe integrations keep it off your servers and reduce scope to SAQ A.
Why shouldn't the checkout success redirect trigger fulfilment?
Answer
Users can close the browser before the redirect or forge the URL; the PSP's signed webhook (or an API re-fetch) is the reliable confirmation.
Open in the app to mark lessons complete, take notes and track your progress.