Secure Iframe Guide
Display a card's sensitive details (card number, expiry, CVV) in a PCI-compliant manner using a secure popup window or iframe, without your application ever handling raw card data directly.
This method renders card details using Base64-encoded card ID and user ID values passed in the URL, along with optional style parameters to match your application's theme.
Security Note: This URL exposes sensitive card data (PAN, expiry, CVV) once loaded. Always render it inside a sandboxed iframe or popup — never fetch or proxy the response through your own backend, and never log the resolved URL.
Card Details Preview
Secure Iframe Test Harness
Generate a live, PCI-compliant card details URL and preview the rendered iframe.
Enter a Card ID and User ID, then generate the URL to preview the embedded card view here.
URLs
| Environment | URL Pattern |
|---|---|
| Sandbox | https://spend.sandbox.zoqq.com/cardSensetiveDetails/{{card_id}}/{{x_user_id}}?styles={{styleEncoding}} |
| Production | https://spend.zoqq.com/cardSensetiveDetails/{{card_id}}/{{x_user_id}}?styles={{styleEncoding}} |
Quick Start
const cardId = "your-card-id";
const xUserId = "your-user-id";
const encodedCardId = btoa(cardId);
const encodedXUserId = btoa(xUserId);
const styles = {
".uq-card-container": {
"background-color": "#ffffff",
"border-radius": "12px"
}
};
const styleEncoding = encodeURIComponent(JSON.stringify(styles));
const url = `https://spend.sandbox.zoqq.com/cardSensetiveDetails/${encodedCardId}/${encodedXUserId}?styles=${styleEncoding}`;
Embedding as an Iframe
<iframe
src="https://spend.sandbox.zoqq.com/cardSensetiveDetails/{{card_id}}/{{x_user_id}}?styles={{styleEncoding}}"
width="520"
height="280"
sandbox="allow-scripts allow-same-origin"
style="border: none; border-radius: 12px;"
title="Secure Card Details"
></iframe>
Recommended container size: 520px × 280px. Adjust styling via the styles parameter rather than resizing content post-load, to avoid layout shift or clipped fields.
Parameters
| Parameter | Required | Description |
|---|---|---|
card_id | Yes | Base64-encoded card ID appended to the URL path. Example: const encodedCardId = btoa(cardId); |
x_user_id | Yes | Base64-encoded user ID appended to the URL path. Example: const encodedXUserId = btoa(xUserId); |
styles | No | A JSON object of CSS overrides, URL-encoded (not Base64). Example: const styleEncoding = encodeURIComponent(JSON.stringify(theme)); |
Supported Style Selectors
| Selector | Description |
|---|---|
body, html | Page background |
.uq-card-container | Card container |
.uq-card-label | Field labels |
.uq-card-number | Card number |
.uq-card-expiry | Expiry |
.uq-card-cvv | CVV |
.uq-card-button | Copy button |
.uq-card-button:hover | Button hover state |
.uq-card-tooltip | Tooltip |
Full Example
const cardId = "your-card-id";
const xUserId = "your-user-id";
const encodedCardId = btoa(cardId);
const encodedXUserId = btoa(xUserId);
const styleEncoding = encodeURIComponent(JSON.stringify(theme));
const url = `https://spend.sandbox.zoqq.com/cardSensetiveDetails/${encodedCardId}/${encodedXUserId}?styles=${styleEncoding}`;
Session Behavior
- The session expires after 60 seconds.
- Reload the iframe/popup to start a new session — the URL must be regenerated (not cached or reused) on reload.
- The
stylesparameter is optional; omitting it renders with default styling.
Error Handling
The following error states may be returned:
| Error | Likely Cause |
|---|---|
| Card ID is missing | card_id not appended to the URL |
| User ID is missing | x_user_id not appended to the URL |
Invalid card_id format | Value isn't valid Base64, or doesn't decode to a valid card ID |
| Card not found or deactivated | Card ID is valid but doesn't match an existing/active card |
| Unable to fetch secure card details | Backend/network issue while resolving the card |
| Failed to load secure card details | Rendering failure on the secure details page itself |
| Session expired | More than 60 seconds elapsed since the URL was generated |
Implementation Notes
card_id— must be Base64 encoded.x_user_id— must be Base64 encoded.styles— must be URL-encoded JSON (not Base64). Do not Base64-encode the styles object; onlyencodeURIComponentit.- Do not persist or cache the generated URL — treat it as a short-lived, single-use link tied to the 60-second session.