Hosted invoice page
A VINR-hosted page where customers pay invoices.
Every finalized invoice gets a secure, VINR-hosted page where your customer can review line items, pay with any supported method, download a PDF receipt, and update their default payment method. You don't build or host anything — VINR renders it, handles SCA, and emits events as the customer acts.
What the page doesAsk
The hosted invoice page is the customer-facing surface of an invoice. It is the default collection experience for both one-off invoices you send and the recurring invoices a subscription generates.
| Capability | Detail |
|---|---|
| Pay now | Charges the amount due using a card or stored method; handles SCA / 3DS inline. |
| Download PDF | A finalized, branded invoice document for the customer's records. |
| Update payment method | Saves a new default method on the customer, reused for future cycles. |
| Status awareness | Shows paid, past_due, or void and disables payment when no longer collectible. |
The page is branded with the logo, colors, and support details from your branding settings, so it looks like your product, not ours.
When the URL existsAsk
A page URL is only present once the invoice is finalized — drafts have no payable surface. The link lives on the invoice as hosted_invoice_url and the PDF as invoice_pdf.
For subscription invoices, VINR finalizes automatically about an hour after the draft is created (or immediately on the first cycle). For invoices you create by hand, call vinr.invoices.finalize(...) to lock the invoice and mint the URL.
Retrieve the hosted page URLAsk
Finalize an invoice and read its hosted URL, then deliver that link however you like — VINR's own email, your transactional mail, or an in-app banner.
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
// Draft -> finalized; only finalized invoices have a hosted page.
const invoice = await vinr.invoices.finalize('inv_4Qp1Z8kR2');
console.log(invoice.hosted_invoice_url);
// https://pay.vinr.com/i/inv_4Qp1Z8kR2/9f3c...
console.log(invoice.invoice_pdf);
// https://pay.vinr.com/i/inv_4Qp1Z8kR2/9f3c.../pdfIf you'd rather have VINR email the page for you, set collection_method: 'send_invoice' when creating the invoice and call vinr.invoices.send(invoice.id) — VINR sends a branded email containing the same link.
curl https://api.vinr.com/v1/invoices/inv_4Qp1Z8kR2/send \
-H "X-Api-Key: $VINR_SECRET_KEY" \
-X POSTWhat the customer sees and doesAsk
Open the link
The customer lands on the hosted page over HTTPS. The URL embeds a signed token, so no login is required — but the token is scoped to that single invoice and expires once the invoice is paid or voided.
Review and pay
They see line items, tax, discounts, and the amount due, then pay with a card or a previously stored method. VINR runs any required SCA challenge in-page.
Land on confirmation
On success the page shows a receipt and a PDF download. VINR marks the invoice paid and the underlying payment completed.
Resulting eventsAsk
Listen for these on your webhook endpoint (verify with vinr.webhooks.verify(payload, signature)). Fulfil access on invoice.paid, never on a client-side redirect.
| Event | Fires when |
|---|---|
invoice.finalized | The page URL becomes available. |
payment.completed | The customer's payment succeeds on the page. |
invoice.paid | The invoice is fully settled — your fulfilment trigger. |
invoice.payment_failed | A payment attempt is declined; feeds dunning. |
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);
if (event.type === 'invoice.paid') {
const invoice = event.data; // amount_paid in minor units, e.g. 2000 = €20.00
await grantAccess(invoice.customer);
}
return new Response('ok', { status: 200 });
}Edge casesAsk
Next stepsAsk
Invoices
The invoice lifecycle from draft to paid.
Dunning & recovery
What happens when a hosted payment fails.
Strong customer authentication
How SCA is handled inline on the page.
Last updated on