Integration models

Compare VINR's three integration surfaces — Checkout, Elements, and API-only — and choose the right one for your use case.

View as MarkdownInstall skills

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

ModelWhat VINR hostsPCI scopeTime to first paymentBest for
CheckoutComplete payment page (UI, 3DS, error handling)SAQ-AUnder an hourStandard commerce, quick time-to-market
ElementsSensitive form fields only (card number, expiry, CVC)SAQ-A EPHalf a dayCustom checkout UX on your own domain
API-onlyNothing — you build the full UISAQ-DDays to weeksPlatforms, 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

CheckoutElementsAPI-only
PCI scopeSAQ-ASAQ-A EPSAQ-D
3DS handlingAutomaticAutomatic (via SDK)Your responsibility
Custom UINoFull layout controlUnlimited
Mobile supportBrowser redirectReact Native SDK availableYou build it
Typical time to integrate< 1 hourHalf a dayDays 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

Was this page helpful?
Edit on GitHub

Last updated on

On this page