Integration Guides
JavaScript Integration Guide
Complete guide to integrating BotsKYC API with JavaScript and TypeScript applications.
Installation
No SDK required - use native fetch API or your preferred HTTP client.
Recommended Libraries:
- Native
fetch(built-in) axios(popular alternative)@aws-amplify/ui-react-liveness(for liveness detection UI)
Code# Optional: Install axios npm install axios # For liveness detection npm install @aws-amplify/ui-react-liveness aws-amplify
Setup
Environment Variables
Create a .env file:
CodeVITE_BOTSKYC_API_KEY=your_api_key_here VITE_BOTSKYC_API_URL=https://api.botskyc.com
Important: Add .env to .gitignore
API Client Setup
Code// src/api/botskyc.js const API_KEY = import.meta.env.VITE_BOTSKYC_API_KEY; const API_URL = import.meta.env.VITE_BOTSKYC_API_URL; export async function callApi(endpoint, options = {}) { const url = `${API_URL}${endpoint}`; const response = await fetch(url, { ...options, headers: { 'Authorization': `Bearer ${API_KEY}`, ...options.headers } }); if (!response.ok) { const error = await response.json(); throw new Error(error.message); } return response.json(); }
Identity Verification
Scan Identity Document
Code// src/services/identity.js import { callApi } from '../api/botskyc'; export async function scanIdentity(files) { const formData = new FormData(); files.forEach(file => { formData.append('documents', file); }); return callApi('/v1/identity/scan', { method: 'POST', body: formData }); } // Usage in component async function handleUpload(event) { const files = Array.from(event.target.files); try { const result = await scanIdentity(files); console.log('Extracted data:', result.extractedData); } catch (error) { console.error('Scan failed:', error); } }
React Component
Code// src/components/IdentityScanner.jsx import { useState } from 'react'; import { scanIdentity } from '../services/identity'; function IdentityScanner() { const [result, setResult] = useState(null); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const handleFileChange = async (event) => { const files = Array.from(event.target.files); if (files.length === 0) return; setLoading(true); setError(null); try { const data = await scanIdentity(files); setResult(data); } catch (err) { setError(err.message); } finally { setLoading(false); } }; return ( <div> <h2>Identity Document Scanner</h2> <input type="file" multiple accept="image/*,application/pdf" onChange={handleFileChange} disabled={loading} /> {loading && <p>Processing...</p>} {error && <p style={{ color: 'red' }}>{error}</p>} {result && ( <div> <h3>Extracted Data</h3> <p>Name: {result.extractedData.name}</p> <p>ID Number: {result.extractedData.idNumber}</p> <p>Date of Birth: {result.extractedData.dateOfBirth}</p> <p>Confidence: {result.confidence}%</p> </div> )} </div> ); } export default IdentityScanner;
Liveness Detection
Create Session
Code// src/services/liveness.js import { callApi } from '../api/botskyc'; export async function createLivenessSession() { return callApi('/v1/liveness/session', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ settings: { auditImagesLimit: 4 } }) }); } export async function getLivenessResults(sessionId) { return callApi(`/v1/liveness/session/${sessionId}/results`); } export async function compareFaces(sourceImage, targetImage) { return callApi('/v1/liveness/compare-faces', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sourceImage, targetImage }) }); }
React Component with AWS Amplify
Code// src/components/LivenessCheck.jsx import { useState, useEffect } from 'react'; import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness'; import { createLivenessSession, getLivenessResults } from '../services/liveness'; function LivenessCheck({ onComplete }) { const [sessionId, setSessionId] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { async function initSession() { try { const session = await createLivenessSession(); setSessionId(session.sessionId); } catch (error) { console.error('Failed to create session:', error); } } initSession(); }, []); const handleAnalysisComplete = async () => { setLoading(true); try { const results = await getLivenessResults(sessionId); if (results.isLive) { onComplete(results); } else { console.error('Liveness check failed'); } } catch (error) { console.error('Error getting results:', error); } finally { setLoading(false); } }; if (!sessionId) { return <div>Initializing...</div>; } return ( <div> <h2>Face Verification</h2> <FaceLivenessDetector sessionId={sessionId} region="eu-west-1" onAnalysisComplete={handleAnalysisComplete} /> {loading && <div>Verifying...</div>} </div> ); } export default LivenessCheck;
Document Processing
Scan Any Document
Code// src/services/documents.js import { callApi } from '../api/botskyc'; export async function scanDocument(files, type = 'scan') { const formData = new FormData(); files.forEach(file => { formData.append('documents', file); }); const endpoints = { scan: '/v1/documents/scan', address: '/v1/documents/address/scan', income: '/v1/documents/income/scan' }; return callApi(endpoints[type], { method: 'POST', body: formData }); }
TypeScript Support
Type Definitions
Code// src/types/botskyc.ts export interface IdentityData { name: string; idNumber: string; dateOfBirth: string; nationality: string; gender: string; expiryDate: string; photo?: string; } export interface ScanResponse { status: 'success' | 'error'; totalDocuments: number; processingTime?: string; extractedData: IdentityData; confidence: number; documentType: string; verificationType: string; } export interface LivenessSession { sessionId: string; status: string; createdAt: string; expiryDate: string; } export interface LivenessResult { sessionId: string; status: string; confidence: number; isLive: boolean; referenceImage: string; timestamp: string; } export interface FaceMatchResult { similarity: number; isMatch: boolean; confidence: number; threshold: number; }
Typed API Client
Code// src/api/botskyc.ts import type { ScanResponse, LivenessSession, LivenessResult } from '../types/botskyc'; const API_KEY = import.meta.env.VITE_BOTSKYC_API_KEY; const API_URL = import.meta.env.VITE_BOTSKYC_API_URL; async function callApi<T>(endpoint: string, options: RequestInit = {}): Promise<T> { const response = await fetch(`${API_URL}${endpoint}`, { ...options, headers: { 'Authorization': `Bearer ${API_KEY}`, ...options.headers } }); if (!response.ok) { const error = await response.json(); throw new Error(error.message); } return response.json(); } export async function scanIdentity(files: File[]): Promise<ScanResponse> { const formData = new FormData(); files.forEach(file => formData.append('documents', file)); return callApi<ScanResponse>('/v1/identity/scan', { method: 'POST', body: formData }); } export async function createLivenessSession(): Promise<LivenessSession> { return callApi<LivenessSession>('/v1/liveness/session', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ settings: { auditImagesLimit: 4 } }) }); } export async function getLivenessResults(sessionId: string): Promise<LivenessResult> { return callApi<LivenessResult>(`/v1/liveness/session/${sessionId}/results`); }
Complete KYC Workflow
Code// src/workflows/kyc.ts import { scanIdentity, createLivenessSession, getLivenessResults, compareFaces } from '../api/botskyc'; export async function performCompleteKYC(idFiles: File[]): Promise<{ verified: boolean; personalInfo: any; livenessConfidence: number; faceMatchSimilarity: number; }> { // Step 1: Scan ID documents const scanResult = await scanIdentity(idFiles); const idPhoto = scanResult.extractedData.photo; // Step 2: Create liveness session const session = await createLivenessSession(); // Step 3: User completes liveness check (in UI) // Returns session ID after completion // Step 4: Get liveness results const livenessResult = await getLivenessResults(session.sessionId); if (!livenessResult.isLive) { throw new Error('Liveness check failed'); } // Step 5: Compare faces const matchResult = await compareFaces(idPhoto, livenessResult.referenceImage); if (!matchResult.isMatch) { throw new Error('Face does not match ID photo'); } // All checks passed return { verified: true, personalInfo: scanResult.extractedData, livenessConfidence: livenessResult.confidence, faceMatchSimilarity: matchResult.similarity }; }
Error Handling
Code// src/utils/errorHandler.js export class BotsKycError extends Error { constructor(errorData) { super(errorData.message); this.errorCode = errorData.errorCode; this.status = errorData.status; this.details = errorData.details; } } export function handleBotsKycError(error) { if (error.status === 422 && error.errorCode === 1004) { return 'Image quality too low. Please retake in better lighting.'; } if (error.status === 429) { return 'Rate limit exceeded. Please wait and try again.'; } if (error.status === 401) { return 'Authentication failed. Please check your API key.'; } return error.message || 'An error occurred. Please try again.'; }
Testing
Code// src/__tests__/identity.test.js import { describe, it, expect, vi } from 'vitest'; import { scanIdentity } from '../services/identity'; describe('Identity Scanning', () => { it('should scan identity documents', async () => { const mockFile = new File(['content'], 'omang.jpg', { type: 'image/jpeg' }); global.fetch = vi.fn().mockResolvedValue({ ok: true, json: async () => ({ status: 'success', extractedData: { name: 'John Doe', idNumber: '123456789' }, confidence: 95.5 }) }); const result = await scanIdentity([mockFile]); expect(result.status).toBe('success'); expect(result.extractedData.name).toBe('John Doe'); }); });
Best Practices
- Environment Variables - Never hardcode API keys
- Error Handling - Always handle errors gracefully
- Loading States - Show loading indicators during API calls
- Validation - Validate files before uploading
- TypeScript - Use types for better developer experience
- Testing - Write tests for API integrations
- Security - Never expose API keys in client-side code
Support
- Email: [email protected]
- API Reference: Full API Docs
- Examples: GitHub Repository
Related Documentation:
Last modified on

