Python ๐Ÿ

The official Python client for the CardScan API provides a pythonic interface for all API operations.

Installation

pip install cardscan-client

Basic Usage

from cardscan_client import CardScanApi
from cardscan_client.exceptions import ApiException

# Initialize with your API key
api_key = "sk_test_cardscan_ai_..."
client = CardScanApi(api_key=api_key)

# Generate a session token for a user
token_response = client.get_access_token(user_id="unique-user-123")
session_token = token_response["Token"]
identity_id = token_response["IdentityId"]
session_id = token_response["session_id"]

# Initialize client with session token for frontend operations
user_client = CardScanApi(session_token=session_token, live=False)

Quick Start with full_scan

The easiest way to scan cards is using the full_scan helper method that handles the entire workflow:

from cardscan_client import CardScanApi

# Initialize the client
client = CardScanApi(api_key="sk_test_cardscan_ai_...")

# Scan a card (front and back)
async def scan_card():
    # Using file paths
    result = await client.full_scan(
        front_image="./front-card.jpg",
        back_image="./back-card.jpg",  # Optional - omit for front-only
        user_id="unique-user-123"
    )
    
    # Or using file objects
    with open("./front-card.jpg", "rb") as front:
        with open("./back-card.jpg", "rb") as back:
            result = await client.full_scan(
                front_image=front,
                back_image=back,
                user_id="unique-user-123"
            )
    
    # Access the results
    print(f"Card ID: {result['card_id']}")
    print(f"Member ID: {result['details']['member_id']}")
    print(f"Group: {result['details']['group_number']}")
    print(f"Payer: {result['details']['payer_name']}")
    
    return result

# Run the async function
import asyncio
result = asyncio.run(scan_card())

The full_scan method automatically:

  • Generates a session token for the user

  • Creates a card with appropriate settings

  • Uploads images in the correct order

  • Polls for processing completion

  • 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

# Create a card with options
card = user_client.create_card(
    enable_backside_scan=False,
    enable_livescan=False,
    metadata={
        "patient_id": "12345",
        "visit_id": "v-67890"
    }
)

print(f"Card ID: {card['card_id']}")
print(f"State: {card['state']}")  # 'pending'

2. Generate Upload URL

# Generate pre-signed upload URL
upload_data = user_client.generate_card_upload_url(
    card_id=card["card_id"],
    orientation="front",
    capture_type="manual"
)

upload_url = upload_data["upload_url"]
upload_parameters = upload_data["upload_parameters"]

3. Upload Image

import requests

# Read image file
with open("insurance_card.jpg", "rb") as f:
    files = {"file": f}
    
    # Upload to S3 using pre-signed URL
    response = requests.post(
        upload_url,
        data=upload_parameters,
        files=files
    )
    response.raise_for_status()

4. Poll for Results

import time

def wait_for_completion(card_id, timeout=300):
    """Poll for card completion with timeout."""
    start_time = time.time()
    
    while time.time() - start_time < timeout:
        card = user_client.get_card(card_id=card_id)
        
        if card["state"] in ["completed", "error"]:
            return card
            
        time.sleep(2)  # Wait 2 seconds between polls
    
    raise TimeoutError(f"Card {card_id} did not complete within {timeout} seconds")

completed_card = wait_for_completion(card["card_id"])
print("Insurance Info:", completed_card.get("details"))

Error Handling

from cardscan_client.exceptions import ApiException

try:
    card = client.get_card(card_id="invalid-id")
except ApiException as e:
    print(f"API Error: {e.status} - {e.body}")
    
    if e.status == 401:
        print("Invalid API key or session token")
    elif e.status == 404:
        print("Card not found")
    elif e.status == 429:
        print("Rate limit exceeded")

Async Support

The client supports async operations using asyncio:

import asyncio
from cardscan_client import AsyncCardScanApi

async def scan_card_async():
    async_client = AsyncCardScanApi(api_key="sk_test_cardscan_ai_...")
    
    # All methods are available as async versions
    token_response = await async_client.get_access_token(
        user_id="unique-user-123"
    )
    
    card = await async_client.create_card(
        session_token=token_response["Token"],
        enable_backside_scan=False
    )
    
    return card

# Run async function
card = asyncio.run(scan_card_async())

WebSocket Support

For real-time updates using WebSocket:

import websocket
import json

def on_message(ws, message):
    data = json.loads(message)
    
    if data["type"] == "card.processing":
        print("Card processing started")
    elif data["type"] == "card.completed":
        print(f"Card completed: {data['card_id']}")
    elif data["type"] == "card.error":
        print(f"Card error: {data['error']}")

def on_error(ws, error):
    print(f"WebSocket error: {error}")

# Connect to WebSocket
ws_url = f"wss://sandbox.cardscan.ai/v1/ws?token={session_token}"
ws = websocket.WebSocketApp(
    ws_url,
    on_message=on_message,
    on_error=on_error
)

# Run in a separate thread
import threading
wst = threading.Thread(target=ws.run_forever)
wst.daemon = True
wst.start()

Eligibility Verification

# Create eligibility request
eligibility = client.create_eligibility(
    card_id=completed_card["card_id"],
    eligibility={
        "provider": {
            "first_name": "John",
            "last_name": "Smith",
            "npi": "1234567890"
        },
        "subscriber": {
            "first_name": "Jane",
            "last_name": "Smith",
            "date_of_birth": "1980-01-01"
        }
    }
)

# Poll for eligibility results
eligibility_result = wait_for_eligibility_completion(
    eligibility["eligibility_id"]
)

# Access eligibility information
if eligibility_result["state"] == "completed":
    summary = eligibility_result["eligibility_summarized_response"]
    print(f"Coverage Active: {summary['coverage_active']}")
    print(f"Copay: ${summary['copay']}")

Batch Operations

Process multiple cards efficiently:

def process_cards_batch(image_paths):
    """Process multiple insurance cards in parallel."""
    cards = []
    
    # Create cards
    for path in image_paths:
        card = user_client.create_card(enable_backside_scan=False)
        cards.append(card)
    
    # Upload images in parallel
    import concurrent.futures
    
    with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
        futures = []
        
        for card, image_path in zip(cards, image_paths):
            future = executor.submit(
                upload_and_process_card,
                card["card_id"],
                image_path
            )
            futures.append(future)
        
        # Wait for all uploads to complete
        results = [f.result() for f in futures]
    
    return results

Configuration Options

from cardscan_client import CardScanApi

# Custom configuration
client = CardScanApi(
    api_key="sk_test_cardscan_ai_...",
    base_url="https://sandbox.cardscan.ai/v1",
    retries=3,
    timeout=30,
    verify_ssl=True
)

Type Hints

The client includes comprehensive type hints:

from typing import Dict, Optional
from cardscan_client.models import (
    CardApiResponse,
    CreateCardRequest,
    EligibilityApiResponse
)

def process_card(card: CardApiResponse) -> Optional[Dict[str, str]]:
    """Extract key information from a completed card."""
    if card.state == "completed" and card.details:
        return {
            "member_id": card.details.member_id,
            "group_number": card.details.group_number,
            "payer_name": card.details.payer_name
        }
    return None

Logging

Enable detailed logging for debugging:

import logging

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)

# The client will now log all requests and responses
client = CardScanApi(api_key="sk_test_cardscan_ai_...")

Source Code

View the source code and contribute: GitHub

Last updated

Was this helpful?