Skip to main content

Best Practices

This guide outlines best practices for using the Nanonets API effectively and securely.

Security

API Key Management

  1. Store API Keys Securely
import os
from dotenv import load_dotenv

# Load API key from environment variable
load_dotenv()
API_KEY = os.getenv('NANONETS_API_KEY')
  1. Rotate API Keys Regularly
def rotate_api_key(old_key):
# Implement your key rotation logic
new_key = generate_new_key()
update_environment(old_key, new_key)
return new_key
  1. Use Different Keys for Different Environments
API_KEY = os.getenv('NANONETS_API_KEY_PROD') if is_production else os.getenv('NANONETS_API_KEY_DEV')

Request Security

  1. Use HTTPS Always
url = "https://app.nanonets.com/api/v4/workflows"  # Always use HTTPS
  1. Validate Input Data
def validate_document(file_path):
# Check file size
if os.path.getsize(file_path) > 10 * 1024 * 1024: # 10MB limit
raise ValueError("File too large")

# Check file type
allowed_types = ['.pdf', '.jpg', '.png']
if not any(file_path.lower().endswith(ext) for ext in allowed_types):
raise ValueError(f"Invalid file type. Allowed types: {allowed_types}")

Performance

Optimizing Requests

  1. Use Connection Pooling
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

session = requests.Session()
retries = Retry(total=5, backoff_factor=0.1)
session.mount('https://', HTTPAdapter(max_retries=retries, pool_connections=100, pool_maxsize=100))
  1. Implement Caching
from functools import lru_cache
import time

@lru_cache(maxsize=100)
def get_workflow_details(workflow_id, api_key):
url = f"https://app.nanonets.com/api/v4/workflows/{workflow_id}"
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
return response.json()
  1. Batch Processing
def process_documents_batch(file_paths, api_key, workflow_id):
results = []
for file_path in file_paths:
try:
result = process_document(file_path, api_key, workflow_id)
results.append(result)
except Exception as e:
results.append({'error': str(e), 'file': file_path})
return results

Error Handling

  1. Implement Retry Logic
from tenacity import retry, stop_after_attempt, wait_exponential

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def make_api_request(url, api_key):
response = requests.get(url, auth=HTTPBasicAuth(api_key, ''))
response.raise_for_status()
return response.json()
  1. Handle Rate Limits
def handle_rate_limit(response):
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
return True
return False

Code Organization

Modular Structure

  1. Separate Concerns
# config.py
API_CONFIG = {
'base_url': 'https://app.nanonets.com/api/v4',
'timeout': 30,
'max_retries': 3
}

# api_client.py
class NanonetsClient:
def __init__(self, api_key):
self.api_key = api_key
self.session = self._create_session()

def _create_session(self):
session = requests.Session()
session.auth = HTTPBasicAuth(self.api_key, '')
return session

def get_workflows(self):
url = f"{API_CONFIG['base_url']}/workflows"
return self.session.get(url).json()
  1. Use Context Managers
class APIConnection:
def __init__(self, api_key):
self.api_key = api_key
self.session = None

def __enter__(self):
self.session = requests.Session()
self.session.auth = HTTPBasicAuth(self.api_key, '')
return self

def __exit__(self, exc_type, exc_val, exc_tb):
if self.session:
self.session.close()

Monitoring and Logging

  1. Implement Structured Logging
import logging
import json
from datetime import datetime

class APILogger:
def __init__(self):
self.logger = logging.getLogger('nanonets_api')
self.logger.setLevel(logging.INFO)

def log_request(self, method, url, status_code, duration):
log_entry = {
'timestamp': datetime.utcnow().isoformat(),
'method': method,
'url': url,
'status_code': status_code,
'duration_ms': duration
}
self.logger.info(json.dumps(log_entry))
  1. Track Performance Metrics
from time import time

def track_performance(func):
def wrapper(*args, **kwargs):
start_time = time()
result = func(*args, **kwargs)
duration = (time() - start_time) * 1000 # Convert to milliseconds
log_performance_metric(func.__name__, duration)
return result
return wrapper

Testing

  1. Unit Tests
import unittest
from unittest.mock import patch

class TestNanonetsAPI(unittest.TestCase):
@patch('requests.Session')
def test_get_workflows(self, mock_session):
mock_response = mock_session.return_value.get.return_value
mock_response.json.return_value = {'workflows': []}

client = NanonetsClient('test_key')
result = client.get_workflows()

self.assertEqual(result, {'workflows': []})
  1. Integration Tests
class TestNanonetsIntegration(unittest.TestCase):
def setUp(self):
self.client = NanonetsClient(os.getenv('TEST_API_KEY'))

def test_document_processing(self):
result = self.client.process_document('test.pdf')
self.assertIn('status', result)
self.assertEqual(result['status'], 'completed')

Need Help?