Skip to main content

Widget configuration

Complete reference for everything you can configure on the <veridia-widget> custom element.

All attributes

AttributeRequiredDefaultDescription
publishable-keyYes-Your qv_pub_* or qv_pub_test_* key
api-baseYes-API endpoint (https://api.xxuxe.online for production)
user-refNo-Your own user identifier (max 128 chars)
countryNo-ISO 3166-1 alpha-2 country code (PY, BR, MX, etc.)
document-typeNo-dni, passport, drivers_license, national_id, or other
submitted-full-nameNo-User's full name for fuzzy matching (max 255 chars)
require-doc-backNo"false"Set "true" if document needs back-side capture
localeNobrowserUI language: en, es, pt
accent-colorNo#2563EBHex color for buttons and active states

Attribute details

publishable-key (required)

The key that identifies your tenant. Two prefixes:

  • qv_pub_test_* — test environment (free, doesn't count toward billing)
  • qv_pub_* — live environment (real billing)

Get yours from the dashboard under API keys.

<veridia-widget publishable-key="qv_pub_test_FJJWXMA2RN2XPRDK6YJX4KTVD0XSQHW9">

api-base (required)

The Veridia API endpoint. For production, always:

<veridia-widget api-base="https://api.xxuxe.online">

Your own identifier for the user. Echoed back in webhook events under userRef. Max 128 chars. Recommended pattern: your DB primary key.

<veridia-widget user-ref="customer-12345">

ISO 3166-1 alpha-2 country code. Improves OCR accuracy by hinting which document layout to expect.

<veridia-widget country="PY">

Common LATAM codes:

CodeCountry
PYParaguay
BRBrazil
MXMexico
ARArgentina
COColombia
CLChile
PEPeru
UYUruguay

document-type (optional)

Hint of what document the user will submit. The VLM still validates, but this improves prompting.

ValueDescription
dniNational ID card (DNI, CI, cedula)
passportPassport
drivers_licenseDriver's license
national_idGeneric national ID
otherAny other ID document
<veridia-widget document-type="dni">

submitted-full-name (optional)

The user's full legal name as they typed it on your form. Used by the backend for fuzzy matching against the OCR'd name. Improves verdict accuracy when names match.

<veridia-widget submitted-full-name="Juan Carlos Perez Gonzalez">

If the OCR result matches (allowing for typos and ordering), it boosts confidence. If it doesn't match at all, a name_mismatch flag fires.

require-doc-back (optional)

Set to "true" if your document type requires a back-side photo. Defaults to "false".

<veridia-widget require-doc-back="true">

When "true", the widget adds a third capture step between document front and selfie.

When you need it: most Latin American DNIs/CIs have important info (address, MRZ) on the back. Brazilian RG, Mexican INE, and similar always need both sides.

locale (optional)

UI language. Defaults to browser language, falls back to English.

ValueLanguage
enEnglish
esSpanish
ptPortuguese (Brazil)
<veridia-widget locale="es">

accent-color (optional)

Hex color for primary buttons, active states, and progress indicators. Defaults to #2563EB (blue).

<veridia-widget accent-color="#7C3AED"> <!-- purple -->
<veridia-widget accent-color="#10B981"> <!-- green -->
<veridia-widget accent-color="#F59E0B"> <!-- amber -->

Stick to colors with WCAG AA contrast against white. Avoid pastels — they fail accessibility checks.

Events

The widget emits two CustomEvents on the host element.

veridia:complete

Fired when the user has finished captures and the API has accepted the submission. The verdict is not in this event — you still need to fetch it from the API or wait for the webhook.

widget.addEventListener('veridia:complete', (e) => {
console.log(e.detail);
// {
// verificationId: "vf_AG07CDWRRFQV4T05ZXG2",
// userRef: "customer-12345",
// status: "queued"
// }
});

The e.detail contains:

FieldTypeDescription
verificationIdstringThe ID to fetch the verdict with
userRefstring | nullThe user-ref you passed in
statusstringInitial status — usually "queued"

veridia:error

Fired when something goes wrong client-side that the user can't recover from (auth failure, network down, etc.).

widget.addEventListener('veridia:error', (e) => {
console.error(e.detail);
// {
// code: "errorInvalidKey",
// message: "API key is invalid or revoked",
// detail: { ... }
// }
});

The e.detail contains:

FieldTypeDescription
codestringMachine-readable error code
messagestringHuman-readable summary
detailobjectOptional extra context

Common error codes:

CodeMeaning
errorInvalidKeyBad/revoked publishable key
errorRateLimitedToo many requests
errorInsufficientCreditsTenant has 0 credits
errorBlurryCapture quality below threshold (auto-retried)
errorNoFaceSelfie has no detectable face (auto-retried)
errorUploadR2 upload failed (auto-retried)
errorNetworkGeneric network failure

The widget handles errorBlurry, errorNoFace, and errorUpload automatically by prompting the user to retry. The other codes are surfaced to your handler.

Updating attributes at runtime

You can change attributes via JavaScript. The widget reactively updates:

const widget = document.querySelector('veridia-widget');

// Change locale dynamically
widget.setAttribute('locale', 'pt');

// Change accent color
widget.setAttribute('accent-color', '#10B981');

// Change country (must happen before user starts capturing)
widget.setAttribute('country', 'BR');

Limitation: changing publishable-key after the widget has been used once will reset the internal state. Don't do this mid-flow.

Sizing

The widget is responsive by default. It tries to fill its container's width, with a minimum height of 380px.

veridia-widget {
display: block;
width: 100%;
max-width: 600px;
min-height: 480px;
margin: 0 auto;
}

The internal layout adapts to mobile (under 480px) automatically.

Styling

The widget uses Shadow DOM for style isolation. Your page CSS does not affect the widget's internals, and the widget's CSS does not leak out.

What you can customize:

  • accent-color attribute (primary color)
  • The container element's size (width, height, margin)
  • Outside content (your page's heading, instructions, etc.)

What you can't customize without forking:

  • Internal typography
  • Internal spacing
  • Capture overlay design

If you need deeper customization, contact support — we offer a white-label tier with custom themes.

Multiple widgets on the same page

You can have multiple widget instances on a page (e.g., one for primary user, one for guarantor). Each operates independently:

<veridia-widget
id="primary-user"
publishable-key="..."
user-ref="user-123">
</veridia-widget>

<veridia-widget
id="guarantor"
publishable-key="..."
user-ref="guarantor-456">
</veridia-widget>

<script>
document.getElementById('primary-user').addEventListener('veridia:complete', (e) => {
// Handle primary user
});
document.getElementById('guarantor').addEventListener('veridia:complete', (e) => {
// Handle guarantor
});
</script>

Each instance loads face-api.js once globally — no double-loading penalty.

Performance notes

  • First load: ~6 MB face-api.js + ~150 KB widget = ~6.2 MB. Most users on 4G load it in 2-3 seconds.
  • Subsequent loads: cached by the browser; near-instant.
  • Model files: ~14 MB lazy-loaded the first time the user starts a capture. Cached after.
  • Total bandwidth per verification: ~20 MB first time, ~150 KB on repeat use.

For users on slow connections, consider a placeholder UI that shows while scripts load:

<div id="kyc-placeholder">
Loading verification widget...
</div>
<veridia-widget id="kyc" hidden ...></veridia-widget>

<script>
customElements.whenDefined('veridia-widget').then(() => {
document.getElementById('kyc-placeholder').remove();
document.getElementById('kyc').hidden = false;
});
</script>

What's next