Code Examples
Ready-to-use code examples for integrating with the CLE Engine API.
Table of Contents
cURL
Basic Request
curl -X POST https://api.cle-engine.com/v1/compute \
-H "Content-Type: application/json" \
-H "X-API-Key: cle_your_api_key_here" \
-d '{
"jurisdiction": "CA",
"last_name": "Smith"
}'
With Environment Variable
# Set your API key
export CLE_API_KEY="cle_your_api_key_here"
# Make requests
curl -X POST https://api.cle-engine.com/v1/compute \
-H "Content-Type: application/json" \
-H "X-API-Key: $CLE_API_KEY" \
-d '{"jurisdiction": "NY", "reporting_period_end": "2026-12-31"}'
Health Check
curl -X GET https://api.cle-engine.com/health
Save Response to File
curl -X POST https://api.cle-engine.com/v1/compute \
-H "Content-Type: application/json" \
-H "X-API-Key: $CLE_API_KEY" \
-d '{"jurisdiction": "TX", "birth_date": "1985-06-15", "admission_date": "2015-11-01"}' \
-o response.json
Python
Basic Usage
import requests
API_KEY = "cle_your_api_key_here"
BASE_URL = "https://api.cle-engine.com"
def compute_cle_deadline(jurisdiction, **kwargs):
"""Calculate CLE deadline for a jurisdiction."""
response = requests.post(
f"{BASE_URL}/v1/compute",
headers={
"Content-Type": "application/json",
"X-API-Key": API_KEY
},
json={
"jurisdiction": jurisdiction,
**kwargs
}
)
response.raise_for_status()
return response.json()
# Example usage
result = compute_cle_deadline("CA", last_name="Smith")
print(f"Due date: {result['due_date']}")
print(f"Compliance group: {result['reporting_group']}")
With Error Handling
import requests
from requests.exceptions import HTTPError, Timeout, RequestException
API_KEY = "cle_your_api_key_here"
BASE_URL = "https://api.cle-engine.com"
def compute_cle_deadline(jurisdiction, **kwargs):
"""Calculate CLE deadline with comprehensive error handling."""
try:
response = requests.post(
f"{BASE_URL}/v1/compute",
headers={
"Content-Type": "application/json",
"X-API-Key": API_KEY
},
json={"jurisdiction": jurisdiction, **kwargs},
timeout=30
)
if response.status_code == 200:
data = response.json()
# Check for missing required fields
if data.get("missing_fields"):
missing = ", ".join(data["missing_fields"])
return {"error": f"Missing required fields: {missing}", "data": data}
return {"success": True, "data": data}
elif response.status_code == 401:
return {"error": "Invalid API key"}
elif response.status_code == 429:
return {"error": "Rate limit exceeded. Please wait and retry."}
else:
return {"error": f"API error: {response.status_code}"}
except Timeout:
return {"error": "Request timed out"}
except RequestException as e:
return {"error": f"Network error: {str(e)}"}
# Example usage
result = compute_cle_deadline("CA", last_name="Garcia")
if result.get("success"):
print(f"Due date: {result['data']['due_date']}")
else:
print(f"Error: {result['error']}")
Using a Class
import requests
import os
from dataclasses import dataclass
from typing import Optional, List
from datetime import date
@dataclass
class CLEDeadline:
due_date: Optional[str]
cycle_start: Optional[str]
cycle_end: Optional[str]
credits_required: Optional[int]
reporting_group: Optional[str]
cle_required: Optional[bool]
required_fields: List[str]
missing_fields: List[str]
notes: Optional[str]
class CLEEngineClient:
"""Client for the CLE Engine API."""
def __init__(self, api_key: Optional[str] = None):
self.api_key = api_key or os.environ.get("CLE_API_KEY")
self.base_url = "https://api.cle-engine.com"
if not self.api_key:
raise ValueError("API key required. Set CLE_API_KEY environment variable.")
def compute(
self,
jurisdiction: str,
profession: str = "lawyer",
last_name: Optional[str] = None,
birth_date: Optional[date] = None,
admission_date: Optional[date] = None,
reporting_category: Optional[str] = None,
reporting_period_end: Optional[date] = None,
renewal_year: Optional[int] = None
) -> CLEDeadline:
"""Calculate CLE deadline for a jurisdiction."""
payload = {"jurisdiction": jurisdiction, "profession": profession}
if last_name:
payload["last_name"] = last_name
if birth_date:
payload["birth_date"] = birth_date.isoformat()
if admission_date:
payload["admission_date"] = admission_date.isoformat()
if reporting_category:
payload["reporting_category"] = reporting_category
if reporting_period_end:
payload["reporting_period_end"] = reporting_period_end.isoformat()
if renewal_year:
payload["renewal_year"] = renewal_year
response = requests.post(
f"{self.base_url}/v1/compute",
headers={
"Content-Type": "application/json",
"X-API-Key": self.api_key
},
json=payload
)
response.raise_for_status()
data = response.json()
return CLEDeadline(
due_date=data.get("due_date"),
cycle_start=data.get("cycle_start"),
cycle_end=data.get("cycle_end"),
credits_required=data.get("credits_required"),
reporting_group=data.get("reporting_group"),
cle_required=data.get("cle_required"),
required_fields=data.get("required_fields", []),
missing_fields=data.get("missing_fields", []),
notes=data.get("notes")
)
def health_check(self) -> bool:
"""Check API health status."""
response = requests.get(f"{self.base_url}/health")
return response.status_code == 200
# Example usage
client = CLEEngineClient()
# Check API health
if client.health_check():
print("API is healthy")
# Calculate deadline
deadline = client.compute(
jurisdiction="CO",
admission_date=date(2020, 6, 15)
)
if deadline.missing_fields:
print(f"Missing: {deadline.missing_fields}")
else:
print(f"Due date: {deadline.due_date}")
print(f"Notes: {deadline.notes}")
JavaScript/Node.js
Using Fetch (Node.js 18+)
const API_KEY = 'cle_your_api_key_here';
const BASE_URL = 'https://api.cle-engine.com';
async function computeCLEDeadline(jurisdiction, options = {}) {
const response = await fetch(`${BASE_URL}/v1/compute`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': API_KEY
},
body: JSON.stringify({
jurisdiction,
...options
})
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.detail || `HTTP ${response.status}`);
}
return response.json();
}
// Example usage
async function main() {
try {
const result = await computeCLEDeadline('CA', { last_name: 'Smith' });
console.log('Due date:', result.due_date);
console.log('Reporting group:', result.reporting_group);
} catch (error) {
console.error('Error:', error.message);
}
}
main();
Using Axios
const axios = require('axios');
const client = axios.create({
baseURL: 'https://api.cle-engine.com',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.CLE_API_KEY
}
});
async function computeCLEDeadline(jurisdiction, options = {}) {
try {
const { data } = await client.post('/v1/compute', {
jurisdiction,
...options
});
if (data.missing_fields && data.missing_fields.length > 0) {
console.warn('Missing fields:', data.missing_fields.join(', '));
}
return data;
} catch (error) {
if (error.response) {
// API returned an error
console.error('API Error:', error.response.data.detail);
} else {
// Network or other error
console.error('Request failed:', error.message);
}
throw error;
}
}
// Example: Batch processing multiple attorneys
async function processAttorneys(attorneys) {
const results = [];
for (const attorney of attorneys) {
const result = await computeCLEDeadline(attorney.jurisdiction, {
last_name: attorney.lastName,
admission_date: attorney.admissionDate
});
results.push({
attorney: attorney.name,
...result
});
// Add small delay to avoid rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
}
return results;
}
TypeScript
import axios, { AxiosInstance } from 'axios';
interface ComputeRequest {
jurisdiction: string;
profession?: string;
last_name?: string;
birth_date?: string;
admission_date?: string;
reporting_category?: string;
reporting_period_end?: string;
renewal_year?: number;
}
interface Citation {
source_id: string;
excerpt_id?: string;
url?: string;
}
interface ComputeResponse {
due_date: string | null;
cycle_start: string | null;
cycle_end: string | null;
credits_required: number | null;
reporting_group: string | null;
cle_required: boolean | null;
required_fields: string[];
missing_fields: string[];
citations: Citation[];
notes: string | null;
}
class CLEEngineClient {
private client: AxiosInstance;
constructor(apiKey: string) {
this.client = axios.create({
baseURL: 'https://api.cle-engine.com',
headers: {
'Content-Type': 'application/json',
'X-API-Key': apiKey
}
});
}
async compute(request: ComputeRequest): Promise<ComputeResponse> {
const { data } = await this.client.post<ComputeResponse>('/v1/compute', request);
return data;
}
async healthCheck(): Promise<boolean> {
try {
const { data } = await this.client.get<{ status: string }>('/health');
return data.status === 'ok';
} catch {
return false;
}
}
}
// Example usage
async function main(): Promise<void> {
const client = new CLEEngineClient(process.env.CLE_API_KEY!);
// Health check
const isHealthy = await client.healthCheck();
console.log('API healthy:', isHealthy);
// Compute deadline
const result = await client.compute({
jurisdiction: 'NJ',
birth_date: '1985-03-15'
});
if (result.missing_fields.length > 0) {
console.log('Missing fields:', result.missing_fields);
} else {
console.log('Due date:', result.due_date);
console.log('Group:', result.reporting_group);
}
}
main().catch(console.error);
Ruby
require 'net/http'
require 'json'
require 'uri'
class CLEEngineClient
BASE_URL = 'https://api.cle-engine.com'
def initialize(api_key)
@api_key = api_key
end
def compute(jurisdiction:, **options)
uri = URI("#{BASE_URL}/v1/compute")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-API-Key'] = @api_key
request.body = { jurisdiction: jurisdiction, **options }.to_json
response = http.request(request)
case response.code.to_i
when 200
JSON.parse(response.body)
when 401
raise 'Invalid API key'
when 429
raise 'Rate limit exceeded'
else
raise "API error: #{response.code}"
end
end
def health_check
uri = URI("#{BASE_URL}/health")
response = Net::HTTP.get_response(uri)
response.code == '200'
end
end
# Example usage
client = CLEEngineClient.new(ENV['CLE_API_KEY'])
result = client.compute(
jurisdiction: 'CA',
last_name: 'Smith'
)
puts "Due date: #{result['due_date']}"
puts "Group: #{result['reporting_group']}"
PHP
<?php
class CLEEngineClient {
private string $apiKey;
private string $baseUrl = 'https://api.cle-engine.com';
public function __construct(string $apiKey) {
$this->apiKey = $apiKey;
}
public function compute(string $jurisdiction, array $options = []): array {
$payload = array_merge(['jurisdiction' => $jurisdiction], $options);
$ch = curl_init($this->baseUrl . '/v1/compute');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: ' . $this->apiKey
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 401) {
throw new Exception('Invalid API key');
} elseif ($httpCode === 429) {
throw new Exception('Rate limit exceeded');
} elseif ($httpCode !== 200) {
throw new Exception("API error: $httpCode");
}
return json_decode($response, true);
}
public function healthCheck(): bool {
$ch = curl_init($this->baseUrl . '/health');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode === 200;
}
}
// Example usage
$client = new CLEEngineClient($_ENV['CLE_API_KEY']);
$result = $client->compute('CA', ['last_name' => 'Smith']);
echo "Due date: " . $result['due_date'] . "\n";
echo "Group: " . $result['reporting_group'] . "\n";
Go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
)
const baseURL = "https://api.cle-engine.com"
type ComputeRequest struct {
Jurisdiction string `json:"jurisdiction"`
Profession string `json:"profession,omitempty"`
LastName string `json:"last_name,omitempty"`
BirthDate string `json:"birth_date,omitempty"`
AdmissionDate string `json:"admission_date,omitempty"`
ReportingCategory string `json:"reporting_category,omitempty"`
ReportingPeriodEnd string `json:"reporting_period_end,omitempty"`
RenewalYear int `json:"renewal_year,omitempty"`
}
type Citation struct {
SourceID string `json:"source_id"`
ExcerptID string `json:"excerpt_id,omitempty"`
URL string `json:"url,omitempty"`
}
type ComputeResponse struct {
DueDate *string `json:"due_date"`
CycleStart *string `json:"cycle_start"`
CycleEnd *string `json:"cycle_end"`
CreditsRequired *int `json:"credits_required"`
ReportingGroup *string `json:"reporting_group"`
CLERequired *bool `json:"cle_required"`
RequiredFields []string `json:"required_fields"`
MissingFields []string `json:"missing_fields"`
Citations []Citation `json:"citations"`
Notes *string `json:"notes"`
}
type CLEClient struct {
apiKey string
httpClient *http.Client
}
func NewCLEClient(apiKey string) *CLEClient {
return &CLEClient{
apiKey: apiKey,
httpClient: &http.Client{},
}
}
func (c *CLEClient) Compute(req ComputeRequest) (*ComputeResponse, error) {
body, err := json.Marshal(req)
if err != nil {
return nil, err
}
httpReq, err := http.NewRequest("POST", baseURL+"/v1/compute", bytes.NewBuffer(body))
if err != nil {
return nil, err
}
httpReq.Header.Set("Content-Type", "application/json")
httpReq.Header.Set("X-API-Key", c.apiKey)
resp, err := c.httpClient.Do(httpReq)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode == 401 {
return nil, fmt.Errorf("invalid API key")
} else if resp.StatusCode == 429 {
return nil, fmt.Errorf("rate limit exceeded")
} else if resp.StatusCode != 200 {
return nil, fmt.Errorf("API error: %d", resp.StatusCode)
}
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var result ComputeResponse
if err := json.Unmarshal(respBody, &result); err != nil {
return nil, err
}
return &result, nil
}
func main() {
client := NewCLEClient(os.Getenv("CLE_API_KEY"))
result, err := client.Compute(ComputeRequest{
Jurisdiction: "CA",
LastName: "Smith",
})
if err != nil {
fmt.Printf("Error: %v\n", err)
return
}
if len(result.MissingFields) > 0 {
fmt.Printf("Missing fields: %v\n", result.MissingFields)
} else {
fmt.Printf("Due date: %s\n", *result.DueDate)
if result.ReportingGroup != nil {
fmt.Printf("Group: %s\n", *result.ReportingGroup)
}
}
}
Common Patterns
Environment Variables
Always use environment variables for API keys:
# .env file
CLE_API_KEY=cle_your_api_key_here
Retry Logic
Implement retries for transient failures:
import time
from functools import wraps
def retry(max_attempts=3, backoff_factor=2):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
wait = backoff_factor ** attempt
time.sleep(wait)
return wrapper
return decorator
@retry(max_attempts=3)
def make_api_call():
# Your API call here
pass
Caching
Cache results to reduce API calls:
from functools import lru_cache
from datetime import date
@lru_cache(maxsize=1000)
def get_deadline(jurisdiction: str, **kwargs) -> dict:
# Cache key is automatically generated from arguments
return api.compute(jurisdiction, **kwargs)