Use this file to discover all available pages before exploring further.
Cardholders must set their PIN before card details can be viewed.If pin_set is false the API returns a 422 PIN_NOT_SET error with a ready-to-use pin_setup_url. Open that URL so the cardholder can set their PIN, then retry the view-token request. See Setting a Card PIN.
Card details (PAN, CVV, expiry) and the card PIN each use separate view tokens. You must request the correct enabled_views for each use case. Never reuse a token between sessions.
Sensitive card data is never returned in plain API responses. Instead, Yativo hosts a secure card view page and provides you with a short-lived URL to embed in your application:
Your backend calls POST /yativo-card/{yativoCardId}/cards/{cardId}/view-token
If pin_set is false, the API returns PIN_NOT_SET and a pin_setup_url — direct the cardholder there first
Once PIN is set, Yativo returns a secure_view_url — a hosted, tokenized page
Your frontend embeds that URL in an <iframe>
The hosted page renders the sensitive data directly — your application never touches the raw values
View tokens expire quickly. Always request a fresh token immediately before rendering and never cache or log secure_view_url.
Optional extra PIN or unlock code the user must enter before the card details are revealed. Adds an additional layer of protection for high-security flows.
interface ViewTokenSuccess { secure_view_url: string; // Hosted page URL — embed this in an iframe expires_at: string; // ISO 8601 — token is invalid after this last_four: string; // Last 4 digits — safe to display without the iframe card_type: string; // "virtual" | "physical" holder_name: string | null; // Cardholder display name pin_set: boolean; // Always true when this response is returned enabled_views: string[]; // Which views are active: ["data"] | ["pin"] | ["data", "pin"] requires_access_code: boolean; // True if access_code was set; user must enter it before details are shown}interface ViewTokenPinNotSet { // Returned when pin_set is false (HTTP 422) pin_setup_url: string; // Hosted PIN setup page — direct the cardholder here expires_at: string; last_four: string; card_type: string; holder_name: string | null; pin_set: false;}
Your frontend must never call the Yativo API directly with your credentials. Always proxy the token request through your backend:
Express.js
TypeScript SDK
Frontend (after fetch)
React
import express from 'express';const app = express();app.use(express.json());app.post('/api/card-view-token', async (req, res) => { // 1. Authenticate your own user first const user = await authenticateRequest(req); if (!user) return res.status(401).json({ error: 'Unauthorized' }); const { enabled_views, access_code, theme } = req.body; // 2. Validate enabled_views — only accept known values const VALID_VIEWS = ['data', 'pin']; if (enabled_views && !enabled_views.every(v => VALID_VIEWS.includes(v))) { return res.status(400).json({ error: 'Invalid enabled_views' }); } // 3. Look up this user's card IDs from your own database const { yativoCardId, cardId } = await getUserCardIds(user.id); // 4. Call Yativo from your backend — credentials never leave the server const response = await fetch( `https://crypto-api.yativo.com/api/v1/yativo-card/${yativoCardId}/cards/${cardId}/view-token`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.YATIVO_API_KEY}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ ...(enabled_views ? { enabled_views } : {}), ...(access_code ? { access_code } : {}), ...(theme ? { theme } : {}), }), } ); const payload = await response.json(); // PIN not yet set — return the setup URL so your frontend can redirect the cardholder if (!response.ok && payload.error_code === 'PIN_NOT_SET') { return res.status(422).json({ error_code: 'PIN_NOT_SET', message: payload.message, pin_setup_url: payload.data?.pin_setup_url, }); } if (!response.ok) { return res.status(502).json({ error: 'Failed to get view token' }); } // Return only the URL — do not cache it res.json(payload.data);});
import { YativoSDK } from '@yativo/crypto-sdk';const sdk = new YativoSDK({ baseURL: 'https://crypto-api.yativo.com/api/v1/', apiKey: process.env.YATIVO_API_KEY!, apiSecret: process.env.YATIVO_API_SECRET!,});// In your backend route handler:const result = await sdk.cards.getViewToken( 'yc_01HX9KZMB3F7VNQP8R2WDGT4E5', // yativoCardId 'card_01HX9KZMB3F7VNQP8R2WDGT4E5', // cardId { enabled_views: ['data', 'pin'], theme: { accent_color: '#813AE3', border_radius: 16, }, });// Send result.data.secure_view_url to your frontendreturn res.json({ url: result.data.secure_view_url });
<!-- Your frontend fetches the URL from your backend, then sets it on the iframe --><div id="card-view-wrapper"> <iframe id="card-iframe" title="Secure Card View" width="420" height="740" style="border:0;border-radius:16px;" allow="clipboard-read; clipboard-write"> </iframe></div><script> async function showCardDetails() { // Fetch from YOUR backend — never call Yativo directly from the browser const res = await fetch('/api/card-view-token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled_views: ['data', 'pin'] }), }); if (!res.ok) { console.error('Failed to get card view token'); return; } const { secure_view_url } = await res.json(); document.getElementById('card-iframe').src = secure_view_url; } showCardDetails();</script>
pin_set reflects the last known state from card activity webhooks. If pin_set is false the view-token request returns a PIN_NOT_SET error and a pin_setup_url — not a secure_view_url. Direct the cardholder to the setup URL, wait for the webhook confirmation, then retry.
When you pass access_code in the token request, requires_access_code: true is returned. The hosted page will prompt the user to enter that code before revealing any card details. Use this for:
Confirming user intent before showing the full card number
Adding a secondary verification step in high-value contexts
# Request with access codecurl -X POST '.../view-token' \ -d '{ "enabled_views": ["data"], "access_code": "7291" }'# Your user will see a prompt to enter 7291 before card details are shown
Use the test script in the backend repo to verify the full flow against your running server:
# Basic test (picks first card on the account)node scripts/test-card-secure-view.js <api_key> <api_secret># Target a specific cardnode scripts/test-card-secure-view.js <api_key> <api_secret> <yativo_card_id> <card_id># With custom views and themeENABLED_VIEWS=data,pin THEME_ACCENT_COLOR=#813AE3 \ node scripts/test-card-secure-view.js <api_key> <api_secret>
The script will print the secure_view_url and a ready-to-paste iframe snippet.
Virtual Cards
Create and manage virtual cards.
API Reference — View Token
Full parameter reference for the view-token endpoint.