A minimal, runnable example of integrating Pay-Pi exactly the way the docs describe (pay-pi.com/docs/finix-js + pay-pi.com/docs/api-reference):
- The browser tokenizes the card with Finix.js — raw card details go straight to Finix and never touch your server.
- The browser sends only the token to your backend.
- Your backend adds the secret
X-Api-Keyand callsPOST /v1/payments.
No build step, no dependencies — just Node 18+.
public/index.html the checkout page (Finix.js v2 tokenization)
server.mjs the backend (/config, /pay, /refund) — holds the secret key
-
Get a sandbox API key. Log in to your dashboard → API keys → New key. Copy the
lc_live_…value (it's shown only once). Your merchant must be onboarded / charges-enabled — the dashboard shows this. -
Set your key + API base. Easiest — copy
.env.exampleto.envand fill in your key (the server loads.envautomatically; works on any OS/shell):PAYPI_API_KEY=lc_live_...your key... PAYPI_API_BASE=https://payments-cqcrd4hxaec7dtdw.southcentralus-01.azurewebsites.netOr set them in your shell instead of a file:
# macOS / Linux (bash/zsh) export PAYPI_API_KEY="lc_live_..." export PAYPI_API_BASE="https://payments-cqcrd4hxaec7dtdw.southcentralus-01.azurewebsites.net"
# Windows PowerShell $env:PAYPI_API_KEY="lc_live_..." $env:PAYPI_API_BASE="https://payments-cqcrd4hxaec7dtdw.southcentralus-01.azurewebsites.net"
Note: the docs use
https://connect.pay-pi.comas the base, but that custom domain isn't live in DNS yet — use the sandbox host above until it is. -
Start it:
node server.mjs
-
Open http://localhost:3000, enter the sandbox test card, pick an amount, and click Pay.
- Test card: 4111 1111 1111 1111, any future expiry, any 3-digit CVC.
- On the sandbox the amount drives the outcome: $4.99 approves, $0.51 declines, $0.01 is "call issuer".
- A successful payment shows the response (
lcPaymentId,status: succeeded, fee, Finix ids) and a Refund button.
server.mjs—/configreturns only the public Finix values (fromGET /v1/meta);/payis where the secret key is added andPOST /v1/paymentsis called with a requiredIdempotency-Key. The key is never sent to the browser.public/index.html— loadsjs.finix.com/v/2/finix.js, mountsFinix.PaymentForm(...), and on submit reads the token atresponse.data.id, thenPOSTs it to/pay.
When the production environment (and the connect.pay-pi.com domain) is available, swap PAYPI_API_BASE to it and
use a live key. Because the browser reads the app id + environment from /v1/meta at runtime, the frontend needs no
change — /v1/meta returns the live values automatically.
- Finix.js tokenization guide — the browser half, in depth.
- API reference — every endpoint this sample uses (and the rest).
- No-code check: the dashboard → Developer → Test your integration runs the same tokenize → charge → refund from your account without cloning anything.
MIT — see LICENSE. Copy freely.