Integration overview

Choose the right integration path across Payments, Billing, and Engagement.

View as MarkdownInstall skills

VINR exposes one API and one SDK across three products — Payments, Billing, and Engagement — but each product offers several integration depths, from a hosted page you can wire up in an afternoon to a fully API-driven flow you control end to end. This page helps you pick the right entry point for your stack, your compliance posture, and how much of the UI you want to own.

Decision guideAsk

Start with two questions: how much UI do you want to build, and how much cardholder data do you want to touch. Touching raw card data raises your PCI DSS scope; hosted and embedded options keep that data on VINR's infrastructure.

PathYou buildPCI scopeBest when
HostedA redirect and a webhook handlerLowest (SAQ A)You want to ship fast or run server-side only
Embedded elementsYour own checkout page, VINR-hosted fieldsLow (SAQ A-EP)You want a branded checkout without handling card data
API-directFull client and server flowHighest (SAQ D)You need total control and are already PCI certified

When in doubt, start hosted. Every hosted integration can be migrated to embedded or API-direct later without changing your data model — the pay_, cust_, and sub_ objects are identical across paths.

Payments pathsAsk

All three payment paths produce the same payment object and emit the same payment.completed and payment.failed events, so your fulfillment logic is portable.

Create a payment server-side and redirect the customer to the returned checkoutUrl. VINR collects card details and handles 3DS.

import { Vinr } from '@vinr/sdk';

const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });

const payment = await vinr.payments.create({
  amount: 1000, // €10.00 in minor units
  currency: 'EUR',
  description: 'Order #1234',
  returnUrl: 'https://yoursite.com/checkout/return',
});

return Response.redirect(payment.checkoutUrl);

Mount VINR Elements in your own page. Card fields are served from VINR's domain inside an iframe, so the data never reaches your server.

const session = await vinr.payments.createSession({
  amount: 1000,
  currency: 'EUR',
});
// Pass session.clientSecret to the browser and mount Elements with it.

Submit a tokenized payment method to the API yourself. This requires a valid PCI SAQ D attestation on file.

const payment = await vinr.payments.create({
  amount: 1000,
  currency: 'EUR',
  paymentMethod: 'pm_tokenized_from_your_client',
  confirm: true,
});

See Payments for the full method matrix and capture options.

Billing pathsAsk

Billing is API-first: you model prod_, price_, and sub_ objects and let VINR drive the invoice lifecycle. There is no separate "hosted" tier, but you can delegate the entire payment-collection step to a hosted checkout.

Define a product and price

const price = await vinr.prices.create({
  productId: 'prod_starter',
  amount: 2900, // €29.00 per period
  currency: 'EUR',
  recurring: { interval: 'month' },
});

Subscribe a customer

const subscription = await vinr.subscriptions.create({
  customerId: 'cust_8fa2',
  priceId: price.id,
});

React to invoice events

VINR generates inv_ objects automatically and charges the customer's default payment method. Listen for invoice.paid and subscription.deleted rather than polling.

const event = vinr.webhooks.verify(payload, signature);
if (event.type === 'invoice.paid') {
  await grantAccess(event.data.customerId);
}

For metered plans, report usage with vinr.usage.record(...), which creates mbu_ records. See Billing.

Engagement pathsAsk

Engagement (loyalty) layers onto either standalone customers or your existing Payments/Billing data. You attach a loy_ account to a cust_ and award points either manually or by reacting to payment events.

// Earn points automatically when a payment completes
const event = vinr.webhooks.verify(payload, signature);
if (event.type === 'payment.completed') {
  await vinr.loyalty.points.earn({
    programId: 'prog_default',
    customerId: event.data.customerId,
    amount: Math.floor(event.data.amount / 100), // 1 point per euro
    sourcePaymentId: event.data.id,
  });
}

This produces a ptx_ transaction and emits loyalty.points.earned. Rewards (rwd_) and redemptions (rdm_) follow the same event-driven pattern. See Engagement.

Combining productsAsk

The biggest reason to standardize on VINR is that one cust_ object threads through all three products. A common end-to-end flow:

Collect the first payment

Use a hosted or embedded Payments flow to capture the customer and a reusable payment method.

Open a subscription

Reuse that cust_ to create a sub_ in Billing — no second card entry.

Reward retention

React to invoice.paid to award loyalty points, building an Engagement loop on top of recurring revenue.

Keep a single set of API keys per environment and one webhook endpoint per service. Routing all three products through one verified we_ endpoint keeps signature handling and replay protection consistent. See Webhooks.

Next stepsAsk

Was this page helpful?
Edit on GitHub

Last updated on

On this page