Qubiclo is a REST API — any HTTP client works. Below are recommended integration patterns, code templates, and a pre-flight checklist to get your integration production-ready.
import requests
import time
class QubicloClient:
BASE = "http://localhost:8000/api/v1"
def __init__(self, email: str, password: str):
self._creds = {"email": email, "password": password}
self._token: str | None = None
self._token_exp: float = 0
def _get_token(self) -> str:
if self._token and time.time() < self._token_exp - 30:
return self._token
r = requests.post(f"{self.BASE}/auth/login", json=self._creds, timeout=10)
r.raise_for_status()
data = r.json()
self._token = data["access_token"]
self._token_exp = time.time() + data["expires_in"]
return self._token
def _headers(self):
return {"Authorization": f"Bearer {self._get_token()}"}
def submit_claim(self, payload: dict) -> dict:
r = requests.post(f"{self.BASE}/claims/intake", json=payload, headers=self._headers(), timeout=30)
r.raise_for_status()
return r.json()
def get_claim(self, claim_id: str) -> dict:
r = requests.get(f"{self.BASE}/claims/{claim_id}", headers=self._headers(), timeout=10)
r.raise_for_status()
return r.json()
def list_providers(self) -> list:
r = requests.get(f"{self.BASE}/providers", headers=self._headers(), timeout=10)
r.raise_for_status()
return r.json()
# Usage
client = QubicloClient("admin@yourhmo.com", "your_password")
result = client.submit_claim({
"claim_id": "CLM-2026-9001",
"member_id": "MBR-88273",
"provider_id": "PRV-102",
"diagnosis_codes": ["J18.9"],
"procedure_codes": ["71045"],
"claim_amount": 125000,
"currency": "NGN",
"service_date": "2026-05-20",
})
print(result["adjudication_outcome"]) # "APPROVED" | "FLAGGED" | "BLOCKED"// qubiclo-client.ts
const BASE = "http://localhost:8000/api/v1";
interface TokenCache { token: string; expiresAt: number }
let cache: TokenCache | null = null;
async function getToken(email: string, password: string): Promise<string> {
if (cache && Date.now() < cache.expiresAt - 30_000) return cache.token;
const resp = await fetch(`${BASE}/auth/login`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, password }),
});
if (!resp.ok) throw new Error(`Login failed: ${resp.status}`);
const data = await resp.json();
cache = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
return cache.token;
}
async function apiCall<T>(method: string, path: string, body?: unknown): Promise<T> {
const token = await getToken(
process.env.AJUDEE_EMAIL!,
process.env.AJUDEE_PASSWORD!,
);
const resp = await fetch(`${BASE}${path}`, {
method,
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
});
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(err?.error?.message ?? `HTTP ${resp.status}`);
}
return resp.json();
}
export const submitClaim = (payload: object) => apiCall("POST", "/claims/intake", payload);
export const getClaim = (id: string) => apiCall("GET", `/claims/${id}`);
export const listProviders = () => apiCall("GET", "/providers");# Python FastAPI webhook receiver
import hmac, hashlib
from fastapi import FastAPI, Request, HTTPException
app = FastAPI()
WEBHOOK_SECRET = "your_webhook_secret"
@app.post("/webhooks/qubiclo")
async def handle_webhook(request: Request):
body = await request.body()
sig = request.headers.get("X-Qubiclo-Signature", "")
expected = "sha256=" + hmac.new(WEBHOOK_SECRET.encode(), body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, expected):
raise HTTPException(status_code=401, detail="Invalid signature")
event = await request.json()
match event["event"]:
case "claim.completed":
await on_claim_completed(event["data"])
case "claim.flagged":
await on_claim_flagged(event["data"])
case "upload.completed":
await on_upload_ready(event["data"])
return {"received": True}
async def on_claim_completed(data: dict):
print(f"Claim {data['claim_id']}: {data['outcome']} — {data['approved_amount']:,}")Token auto-refresh
Detect 401 responses and refresh the access token automatically before retrying.
Idempotency keys on POST
Send a unique Idempotency-Key header on claim submissions to prevent duplicates on retry.
Webhook signature verification
Validate X-Qubiclo-Signature on every incoming webhook before processing.
Idempotent webhook handler
Handle duplicate deliveries gracefully — check if the event was already processed.
Exponential backoff on 429
Respect the Retry-After header and back off when rate limited.
Structured error logging
Log request_id from error responses to correlate client errors with server-side traces.
TLS in production
Point AJUDEE_BASE_URL to the HTTPS endpoint — never send credentials over plain HTTP.
Scoped API credentials
Create a dedicated user with only the scopes your integration needs (principle of least privilege).
Never hardcode credentials. Use environment variables:
# .env
AJUDEE_BASE_URL=http://localhost:8000/api/v1
AJUDEE_TENANT=your-hmo
AJUDEE_EMAIL=admin@yourhmo.com
AJUDEE_PASSWORD=your_password
AJUDEE_WEBHOOK_SECRET=your_webhook_secret