Generate PIN View Token
curl --request POST \
--url https://api.example.com/v1/card/pin/token \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--header 'x-client-key: <x-client-key>' \
--data '
{
"customCss": {
"customCss.backgroundColor": "<string>",
"customCss.textColor": "<string>"
}
}
'import requests
url = "https://api.example.com/v1/card/pin/token"
payload = { "customCss": {
"customCss.backgroundColor": "<string>",
"customCss.textColor": "<string>"
} }
headers = {
"x-client-key": "<x-client-key>",
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-client-key': '<x-client-key>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
customCss: {'customCss.backgroundColor': '<string>', 'customCss.textColor': '<string>'}
})
};
fetch('https://api.example.com/v1/card/pin/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/card/pin/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customCss' => [
'customCss.backgroundColor' => '<string>',
'customCss.textColor' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json",
"x-client-key: <x-client-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/card/pin/token"
payload := strings.NewReader("{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-client-key", "<x-client-key>")
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/card/pin/token")
.header("x-client-key", "<x-client-key>")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/card/pin/token")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-client-key"] = '<x-client-key>'
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebb",
"imageUrl": "https://cards.baanx.com/details-image?token=100a99cf-f4d3-4fa1-9be9-2e9828b20ebb"
}
Card
Generate PIN View Token
Generate a secure token for viewing the card PIN through an image-based display
POST
/
v1
/
card
/
pin
/
token
Generate PIN View Token
curl --request POST \
--url https://api.example.com/v1/card/pin/token \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--header 'x-client-key: <x-client-key>' \
--data '
{
"customCss": {
"customCss.backgroundColor": "<string>",
"customCss.textColor": "<string>"
}
}
'import requests
url = "https://api.example.com/v1/card/pin/token"
payload = { "customCss": {
"customCss.backgroundColor": "<string>",
"customCss.textColor": "<string>"
} }
headers = {
"x-client-key": "<x-client-key>",
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-client-key': '<x-client-key>',
Authorization: '<authorization>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
customCss: {'customCss.backgroundColor': '<string>', 'customCss.textColor': '<string>'}
})
};
fetch('https://api.example.com/v1/card/pin/token', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/card/pin/token",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'customCss' => [
'customCss.backgroundColor' => '<string>',
'customCss.textColor' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json",
"x-client-key: <x-client-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/card/pin/token"
payload := strings.NewReader("{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-client-key", "<x-client-key>")
req.Header.Add("Authorization", "<authorization>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/card/pin/token")
.header("x-client-key", "<x-client-key>")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/card/pin/token")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-client-key"] = '<x-client-key>'
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"customCss\": {\n \"customCss.backgroundColor\": \"<string>\",\n \"customCss.textColor\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebb",
"imageUrl": "https://cards.baanx.com/details-image?token=100a99cf-f4d3-4fa1-9be9-2e9828b20ebb"
}
Overview
Generates a time-limited secure token that allows users to view their card PIN as a secure image. The PIN is never transmitted to or stored by your application, ensuring security and compliance.PCI ComplianceThis endpoint maintains PCI compliance by delivering PIN data as a secure image. Your application never handles the actual PIN value.
Authentication
This endpoint requires authentication via Bearer token:Authorization: Bearer YOUR_ACCESS_TOKEN
Request
Headers
string
required
Your public API client key
boolean
default:false
Set to
true to route requests to the US backend environmentstring
required
Bearer token for authentication
Body
The request body is optional. If omitted, default styling will be applied to the PIN image.
object
Customize the visual appearance of the PIN image
Request Example
curl -X POST https://dev.api.baanx.com/v1/card/pin/token \
-H "x-client-key: YOUR_CLIENT_KEY" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"customCss": {
"backgroundColor": "#EFEFEF",
"textColor": "#000000"
}
}'
const response = await fetch('https://dev.api.baanx.com/v1/card/pin/token', {
method: 'POST',
headers: {
'x-client-key': 'YOUR_CLIENT_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
customCss: {
backgroundColor: '#EFEFEF',
textColor: '#000000'
}
})
});
const data = await response.json();
console.log('PIN image URL:', data.imageUrl);
import requests
url = "https://dev.api.baanx.com/v1/card/pin/token"
headers = {
"x-client-key": "YOUR_CLIENT_KEY",
"Authorization": "Bearer YOUR_ACCESS_TOKEN",
"Content-Type": "application/json"
}
payload = {
"customCss": {
"backgroundColor": "#EFEFEF",
"textColor": "#000000"
}
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
print(f"PIN image URL: {data['imageUrl']}")
interface PinTokenRequest {
customCss?: {
backgroundColor?: string;
textColor?: string;
};
}
interface PinTokenResponse {
token: string;
imageUrl: string;
}
const generatePinToken = async (
config?: PinTokenRequest
): Promise<PinTokenResponse> => {
const response = await fetch('https://dev.api.baanx.com/v1/card/pin/token', {
method: 'POST',
headers: {
'x-client-key': 'YOUR_CLIENT_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: config ? JSON.stringify(config) : undefined
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
};
Response
Success Response
string
Secure, time-limited token (UUID format)Lifetime: ~10 minutesUsage: Single-use token that becomes invalid after the image is accessed
string
URL that renders PIN as a secure imageUsage: Display PIN by using this URL as the
src attribute of an <img> tagFormat: <HOST>/details-image?token={token}Security: Treat this URL as highly sensitive. Do not log or store it.{
"token": "100a99cf-f4d3-4fa1-9be9-2e9828b20ebb",
"imageUrl": "https://cards.baanx.com/details-image?token=100a99cf-f4d3-4fa1-9be9-2e9828b20ebb"
}
Error Responses
{
"message": "Not authenticated"
}
{
"message": "Not authorized"
}
{
"message": "Card not found"
}
{
"message": "Validation error",
"errors": [
{
"field": "customCss.backgroundColor",
"message": "Invalid hex color format"
}
]
}
{
"message": "Invalid client key"
}
{
"message": "Missing client key"
}
{
"message": "Internal server error"
}
Integration Method
Display PIN as a secure image without interactive elements.Basic Implementation
const { imageUrl } = await generatePinToken({
customCss: {
backgroundColor: '#EFEFEF',
textColor: '#000000'
}
});
const img = document.createElement('img');
img.src = imageUrl;
img.alt = 'Card PIN';
img.style.maxWidth = '100%';
img.style.borderRadius = '8px';
document.getElementById('pin-image-container').appendChild(img);
React Component Example
import { useState } from 'react';
export function PinImageViewer() {
const [imageUrl, setImageUrl] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleViewPin = async () => {
setLoading(true);
setError(null);
try {
const response = await fetch('https://dev.api.baanx.com/v1/card/pin/token', {
method: 'POST',
headers: {
'x-client-key': 'YOUR_CLIENT_KEY',
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
'Content-Type': 'application/json'
},
body: JSON.stringify({
customCss: {
backgroundColor: '#EFEFEF',
textColor: '#000000'
}
})
});
if (!response.ok) {
throw new Error('Failed to generate PIN token');
}
const data = await response.json();
setImageUrl(data.imageUrl);
} catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred');
} finally {
setLoading(false);
}
};
return (
<div>
<button onClick={handleViewPin} disabled={loading}>
{loading ? 'Loading...' : 'View PIN'}
</button>
{error && <div className="error">{error}</div>}
{imageUrl && (
<div className="pin-image-container">
<img
src={imageUrl}
alt="Card PIN"
style={{ maxWidth: '100%', borderRadius: '8px' }}
/>
<button onClick={() => setImageUrl(null)}>Close</button>
</div>
)}
</div>
);
}
Security NoteImage URLs contain sensitive PIN information. Always:
- Use HTTPS only
- Never log or store the imageUrl
- Display in secure contexts only
- Clear the image from DOM when user is done viewing
Customization Examples
Dark Theme
{
"customCss": {
"backgroundColor": "#1F2937",
"textColor": "#F9FAFB"
}
}
Light Theme
{
"customCss": {
"backgroundColor": "#FFFFFF",
"textColor": "#111827"
}
}
Brand Colors
{
"customCss": {
"backgroundColor": "#F0F9FF",
"textColor": "#0C4A6E"
}
}
Security Best Practices
Token Security
- Tokens expire after ~10 minutes
- Single-use tokens become invalid after first access
- Generate new tokens for each PIN view request
- Never store, cache, or log tokens
PCI ComplianceUsing this endpoint ensures PCI compliance as PIN data is delivered as a secure image. Your application never handles the actual PIN value.
URL HandlingTreat
imageUrl as highly sensitive. Use HTTPS only, never log these URLs, and display only in authenticated, secure contexts.Best Practices
Error Handling
async function showPIN() {
try {
const { imageUrl } = await generatePinToken({
customCss: {
backgroundColor: '#EFEFEF',
textColor: '#000000'
}
});
const img = document.createElement('img');
img.src = imageUrl;
img.alt = 'Card PIN';
img.style.maxWidth = '100%';
document.getElementById('pin-container').appendChild(img);
} catch (error) {
if (error.response?.status === 404) {
alert('No card found. Please order a card first.');
} else if (error.response?.status === 401) {
alert('Session expired. Please log in again.');
} else if (error.response?.status === 422) {
alert('Invalid styling parameters. Please check your customCss values.');
} else {
alert('Failed to load PIN. Please try again.');
}
}
}
Cleanup After Viewing
function createPINViewer() {
let currentImage: HTMLImageElement | null = null;
async function showPIN() {
const { imageUrl } = await generatePinToken();
currentImage = document.createElement('img');
currentImage.src = imageUrl;
currentImage.alt = 'Card PIN';
document.getElementById('pin-container').appendChild(currentImage);
}
function hidePIN() {
if (currentImage) {
currentImage.remove();
currentImage = null;
}
}
return { showPIN, hidePIN };
}
const pinViewer = createPINViewer();
Related Endpoints
POST /v1/card/set-pin/token- Generate token to set or change card PINPOST /v1/card/details/token- Generate token to view card detailsGET /v1/card/status- Check card status before viewing PIN
Was this page helpful?
⌘I