Skip to main content
Put a branded Pay with Platnova button on your website. When your customer clicks it, they go to Platnova’s hosted checkout at pay.platnova.com. The checkout shows every payment method that is live for the currency, and then sends them back to your site. The button never sees your API key. Your server creates the checkout with your key and passes only the checkout link to the browser.
Never put your API key in browser code, HTML, or a mobile app bundle. Anyone who loads your page could read it and use it. The button script refuses any option that looks like a key.

How it works

  1. Your server calls POST /v1/checkout with your API key.
  2. Your server gives the returned data.url to the browser.
  3. The button sends your customer to that link, and they pay on Platnova’s hosted checkout.
  4. After a successful payment, Platnova sends them to your success_url.
  5. Your server confirms the payment with a webhook or by retrieving the checkout. Don’t rely on the redirect alone.

1. Create the checkout on your server

Use your API key in the X-API-KEY header. Every payment method that is live for the currency is offered, and new methods reach your customers as we turn them on; payment_options is ignored.
The response contains the checkout id and the hosted checkout url:
See Initiating checkout for every request field and the payment methods offered.

Who pays the fee

fee_bearer is optional and decides who pays Platnova’s deposit fee:
  • "customer" (the default, used when you leave it out): the fee is added on top, so the customer pays amount plus the fee and you receive amount.
  • "merchant": the customer pays exactly amount, and you receive amount less the fee.
With "merchant", Nova Tag transfer isn’t offered: the payer’s app adds its own fee on top, so the merchant can’t bear it there. Every other live method still is.
Save data.id against your order. You’ll need it to confirm the payment. Put your own order id in success_url, because Platnova redirects to it exactly as you sent it, with nothing added.

2. Add the script to your page

Load the script once, on any page that shows the button:
It has no dependencies and makes no network requests of its own. v1 is a stable version: we fix bugs inside it but never change how it behaves. If your site sends a Content Security Policy, allow https://pay.platnova.com in script-src.

3. Show the button

Pick whichever fits how your page is built. Render the checkout url from step 1 into the page:
The script replaces the link with the branded button. If the script doesn’t load, the customer still has a working link. A checkout link stays valid for 7 days, so for pages that stay open longer, use option B. You can also use a container:

Option B: create the checkout when the customer clicks

This is best when the cart can change, or when you don’t want to create a checkout for every page view. Call PlatnovaPay.button with a createCheckout function that asks your server for a fresh link:
While your server responds, the button shows a loading state and ignores repeat clicks. If createCheckout throws, takes longer than 20 seconds, or returns anything other than a Platnova checkout link, the button resets and shows “We couldn’t open checkout. Please try again.” It also calls onError and dispatches a platnova:error event that bubbles up from the button.

Options

Pass either checkoutUrl or createCheckout, not both. PlatnovaPay.button returns { element, destroy }. If your single-page app adds buttons after the page loads, call PlatnovaPay.init() to pick them up.
The button only ever sends customers to Platnova’s checkout (https://pay.platnova.com, plus the sandbox checkout host). It refuses any other link, so nobody can use it to redirect your customers somewhere else. A link it refuses is left exactly as you wrote it, and the reason is logged in the browser console.
The button renders in its own isolated styles (Shadow DOM), so your site’s CSS won’t change how it looks. It is a real link or button, so it works with the keyboard and screen readers, and it shows a visible focus ring.

4. Handle the redirect back

After a successful payment, the checkout shows a confirmation and then sends the customer to your success_url. Use that page to thank them. A customer who decides not to pay can use Cancel and return to [your business name] on the checkout, which sends them to your cancel_url in the same tab, exactly as you sent it. If they may already be paying (for example, they have an open bank-transfer account or crypto invoice), the checkout asks them to confirm first, because the payment can still arrive after they leave. If you leave out cancel_url, the checkout shows no return action and customers can only close the tab, so always send your own cancel_url. Either way, keep the order payable on your side until the checkout is paid or you cancel the order. With option B, the button resets when they come back to your page. A visit to success_url is not proof of payment: anyone can type that URL into their browser.

5. Confirm the payment on your server

Confirm the payment from your server before you fulfil the order. Use either or both of these:
  • Webhook (recommended). Configure a webhook for checkout.paid, and checkout.failed if you want to hear about payments that did not settle. The event’s data.checkout_id matches the id you saved in step 1. data.amount is what you are credited, data.paid_amount is what the customer paid, and data.reference is the payment reference.
  • Retrieve the checkout. Call GET /v1/checkout/{id}. A paid checkout has status: "success" with paid_at and payment_reference. An unpaid one stays pending.
Check that the amount and currency match your order before you mark it paid.

No JavaScript? Use a button image

If you can’t run scripts, for example in an email, link a static button image to the checkout url:
Email clients often block SVG, so use the PNG there. To see every variant live, open the button demo page.

Testing in sandbox

Point your server at https://sandbox.api.platnova.co with your sandbox API key. Sandbox checkout links live on Platnova’s sandbox checkout host, and the button accepts them exactly as it accepts live ones. See Environments.