This page is not translated yet and is shown in English.

JavaScript widget

Embedding the widget on any stack, the server-side proxy it requires, its configuration and callbacks, and why the callback is not a gate.

Last updated: 2026-09-04

The widget is the integration for a storefront that is neither WooCommerce nor Shopify — a custom platform, a headless frontend, or anything else. It renders the verification step and reports what happened. It does not hold your API key, and it is not the thing that decides whether a purchase goes through.

It is one of three integrations, alongside WooCommerce and Shopify. Unlike those two, it expects you to write a small piece of server code.

The one thing to understand first

`baseUrl` points at your server, never at the eIDAS Pro API

The widget runs in the shopper's browser, so it can never hold a merchant API key. It calls a thin proxy on a domain you control, and that proxy is what attaches the key. Pointing baseUrl at https://api.eidas-pro.com does not work and would not be safe if it did.

So the shape is:

browser ── widget ──▶ your proxy ── x-merchant-api-key ──▶ eIDAS Pro API
                          │
your checkout ────────────┘   (server-to-server, the actual gate)

What the proxy has to expose

Two routes, which are the only ones the widget calls:

RouteWhat it does
POST {baseUrl}/verify/initCalls POST /api/verification/init with your key. Returns sessionId, authorizationUrl and expiresAt, plus qrCodeUrl when the session uses a QR-based method — absent on the redirect-based path, so treat it as optional and never assume it is there.
GET {baseUrl}/verify/status?sessionId=Reports the session's current state to the waiting page.

Two rules for writing it:

  • Never pass the key onward. Return only the public fields listed above.
  • Confirm the verdict yourself. When the session reaches a terminal state, your server should read the authenticated GET /api/verification/:sessionId/result and record the answer server-side. That record — not anything the browser reported — is what your checkout consults before it lets an order through.

Reference proxies for Node, PHP, Java and Go ship alongside the widget source; each one wires the key server-side and exposes exactly these two routes.

Getting the bundle

The widget builds to two files: eidas-widget.umd.cjs, which defines the browser global EIDASWidget, and eidas-widget.esm.js, which exports init. There is no public CDN or package-registry release to point at yet, so ask your eIDAS Pro contact for the current build, or build it from the widget source. Serve both from your own site alongside the rest of your JavaScript, and load whichever suits your stack — the examples below assume you have put them under /assets/.

Embedding it

<div id="verification-widget"></div>

<script src="/assets/eidas-widget.umd.cjs"></script>
<script>
  EIDASWidget.init({
    containerId: "verification-widget",
    baseUrl: "https://verify.your-shop.com",
    onVerified: function (verified) {
      if (verified) {
        document.getElementById("checkout-btn").disabled = false;
      }
    },
  });
</script>

Or as a module, importing the file you serve rather than a package name — there is no registry release, so a bare specifier would not resolve:

import { init } from "/assets/eidas-widget.esm.js";

init({
  containerId: "verification-widget",
  baseUrl: "https://verify.your-shop.com",
  onVerified: (verified, { sessionId }) => {
    console.log("outcome (UX signal only):", verified, sessionId);
  },
});

init() renders into the container and resolves once the session reaches a terminal state. It returns no instance to start or destroy later — to run another verification, call init() again.

Configuration

OptionTypeDefaultNotes
containerIdstringrequiredId of the element to render into. A missing element is a CONFIG error.
baseUrlstringrequiredYour proxy's origin. Not the eIDAS Pro API.
methodeudi idin itsmeRequest a specific method. Omit to take the proxy's or deployment's default; only ask for one that supportedMethods lists.
verificationTypeageageThe widget supports age only.
themelight darklightAdds a class. The widget ships no CSS.
localestringReserved. It does not localise anything yet.
pollingIntervalMsnumber2500How often the widget asks your proxy for the status.
timeoutMsnumber300000Overall bound. Note the session itself expires after 15 minutes.
metadataobjectForwarded to your proxy's /verify/init so you can carry an order id.

Callbacks

CallbackFires when
onVerifiedThe session reached a definitive verdict. true = passed, false = ran and did not pass. Also receives { sessionId }.
onStatusChangeOn each status poll while the session is in progress. The same status can repeat.
onErrorOn any non-verdict outcome. Inspect error.code.
onExpiredThe session reached the terminal expired state, alongside the EXPIRED error.

onError codes are CONFIG, NETWORK, TIMEOUT, CANCELLED, FAILED and EXPIRED. Note the split: a shopper who fails the check is a verdict and reaches onVerified(false); a shopper who closes the window, or a network that dies, is an error. Do not treat the two as the same thing — one is an answer, the other is the absence of one.

`onVerified` is a UX signal, not a security boundary

It runs in the shopper's browser, and anything in the browser can be made to say anything. Use it to enable a button or swap a message. Before you actually take the order, ask your own server — which read the authenticated result endpoint — whether that session passed.

What the shopper sees

Two shapes, chosen by what the session came back with:

  • Redirect. When the session has an authorizationUrl, the widget opens it in a popup and watches both the popup and the status in parallel, so a shopper who closes the window is reported as cancelled rather than left hanging. A blocked popup is a CONFIG error — tell the shopper to allow popups.
  • QR code. When the session came back with a QR image instead, the widget renders it and polls.

If a session comes back with neither, the widget reports FAILED rather than showing an empty box.

The widget polls only; it does not open the Server-Sent Events stream, and the reference proxies do not expose one. If you want push updates, that is server-side work on your side today.

Styling

The widget ships no CSS on purpose, so it inherits your site's styles instead of fighting them. It emits eidas-widget on every root element, plus eidas-qr, eidas-error or eidas-verified for the state, plus eidas-theme-light or eidas-theme-dark. Style those classes yourself.

Before you launch

Check the deployment can serve a verification at all:

curl https://api.eidas-pro.com/api/config

An empty supportedMethods array means every session your proxy starts will fail closed, no matter how the widget is configured. See how a verification works, and troubleshooting for what the proxy's errors mean.