Vezmo App

Accept payments

Hosted Checkout

A VezmoPay-hosted payment page, and the simplest way to take a payment: you create a payment session on your server, redirect the customer to a VezmoPay-hosted page, they pay, and we redirect them back. Nothing is embedded on your site, you write no checkout UI, and card data never touches your servers — so it's the lowest-effort, lowest-compliance option (PCI SAQ‑A).

It uses the same session you create for the embed and Elements — you simply use the returned url instead of mounting anything. Compare the options:

  • Hosted Checkout (this page) — redirect to a VezmoPay page. Zero front-end code.
  • Embed / Checkout JS — drop our payment form into your own page via vezmo.js.
  • Elements — build your own UI with composable fields.

How it works

  1. Your server creates a session with your API key and gets back a url.
  2. You redirect the customer to that url.
  3. The customer pays on the VezmoPay-hosted page; we redirect them to your successUrl (or cancelUrl), and a webhook confirms the payment server-side.

1. Create a session — POST /merchant/secure-payments

Authenticate first (exchange your key + secret for an access token via POST /merchant/api-auth/login — see Authentication), then create the session. The amount is fixed here, server-side. Pass your customer's name and email in client, and the successUrl / cancelUrl you want them returned to. You may also pass phone and an optional address (line1, line2, city, state, postalCode, country) in client — it's kept on the payment record.

Request
curl -X POST https://api.vezmo.com/api/v1/merchant/secure-payments \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Order #1234",
    "amount": 49.99,
    "currency": "USD",
    "client": {
      "name": "Ada Lovelace",
      "email": "ada@example.com",
      "country": "US",
      "postalCode": "94103"
    },
    "successUrl": "https://your-store.com/order/success",
    "cancelUrl":  "https://your-store.com/order/cancelled",
    "theme": "light"
  }'

Customer fields. Send the customer in a client object. When you do, name, email, country (ISO code, e.g. US) and postalCode are required; a request missing one is rejected with 400. line1, city, state and phone are optional, but a complete address improves fraud screening.

For a card payment we forward only the customer's name and address to the card network for verification (AVS and fraud checks), never their email or phone. Email is forwarded only for bank (ACH), saved-card and wallet payments; bank payments need it for the debit mandate. Every field you send is kept on your payment record.

The response carries the hosted url:

201 Created
{
  "success": true,
  "data": {
    "securePayment": {
      "clientToken": "eyJ...",
      "url": "https://api.vezmo.com/api/v1/secure-payments/eyJ...",
      "expiresAt": "2026-06-30T14:30:00.000Z"
    }
  }
}

2. Redirect the customer to the URL

Send the customer to data.securePayment.url. It is a public, single-session link that 302-redirects to the white-label VezmoPay checkout page — no API key, no token handling on your side. The link is short-lived (default 30 min, max 24 h; set ttlMinutes to adjust).

// e.g. in your route handler after creating the session:
res.redirect(session.url);

// or client-side:
window.location = session.url;

3. Handle the return

After the payment resolves server-side, VezmoPay redirects the customer to:

  • successUrl?paymentId=<id>&status=success — on a confirmed payment;
  • cancelUrl?status=failed — on a terminal failure or cancellation.
  • app.returnUrl — for a checkout opened from your mobile app: the buyer goes back to your app whatever the outcome, with paymentId and status. It must be registered under Developers → Mobile apps. See Checkout for apps.

Both URLs must use https; anything else is refused with 400. They don't need to be in your Trusted origins (those are only for the embed). If you omit them, nothing redirects — the page just shows the result and you reconcile by webhook.

Fulfil on the webhook, not the redirect. The success redirect is a convenience; treat the payment.success webhook as the source of truth before shipping goods or granting access. Reconcile by the paymentId.

What the customer sees

A fully white-label VezmoPay page — your business name, your brand color and logo, the amount, and the available payment methods: card and wallets (Apple Pay, Google Pay) and, when you turn them on and the payment qualifies, bank transfer (ACH), Instant ACH, Cash App Pay, Klarna, Affirm, Afterpay, Amazon Pay, UPI for a payer paying in Indian rupees and Pix for one paying in Brazilian reais. No processor branding beyond the unavoidable bank-connect step. 3‑D Secure is handled automatically. Footer reads “Secured by VezmoPay”.

With Klarna, Affirm, Afterpay or Amazon Pay the customer finishes on the method's own page and comes straight back to the checkout, which then sends them to your successUrl like any other payment (details).

Theming

Set theme on the session (light / dark / auto; auto follows the customer's device). Your company logo and brand color are applied automatically from your VezmoPay branding settings.

Test cards

  • 4242 4242 4242 4242 — success
  • 4000 0000 0000 3220 — 3‑D Secure required
  • 4000 0000 0000 0002 — declined

Going live

  • Make sure your successUrl / cancelUrl use https.
  • Your account must be approved to collect payments.
  • Use your live API key; the hosted page renders in live mode automatically.
  • Subscribe a webhook endpoint to payment.success and fulfil from it.

Webhooks

Hosted-checkout payments settle through the same pipeline as every other VezmoPay charge and emit the same events — payment.success, payment.failed, payment.refunded, and the dispute.* events. See Webhooks. For the underlying endpoints (when you want raw control), see the endpoint reference.