Integration Guides
Python Integration Guide
Complete guide to integrating BotsKYC API with Python applications.
Installation
No SDK required - use standard requests library.
Codepip install requests python-dotenv
Setup
Environment Variables
Create a .env file:
CodeBOTSKYC_API_KEY=your_api_key_here BOTSKYC_API_URL=https://api.botskyc.com
Important: Add .env to .gitignore
API Client Setup
Code# botskyc/client.py import os import requests from typing import Dict, Any, List, Optional from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv('BOTSKYC_API_KEY') API_URL = os.getenv('BOTSKYC_API_URL', 'https://api.botskyc.com') class BotsKYCClient: def __init__(self, api_key: Optional[str] = None): self.api_key = api_key or API_KEY self.base_url = API_URL if not self.api_key: raise ValueError('API key is required') def _get_headers(self) -> Dict[str, str]: return { 'Authorization': f'Bearer {self.api_key}' } def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]: url = f'{self.base_url}{endpoint}' headers = self._get_headers() if 'headers' in kwargs: headers.update(kwargs['headers']) response = requests.request( method=method, url=url, headers=headers, **kwargs ) response.raise_for_status() return response.json()
Identity Verification
Scan Identity Document
Code# botskyc/identity.py from typing import List, Dict, Any from pathlib import Path class IdentityService: def __init__(self, client): self.client = client def scan(self, file_paths: List[str]) -> Dict[str, Any]: """Scan identity documents""" files = [] for path in file_paths: file_obj = open(path, 'rb') files.append(('documents', file_obj)) try: result = self.client._request( 'POST', '/v1/identity/scan', files=files ) return result finally: # Close all file objects for _, file_obj in files: file_obj.close() def scan_bytes(self, file_data: List[tuple]) -> Dict[str, Any]: """ Scan identity documents from bytes file_data: List of (filename, bytes) tuples """ files = [('documents', (name, data)) for name, data in file_data] return self.client._request( 'POST', '/v1/identity/scan', files=files ) # Usage from botskyc.client import BotsKYCClient from botskyc.identity import IdentityService client = BotsKYCClient() identity = IdentityService(client) # Scan from file paths result = identity.scan(['omang-front.jpg', 'omang-back.jpg']) print(f"Name: {result['extractedData']['name']}") print(f"ID Number: {result['extractedData']['idNumber']}")
Flask Application Example
Code# app.py from flask import Flask, request, jsonify from botskyc.client import BotsKYCClient from botskyc.identity import IdentityService app = Flask(__name__) client = BotsKYCClient() identity_service = IdentityService(client) @app.route('/api/verify-identity', methods=['POST']) def verify_identity(): if 'documents' not in request.files: return jsonify({'error': 'No documents provided'}), 400 files = request.files.getlist('documents') # Prepare file data file_data = [(f.filename, f.read()) for f in files] try: result = identity_service.scan_bytes(file_data) return jsonify(result) except requests.HTTPError as e: return jsonify({'error': str(e)}), e.response.status_code except Exception as e: return jsonify({'error': str(e)}), 500 if __name__ == '__main__': app.run(debug=True)
Liveness Detection
Liveness Service
Code# botskyc/liveness.py from typing import Dict, Any class LivenessService: def __init__(self, client): self.client = client def create_session(self, audit_images_limit: int = 4) -> Dict[str, Any]: """Create a new liveness session""" return self.client._request( 'POST', '/v1/liveness/session', json={'settings': {'auditImagesLimit': audit_images_limit}}, headers={'Content-Type': 'application/json'} ) def get_results(self, session_id: str) -> Dict[str, Any]: """Get liveness session results""" return self.client._request( 'GET', f'/v1/liveness/session/{session_id}/results' ) def verify(self, session_id: str) -> Dict[str, Any]: """Verify liveness with validation""" return self.client._request( 'POST', f'/v1/liveness/verify/{session_id}' ) def compare_faces(self, source_image: str, target_image: str) -> Dict[str, Any]: """Compare two face images""" return self.client._request( 'POST', '/v1/liveness/compare-faces', json={ 'sourceImage': source_image, 'targetImage': target_image }, headers={'Content-Type': 'application/json'} ) # Usage from botskyc.liveness import LivenessService liveness = LivenessService(client) # Create session session = liveness.create_session() print(f"Session ID: {session['sessionId']}") # Get results (after frontend completes liveness check) results = liveness.get_results(session['sessionId']) print(f"Is Live: {results['isLive']}") print(f"Confidence: {results['confidence']}")
Document Processing
Document Service
Code# botskyc/documents.py from typing import List, Dict, Any class DocumentService: def __init__(self, client): self.client = client def scan(self, file_paths: List[str], doc_type: str = 'scan') -> Dict[str, Any]: """ Scan documents doc_type: 'scan' | 'address' | 'income' """ endpoints = { 'scan': '/v1/documents/scan', 'address': '/v1/documents/address/scan', 'income': '/v1/documents/income/scan' } files = [(open(path, 'rb')) for path in file_paths] try: result = self.client._request( 'POST', endpoints[doc_type], files=[('documents', f) for f in files] ) return result finally: for f in files: f.close() # Usage from botskyc.documents import DocumentService documents = DocumentService(client) # Scan address proof result = documents.scan(['utility-bill.pdf'], doc_type='address') print(f"Address: {result['extractedData']['address']}") # Scan income proof result = documents.scan(['payslip.pdf'], doc_type='income') print(f"Salary: {result['extractedData']['netSalary']}")
Complete KYC Workflow
Code# workflows/kyc.py from typing import List, Dict, Any from botskyc.client import BotsKYCClient from botskyc.identity import IdentityService from botskyc.liveness import LivenessService class KYCWorkflow: def __init__(self): self.client = BotsKYCClient() self.identity = IdentityService(self.client) self.liveness = LivenessService(self.client) def perform_complete_kyc( self, id_files: List[str], session_id: str ) -> Dict[str, Any]: """ Perform complete KYC verification Args: id_files: Paths to ID document images session_id: Liveness session ID (after user completes check) Returns: Complete verification result """ # Step 1: Scan ID documents scan_result = self.identity.scan(id_files) id_photo = scan_result['extractedData'].get('photo') # Step 2: Get liveness results liveness_result = self.liveness.get_results(session_id) if not liveness_result['isLive']: raise ValueError('Liveness check failed') # Step 3: Compare faces if id_photo and liveness_result.get('referenceImage'): face_match = self.liveness.compare_faces( id_photo, liveness_result['referenceImage'] ) if not face_match['isMatch']: raise ValueError('Face does not match ID photo') else: face_match = None # Return complete result return { 'verified': True, 'personalInfo': scan_result['extractedData'], 'livenessConfidence': liveness_result['confidence'], 'faceMatch': face_match } # Usage workflow = KYCWorkflow() try: result = workflow.perform_complete_kyc( id_files=['omang-front.jpg', 'omang-back.jpg'], session_id='abc123-def456-ghi789' ) print('KYC Verification Complete:') print(f"Name: {result['personalInfo']['name']}") print(f"Liveness Confidence: {result['livenessConfidence']}%") print(f"Face Match: {result['faceMatch']['similarity']}%") except ValueError as e: print(f'Verification failed: {e}') except Exception as e: print(f'Error: {e}')
Error Handling
Code# botskyc/exceptions.py import requests from typing import Dict, Any class BotsKYCError(Exception): def __init__(self, error_data: Dict[str, Any]): self.error_code = error_data.get('errorCode') self.message = error_data.get('message') self.status = error_data.get('status') self.details = error_data.get('details', {}) self.timestamp = error_data.get('timestamp') super().__init__(self.message) def handle_request_error(error: requests.HTTPError) -> BotsKYCError: """Convert HTTP error to BotsKYCError""" try: error_data = error.response.json() return BotsKYCError(error_data) except ValueError: # Response not JSON return BotsKYCError({ 'errorCode': error.response.status_code, 'message': error.response.text, 'status': error.response.status_code }) # Usage in client def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]: try: response = requests.request(...) response.raise_for_status() return response.json() except requests.HTTPError as e: raise handle_request_error(e)
Retry Logic
Code# botskyc/retry.py import time from typing import Callable, Any from requests import HTTPError def retry_with_backoff( func: Callable, max_retries: int = 3, base_delay: float = 1.0 ) -> Any: """Retry function with exponential backoff""" retries = 0 delay = base_delay while retries < max_retries: try: return func() except HTTPError as e: if e.response.status_code < 500: # Client error - don't retry raise retries += 1 if retries >= max_retries: raise print(f'Retry {retries}/{max_retries} after {delay}s') time.sleep(delay) delay *= 2 # Usage def scan_with_retry(file_paths): return retry_with_backoff( lambda: identity.scan(file_paths), max_retries=3 )
Django Integration
Code# myapp/views.py from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from botskyc.client import BotsKYCClient from botskyc.identity import IdentityService client = BotsKYCClient() identity = IdentityService(client) @csrf_exempt def verify_identity(request): if request.method != 'POST': return JsonResponse({'error': 'Method not allowed'}, status=405) files = request.FILES.getlist('documents') if not files: return JsonResponse({'error': 'No documents provided'}, status=400) # Prepare file data file_data = [(f.name, f.read()) for f in files] try: result = identity.scan_bytes(file_data) return JsonResponse(result) except Exception as e: return JsonResponse({'error': str(e)}, status=500)
Async Support
Code# botskyc/async_client.py import aiohttp import asyncio from typing import Dict, Any, List class AsyncBotsKYCClient: def __init__(self, api_key: str): self.api_key = api_key self.base_url = 'https://api.botskyc.com' async def _request(self, method: str, endpoint: str, **kwargs) -> Dict[str, Any]: url = f'{self.base_url}{endpoint}' headers = {'Authorization': f'Bearer {self.api_key}'} if 'headers' in kwargs: headers.update(kwargs['headers']) async with aiohttp.ClientSession() as session: async with session.request( method=method, url=url, headers=headers, **kwargs ) as response: response.raise_for_status() return await response.json() async def scan_identity(self, file_paths: List[str]) -> Dict[str, Any]: data = aiohttp.FormData() for path in file_paths: data.add_field('documents', open(path, 'rb'), filename=path) return await self._request('POST', '/v1/identity/scan', data=data) # Usage async def main(): client = AsyncBotsKYCClient(API_KEY) result = await client.scan_identity(['omang-front.jpg', 'omang-back.jpg']) print(result) asyncio.run(main())
Testing
Code# tests/test_identity.py import unittest from unittest.mock import Mock, patch from botskyc.client import BotsKYCClient from botskyc.identity import IdentityService class TestIdentityService(unittest.TestCase): def setUp(self): self.client = BotsKYCClient(api_key='test_key') self.identity = IdentityService(self.client) @patch('requests.request') def test_scan_identity(self, mock_request): # Mock response mock_response = Mock() mock_response.json.return_value = { 'status': 'success', 'extractedData': { 'name': 'John Doe', 'idNumber': '123456789' } } mock_request.return_value = mock_response # Test result = self.identity.scan(['test.jpg']) self.assertEqual(result['status'], 'success') self.assertEqual(result['extractedData']['name'], 'John Doe') if __name__ == '__main__': unittest.main()
Best Practices
- Environment Variables - Use
.envfor API keys - Error Handling - Always catch and handle exceptions
- File Handling - Close files properly (use context managers)
- Type Hints - Use type hints for better code clarity
- Retry Logic - Implement retries for transient errors
- Async - Use async client for high-throughput applications
- Testing - Mock API calls in tests
Support
- Email: [email protected]
- API Reference: Full API Docs
- Examples: GitHub Repository
Related Documentation:
Last modified on