// docs · merchants
widget.js · light & dark · allowed origins · POST /v1/pay · zero checkout JavaScript
Add a single script tag to your public page. The script injects a button; buyers pick an amount, we call POST /v1/pay with your API key, then open the hosted checkout URL in a new tab. Checkout itself stays server-rendered HTML — no JavaScript required for the buyer there.
There is no npm package: the file is plain JavaScript served from this site's /widget.js.
Live demo: /demo/activist.
widget.js livesAbsolute URL (production default): https://lolipop.cash/widget.js
The embed supports light and dark UIs. By default it follows the visitor’s system preference (prefers-color-scheme) — use data-theme="auto" or omit the attribute.
To pin one look, set data-theme="light" or data-theme="dark" on the same tag as your data-api-key (or on #lolipop-widget-anchor when the key lives there). To sync with your own theme toggle without reloading the script, update data-lpw-theme on #lpw-root or dispatch a window CustomEvent named lolipop-theme-change with detail: 'light' or 'dark'. On this site, /demo/activist follows the nav theme that way.
Set these on the same script tag as src="…/widget.js", or on #lolipop-widget-anchor when the executing script has no key (see /demo/activist).
| attribute | required | description |
|---|---|---|
data-api-key | yes | Full sk_live_… secret (widget-only key recommended). |
data-api-base | no | API origin; default https://api.lolipop.cash |
data-presets | no | Comma-separated fiat amounts; default 5,10,25 |
data-currency | no | Fiat code; default USD |
data-recipient-name | no | Shown on checkout as name; default Support |
data-recipient-sub | no | Subtitle under recipient (e.g. journalist · privacy advocate); hidden if empty |
data-button-text | no | Label on the injected button (modal mode only) |
data-inline | no | If true / 1 / yes: form in page flow (no overlay, no trigger button). |
data-auto-open | no | Modal only: opens overlay on load; trigger stays hidden until close. |
data-theme | no | auto (default): light UI when prefers-color-scheme is light. light or dark: force palette. Hosts can also sync via lolipop-theme-change — see light & dark mode. |
data-locale | no | en or de for widget UI strings. If omitted, uses navigator.language (German when the primary tag is de). The widget sends checkout_locale on POST /v1/pay so the hosted checkout HTML matches; JSON API error messages stay English. |
The sk_live_ secret is visible in your page source — treat it like a capability token, not a password to your whole account. Use a key scoped to create_orders only, rotate if leaked, and keep allowed origins as short a list as practical.
Origin checks stop other websites from using your key in a browser; they do not stop someone who copies the key and calls the API from a server (Origin can be spoofed off-browser). Server integrations should use a different key with an IP allowlist instead.
Replace placeholders before going live. Do not use async or defer on this script tag.
Optional attributes (same tag as data-api-key): data-inline="true" — form in page flow (no overlay); see live demo. data-auto-open="true" — modal only: open overlay on load. data-theme="auto" (or omit) — match visitor system light/dark; data-theme="light" or "dark" — force one palette. Site-toggle sync: light & dark mode.
<script src="https://lolipop.cash/widget.js"
data-api-key="YOUR_SK_LIVE_WIDGET_KEY"
data-api-base="https://api.lolipop.cash"
data-recipient-name="Your collective"
data-presets="5,10,25,50"
></script>