Add the payment widget to your site
Load the Leapa widget, render a payment form, and read the result.
The Leapa widget is a custom HTML element that renders a payment form inside your own page. The payer’s browser sends card numbers straight to Leapa, so your site never stores or forwards them. This page takes you from an empty page to a working form.
This is what your payer sees. Ten lines of HTML put it on the page, and Leapa handles the card details, the bank’s identity check and the receipt:

Every attribute the element reads, with defaults and limits.
Events and responsesWhat the widget hands back when a payment succeeds or fails.
Before you start
You need three things:
- A Leapa account with a currency account in the currency you want to charge
- An API key issued for that currency account, from your account settings
- A page whose HTML you can edit
Your API key is a JSON Web Token (JWT), a signed string that records a few facts about you. The widget reads two of them. Your merchant country decides which payment methods appear, and the key itself says whether it is live or test.
Build against a test key
On every render the widget prints its environment and version to the browser
console, as [LEAPA:ENV]: Test - version: v3.2.0. Read that line to confirm
which key loaded. Switch to your live key only after both onSuccess and
onFailure do what you expect on your own page.
The widget serves two merchant countries:
- Burundi: card and BurundiPay
- Cameroon: card
With a key issued for any other country, the widget shows the payer a banner instead of a form, and names the country on your console.
Put the form on the page
Three steps: load the widget, place the element, listen for the result.
Load the widget
Add both tags to the <head> of your page:
The script defines the element. The stylesheet is 48 bytes and holds one rule, which hides the element until the script claims it.
Ask for the version by name
Both URLs name v3.2.0, and yours should too. A URL with no version in it
follows whatever Leapa published last, so a release you did not ask for can
change your checkout on a Tuesday morning. Pinning means you decide when
that happens.
Keep both tags
Drop the stylesheet and your page shows an empty inline box for a moment, laid out by your own CSS rather than by the widget.
Add the element
Put the element where you want the form to appear:
Three attributes are required in every mode: api-key, mode and description. Each mode adds one of its own: amount for charge, invoice-id for invoice, currency for add. Set currency anyway in the other two, because it is sent with the payment and it decides whether BurundiPay can appear.
The widget checks all of that before it renders. A rule that fails replaces the whole form with this banner:

The banner is deliberately vague, because the payer cannot fix an attribute and should not read your configuration. Open the console to find out which rule failed. Only the first failing rule is reported, so fix them one at a time.
The id matters when you place more than one widget on the same page. Give each one a different id so your event listeners can tell them apart.
Read the result
The widget reports back through two events on the element: onSuccess when Leapa accepts the payment, and onFailure when it does not.
The widget already shows the payer a green or red banner, so you do not have to render the outcome yourself. Use these events for the work only your site can do: store the customer ID you got back, mark an order paid, or send the payer to a thank-you page. Events and responses documents what event.detail holds in each case.
What the card form asks for
The card form always collects the card number, expiry, security code and a billing address. On top of that it shows a first name, a last name and an email field.
Pass a real value for any of those three and the widget fills it in and hides the field:
The second form asks only for the card and the address. The widget sends the name and email with the payment:

Two more attributes change the form. dob="true" adds a date of birth field, which is otherwise absent. tos="true" adds a required checkbox linking to Leapa’s terms of service, above the button. Widget attributes covers every combination.
The three modes
The mode attribute decides what the form does when the payer submits it.
Save a payment method with add
Use add to store a customer and a card for later, without taking money now:
The widget creates the customer, saves the card, and returns both objects. When a customer with that email already exists, it adds the card to that customer instead of failing. To add a second card to a customer you already know, pass customer-id and leave email out.
Visa cards register through a zero-amount charge, which is why an add form still needs a currency.
Take a payment with charge
Use charge to take money now. Add amount to the required set:
Amounts are in the main unit, not in cents
The example above charges 25.00 USD. Each currency has a floor and a ceiling, listed in Amount limits. An amount outside them shows a banner instead of the form.
Pay an existing invoice with invoice
Use invoice when you have already created an invoice in Leapa and want the payer to settle it:
invoice-id is required here. amount is not, but pass it anyway: BurundiPay puts the figure on the Pay button, so a payer approving a request sees what they are approving.
Invoice mode is also the only mode that offers BurundiPay. Both of its rails settle against an invoice, so a Burundi merchant charging directly sees card alone.
Choose which payment methods appear
By default the widget offers every method the merchant’s country supports, and shows a chooser only when there is more than one:

Set source-type to pin one method and drop the chooser:
| Value | What the payer gets |
|---|---|
all | Every method the country supports. This is the default |
card | The card form only |
burundipay | BurundiPay, with both of its rails on one screen |
burundipay-qr | BurundiPay, pinned to the QR code |
burundipay-phone | BurundiPay, pinned to the phone request |
A Cameroon merchant on the default gets a card form and no chooser, because Cameroon supports card alone. A Burundi merchant on a BIF invoice gets both tiles, if their account is enabled for instant bank payments.
A pinned method never falls back
Pin a method the country does not support and the widget shows a banner rather than serving card in its place. That is deliberate: a page that quietly serves something else hides a broken integration.
Language and appearance
Set lang to translate every label, placeholder and error message. English and French are supported, and the widget follows the attribute when you change it after load:

Set theme to light, dark, or auto to follow the payer’s device. Leaving it out gives you a transparent background that sits on whatever your page paints behind it. You can also recolour the form to match your brand with CSS custom properties. Theming covers both.
What 3D Secure means for your checkout
3D Secure (3DS) is an extra identity check that card networks run during a card payment. You know it by its brand names, Visa Secure and Mastercard Identity Check. The widget runs it for you on every card payment, and there is nothing to configure.
Card-not-present payments, meaning any payment where nobody swipes the physical card, are more open to fraud than in-person ones. 3DS shifts that risk by asking the bank to confirm the payer is the real cardholder before the payment goes through.
When the bank wants that confirmation, it takes over the screen and asks for a code it sent to the payer’s phone or email:

Not every payment is challenged. The bank decides, and a payment can pass without the payer seeing anything. Either way the widget waits for the outcome and then fires onSuccess or onFailure, so your code handles both paths the same way.
BurundiPay does not use 3DS. The payer approves in their bank app instead.
Test before you go live
A test key runs against Leapa’s test environment and the card networks’ staging authentication service, so no real money moves. These are the gateway test card numbers:
| Card number | Pays as |
|---|---|
4456530000001096 | Visa |
5123450000000008 | Mastercard, in XAF |
Any future expiry date and any three-digit security code work with them.
Localhost talks to a different API
On localhost the widget calls Leapa’s development API rather than the
production one. Use a key issued for that environment while you build, and
re-test on a deployed URL before you ship.