TypeScript/JavaScript ๐
The official TypeScript/JavaScript client for the CardScan API provides a type-safe interface for all API operations.
Installation
npm install @cardscan.ai/cardscan-client
# or
yarn add @cardscan.ai/cardscan-client
# or
pnpm add @cardscan.ai/cardscan-client
Basic Usage
import { CardScanApi } from '@cardscan.ai/cardscan-client';
// Initialize with your API key
const apiKey = 'sk_test_cardscan_ai_...';
const client = new CardScanApi({ apiKey });
// Generate a session token for a user
const { Token, IdentityId, session_id } = await client.getAccessToken({
user_id: 'unique-user-123'
});
// Initialize client with session token for frontend operations
const userClient = new CardScanApi({
sessionToken: Token,
live: false // Use sandbox environment
});
Quick Start with fullScan
The easiest way to scan cards is using the fullScan
helper method that handles the entire workflow:
// Initialize with websocket URL for fullScan support
const client = new CardScanApi({
apiKey: 'sk_test_cardscan_ai_...',
websocketUrl: 'wss://sandbox.cardscan.ai/v1/ws' // Required for fullScan
});
// Scan a card (front and back)
async function scanCard() {
// For Node.js - using file paths
const result = await client.fullScan({
frontImage: './front-card.jpg',
backImage: './back-card.jpg' // Optional - omit for front-only
});
// For browser - using File objects from input
const frontFile = document.getElementById('front-input').files[0];
const backFile = document.getElementById('back-input').files[0];
const result = await client.fullScan({
frontImage: frontFile,
backImage: backFile // Optional
});
// Access the results
console.log('Card ID:', result.card_id);
console.log('Member ID:', result.details.member_id);
console.log('Group:', result.details.group_number);
console.log('Payer:', result.details.payer_name);
return result;
}
The fullScan
method automatically:
Creates a card with appropriate settings
Generates upload URLs
Uploads images in the correct order
Monitors processing via WebSocket
Returns the completed card with all extracted data
Manual Card Scanning Workflow
For more control over the scanning process, you can use the step-by-step approach:
1. Create a Card
const card = await userClient.createCard({
enable_backside_scan: false,
enable_livescan: false,
metadata: {
patient_id: '12345',
visit_id: 'v-67890'
}
});
console.log('Card ID:', card.card_id);
console.log('State:', card.state); // 'pending'
2. Generate Upload URL
const uploadData = await userClient.generateCardUploadUrl({
card_id: card.card_id,
orientation: 'front',
capture_type: 'manual'
});
// uploadData contains:
// - upload_url: Pre-signed S3 URL
// - upload_parameters: Form data fields for upload
3. Upload Image
// Create form data with upload parameters
const formData = new FormData();
Object.entries(uploadData.upload_parameters).forEach(([key, value]) => {
formData.append(key, value as string);
});
// Add the image file last
formData.append('file', imageFile);
// Upload directly to S3
await fetch(uploadData.upload_url, {
method: 'POST',
body: formData
});
4. Poll for Results
async function waitForCompletion(cardId: string): Promise<CardApiResponse> {
while (true) {
const card = await userClient.getCard({ card_id: cardId });
if (card.state === 'completed' || card.state === 'error') {
return card;
}
// Wait 2 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
const completedCard = await waitForCompletion(card.card_id);
console.log('Insurance Info:', completedCard.details);
Error Handling
import { ApiError } from '@cardscan.ai/cardscan-client';
try {
const card = await client.getCard({ card_id: 'invalid-id' });
} catch (error) {
if (error instanceof ApiError) {
console.error('API Error:', error.status, error.body);
switch (error.status) {
case 401:
console.error('Invalid API key or session token');
break;
case 404:
console.error('Card not found');
break;
case 429:
console.error('Rate limit exceeded');
break;
}
}
}
WebSocket Support
For real-time updates, connect to the WebSocket API:
const ws = new WebSocket(`wss://sandbox.cardscan.ai/v1/ws?token=${Token}`);
ws.onmessage = (event) => {
const message = JSON.parse(event.data);
switch (message.type) {
case 'card.processing':
console.log('Card processing started');
break;
case 'card.completed':
console.log('Card completed:', message.card_id);
break;
case 'card.error':
console.error('Card error:', message.error);
break;
}
};
Eligibility Verification
// Create eligibility request
const eligibility = await client.createEligibility({
card_id: completedCard.card_id,
eligibility: {
provider: {
first_name: 'John',
last_name: 'Smith',
npi: '1234567890'
},
subscriber: {
first_name: completedCard.details.member_name,
last_name: completedCard.details.member_name,
date_of_birth: '1980-01-01'
}
}
});
// Poll for eligibility results
const eligibilityResult = await waitForEligibilityCompletion(
eligibility.eligibility_id
);
Helper Methods
Full Scan Helper
The client includes a fullScan
helper method that simplifies the entire card scanning workflow:
import { CardScanApi } from '@cardscan.ai/cardscan-client';
import { createReadStream } from 'fs'; // Node.js only
const client = new CardScanApi({
apiKey: 'sk_test_cardscan_ai_...',
websocketUrl: 'wss://sandbox.cardscan.ai' // Required for fullScan
});
// Full card scan with front and back images
async function scanCard() {
try {
// Node.js - using file streams
const frontImage = createReadStream('./front-card.jpg');
const backImage = createReadStream('./back-card.jpg');
// Browser - using File objects from input[type="file"]
// const frontImage = document.getElementById('front-input').files[0];
// const backImage = document.getElementById('back-input').files[0];
// The fullScan method handles:
// 1. Creating a card with appropriate settings
// 2. Uploading images in correct order (front first, then back)
// 3. Waiting for processing completion via websockets
// 4. Returning the final card data with extracted information
const cardResult = await client.fullScan({
frontImage: frontImage,
backImage: backImage, // Optional - omit for front-only scanning
});
console.log('Card ID:', cardResult.card_id);
console.log('Extracted Data:', cardResult.details);
// Access extracted information
if (cardResult.details) {
console.log('Member ID:', cardResult.details.member_id);
console.log('Plan Name:', cardResult.details.plan_name);
console.log('Payer Name:', cardResult.details.payer_name);
}
} catch (error) {
console.error('Card scan failed:', error);
}
}
// Front-only scan
async function scanFrontOnly() {
const frontImage = createReadStream('./front-card.jpg');
const cardResult = await client.fullScan({
frontImage: frontImage
// No backImage parameter for front-only scanning
});
console.log('Front-only scan completed:', cardResult);
}
TypeScript Types
The client includes full TypeScript definitions for all API operations:
import type {
CardApiResponse,
CardState,
CreateCardRequest,
EligibilityApiResponse,
WebhookEvent
} from '@cardscan.ai/cardscan-client';
// All responses are fully typed
function processCard(card: CardApiResponse): void {
if (card.state === 'completed' && card.details) {
console.log('Member ID:', card.details.member_id);
console.log('Group Number:', card.details.group_number);
// TypeScript knows these fields might be undefined
if (card.details.rx_bin) {
console.log('RX BIN:', card.details.rx_bin);
}
}
}
Configuration Options
const client = new CardScanApi({
apiKey: 'sk_test_cardscan_ai_...',
// Optional configuration
baseUrl: 'https://sandbox.cardscan.ai/v1', // Override base URL
websocketUrl: 'wss://sandbox.cardscan.ai/v1/ws', // WebSocket URL (required for fullScan)
timeout: 30000, // Request timeout in milliseconds
retries: 3, // Number of retries for failed requests
retryDelay: 1000 // Delay between retries in milliseconds
});
Browser Usage
The client works in both Node.js and browser environments:
<!-- Using CDN -->
<script src="https://unpkg.com/@cardscan.ai/cardscan-client/dist/index.min.js"></script>
<script>
const client = new CardScanApi.CardScanApi({
apiKey: 'sk_test_cardscan_ai_...'
});
</script>
Source Code
View the source code and contribute: GitHub
Last updated
Was this helpful?