Integration models
Compare VINR's three integration surfaces — Checkout, Elements, and API-only — and choose the right one for your use case.
VINR offers three integration surfaces: Hosted Checkout, Elements, and API-only. Choosing the right one determines how much you build versus how much control you have over the payment experience. Most merchants start with Checkout and never need more.
The three modelsAsk
| Model | What VINR hosts | PCI scope | Time to first payment | Best for |
|---|---|---|---|---|
| Checkout | Complete payment page (UI, 3DS, error handling) | SAQ-A | Under an hour | Standard commerce, quick time-to-market |
| Elements | Sensitive form fields only (card number, expiry, CVC) | SAQ-A EP | Half a day | Custom checkout UX on your own domain |
| API-only | Nothing — you build the full UI | SAQ-D | Days to weeks | Platforms, marketplaces, enterprise integrations |
CheckoutAsk
VINR hosts the entire payment form. You create a session from your backend, redirect the customer to checkout.vinr.com, and verify the result when they return. VINR handles card entry, Apple Pay, Google Pay, Click-to-Pay, 3DS challenges, and all error states.
Create a Checkout session
POST to /checkout/session with the order amount, currency, and redirect URLs. The response contains a checkoutUrl.
const { sessionId, checkoutUrl } = await fetch(
`${process.env.INTENT_API_URL}/checkout/session`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': process.env.VINR_API_KEY!,
},
body: JSON.stringify({
amount: 5000,
currency: 'EUR',
successUrl: 'https://yoursite.com/success',
cancelUrl: 'https://yoursite.com/cancel',
}),
}
).then(r => r.json());Redirect the customer
window.location.href = checkoutUrl;VINR renders the payment form on a VINR-owned domain. Your servers never see raw card data.
Verify on return
When the customer lands on successUrl?sessionId=..., fetch the session result before fulfilling the order.
const result = await fetch(
`${process.env.INTENT_API_URL}/checkout/session/${sessionId}/result`,
{ headers: { 'X-Api-Key': process.env.VINR_API_KEY! } }
).then(r => r.json());
if (result.status === 'completed') {
await fulfillOrder(result);
}Read the full Checkout integration guide.
ElementsAsk
VINR UI components are embedded directly in your page. You own the page layout, step flow, and branding — VINR owns the sensitive fields (card number, expiry, CVC). Card data is entered in VINR-hosted iframes, encrypted in the browser, and returned as a token your backend can charge. Because raw card data never touches your JavaScript or servers, SAQ-A EP (rather than full SAQ-D) applies.
The example below shows the minimum code to mount a card element inside a React component:
import { useRef } from 'react';
import { useAsparyxSDK, useAsparyxElement, useTokenReceived } from '@vinr/elements';
export default function CardForm({ intent }: { intent: Intent }) {
const containerRef = useRef<HTMLDivElement>(null);
const { sdk, status } = useAsparyxSDK({
merchantId: intent.accountId,
publicKey: intent.publicKey,
secureFormsUrl: 'https://elements.vinr.com',
enabled: !!intent,
});
useAsparyxElement(sdk, 'full-payment', {
container: containerRef,
amount: intent.amount,
currency: intent.currency,
});
useTokenReceived(sdk, async (data) => {
await fetch('/api/process-payment', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
intentId: intent.id,
paymentMethod: { card: { payload: data.payload.card.payload } },
billingDetails: data.payload.billingDetails,
}),
});
});
return (
<>
<div ref={containerRef} style={{ minHeight: 550 }} />
<button
disabled={status !== 'ready'}
onClick={() => sdk?.submit(intent.amount, intent.currency)}
>
Pay
</button>
</>
);
}Read the full Elements integration guide.
API-only (Advanced flow)Ask
You build the entire UI, collect card data, and tokenize it yourself before passing the payload to VINR. This gives you the highest degree of control over every pixel and interaction, but it also gives you the highest PCI scope: SAQ-D, which requires a full annual assessment and quarterly network scans. Most merchants should exhaust Checkout and Elements before reaching for this model.
API-only is the right choice when:
- You are a payment platform or marketplace that needs to route funds across multiple sub-merchants.
- You have an existing card-vault or tokenization system you want to connect to VINR.
- Your enterprise compliance team mandates end-to-end control over all payment data flows.
Read the full API-only integration guide.
Decision matrixAsk
Prop
Type
| Checkout | Elements | API-only | |
|---|---|---|---|
| PCI scope | SAQ-A | SAQ-A EP | SAQ-D |
| 3DS handling | Automatic | Automatic (via SDK) | Your responsibility |
| Custom UI | No | Full layout control | Unlimited |
| Mobile support | Browser redirect | React Native SDK available | You build it |
| Typical time to integrate | < 1 hour | Half a day | Days to weeks |
Changing models laterAsk
You can migrate from Checkout to Elements, or from Elements to API-only, without changing your backend payment logic. The pay_... payment IDs, webhook event names, and result status values are identical across all three models. The only thing that changes is the frontend integration code and your PCI scope obligations.
Changing integration model changes your PCI scope. Moving from Checkout (SAQ-A) to Elements (SAQ-A EP) or API-only (SAQ-D) requires re-assessing your compliance posture. Talk to your compliance team before migrating in production.
Next stepsAsk
Checkout
Redirect to a VINR-hosted payment page — no frontend code required, SAQ-A scope.
Elements
Embed card fields in your React app while VINR handles all sensitive data, SAQ-A EP scope.
API-only
Build a fully custom payment UI for platforms and enterprise integrations.
Last updated on