Core concepts

The object model, event system, and three-product architecture behind every VINR integration.

View as MarkdownInstall skills

Every VINR integration — whether you're taking a one-off payment or running a subscription-plus-loyalty loop — is built on the same small set of ideas. This page explains them once so the rest of the documentation makes sense.

Three products, one platformAsk

VINR exposes three products through a single API and a single SDK. You can use any one of them independently, or combine all three.

The three products share one customer object. A cust_ you create for a first payment is the same record you attach a subscription and a loyalty account to — no duplicate data, no re-collecting card details, no second identity for the same person.

You do not need to use all three products. Many integrations start with Payments alone and add Billing or Engagement later. The cust_ object is backward-compatible — you can attach a subscription to a customer who has only ever made one-off payments.

Objects and IDsAsk

Every resource in VINR is an object with a typed, prefixed ID. The prefix tells you exactly what you're looking at — in logs, in dashboard URLs, and in webhook payloads.

PrefixObjectDescription
cust_CustomerA person or business. Shared across all three products.
pay_PaymentA single charge attempt. May require 3DS before confirming.
pm_Payment methodA saved card or bank account attached to a customer.
re_RefundA full or partial reversal of a pay_.
dp_DisputeA chargeback raised by the cardholder's bank.
po_PayoutFunds settled to your bank account.
prod_ProductA thing you sell. Has one or more price_ objects.
price_PriceAn amount, currency, and billing interval.
sub_SubscriptionA customer subscribed to a price. Drives the invoice lifecycle.
inv_InvoiceA billing statement. Paid automatically or sent to the customer.
mbu_Metered billing usageA usage record for consumption-based pricing.
loy_Loyalty accountA points balance attached to a cust_.
ptx_Points transactionAn earn or burn event against a loyalty account.
rwd_RewardA redeemable item in a loyalty catalog.
rdm_RedemptionA customer exchanging points for a reward.
evt_EventA webhook event delivered to your endpoint.
we_Webhook endpointA registered URL that receives evt_ objects.

Object IDs are not portable across environments. A cust_ created in sandbox does not exist in live. Re-create reference data when you move to production.

The event modelAsk

VINR is event-driven. Every meaningful state change — a payment completing, an invoice generating, a customer earning points — emits an evt_ object delivered to your registered webhook endpoint. Do not poll the API for state changes; react to events instead.

A webhook payload always has the same shape:

{
  id: "evt_01j2k...",
  type: "payment.completed",
  created: 1717200000,
  data: { /* the full object that changed */ }
}

Your endpoint must verify the x-vinr-signature header before trusting the payload, then return 2xx within 30 seconds. VINR retries unacknowledged deliveries with exponential backoff for up to 72 hours.

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

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

export async function POST(req: Request) {
  const payload = await req.text();
  const signature = req.headers.get('x-vinr-signature');

  const event = vinr.webhooks.verify(payload, signature);

  switch (event.type) {
    case 'payment.completed':
      await fulfillOrder(event.data.metadata.orderId);
      break;
    case 'invoice.paid':
      await grantAccess(event.data.customerId);
      break;
    case 'loyalty.points.earned':
      await notifyCustomer(event.data.customerId, event.data.amount);
      break;
  }

  return new Response('OK', { status: 200 });
}

Make every handler idempotent: store the processed evt_ id and short-circuit duplicates. VINR may redeliver the same event on retry.

Key events by product

EventWhen it fires
payment.completedA charge was successfully captured
payment.failedA charge attempt was declined or errored
payment.refundedA re_ was applied to a pay_
invoice.createdA billing cycle generated a new invoice
invoice.paidAn invoice was collected successfully
invoice.payment_failedAn invoice charge attempt failed (triggers dunning)
subscription.deletedA subscription was cancelled or expired
loyalty.points.earnedA ptx_ earn was recorded
loyalty.points.redeemedA customer redeemed points for a reward
payout.paidFunds were settled to your bank account
dispute.createdA chargeback was opened against a pay_

EnvironmentsAsk

Every VINR account has two isolated environments. They share nothing — not keys, not objects, not money.

SandboxLive
API base URLhttps://sandbox.api.vinr.comhttps://api.vinr.com
Key prefixsk_test_… / pk_test_…sk_live_… / pk_live_…
MoneySimulated — no real fundsReal funds and payouts
Test cardsRequiredRejected
KYB requiredNoYes

The SDK switches base URL automatically based on which key you provide — a sk_test_… key can never touch the live API. If you call the REST API directly, keep the host and key in sync; a live key against the sandbox host returns 401.

Switch environments using the toggle in the top-left of the dashboard. Each environment has its own API keys, webhook endpoints, and webhook secrets.

AuthenticationAsk

VINR uses two API keys per environment:

  • Secret key (sk_test_… / sk_live_…) — server-side only. Used to create payments, read customer data, and verify webhooks. Never expose this in client-side code or commit it to version control.
  • Public key (pk_test_… / pk_live_…) — safe for browser use. Initializes the embedded Elements UI. It cannot make server-side API calls.

Pass the secret key via the X-Api-Key header (REST) or the SDK constructor. See Authentication for scoped keys, rotation, and key management best practices.

Next stepsAsk

Was this page helpful?
Edit on GitHub

Last updated on

On this page