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?