SDKs
Official Node.js and Python clients with retry, idempotency, and webhook helpers built in.
CiteFlow ships two official SDKs that wrap the REST API with retry
policies, automatic Idempotency-Key generation, polling helpers, and
HMAC webhook verification. Use them and you can stop reading half the
rest of these docs.
| Runtime | Package | Versions |
|---|---|---|
| Node.js 18+ | @citeflow/sdk | v0.1.0 |
| Python 3.9+ | citeflow-python | v0.1.0 |
Both SDKs follow Semantic Versioning and track
the v1 API. Breaking changes mint v1 → v2 and the SDK majors
move with it.
Install
Node
npm install @citeflow/sdk
# pnpm add @citeflow/sdk
# yarn add @citeflow/sdkPython
pip install citeflow-pythonHello world
Node
import { Citeflow } from '@citeflow/sdk';
const client = new Citeflow({ apiKey: process.env.CITEFLOW_API_KEY! });
const audit = await client.audits.create({
url: 'https://example.com',
type: 'seo',
});
const result = await client.audits.waitForCompletion(audit.audit_id, {
timeoutMs: 90_000,
});
console.log(result.status, result.status === 'complete' && result.scores);Python
import os
from citeflow import Citeflow
client = Citeflow(api_key=os.environ["CITEFLOW_API_KEY"])
audit = client.audits.create(url="https://example.com", type="seo")
result = client.audits.wait_for_completion(audit["audit_id"], timeout=90)
print(result["status"], result.get("scores"))What the SDK does for you
| Concern | Without SDK | With SDK |
|---|---|---|
| Auth header | manual Authorization: Bearer … | new Citeflow({ apiKey }) |
| Idempotency | mint UUID per POST, store, retry-safe | automatic per call |
| Retry on 429/5xx | exp backoff + jitter + Retry-After honoring | built in (maxRetries: 3) |
| Polling for audits | custom loop with timeout + interval | waitForCompletion / wait_for_completion |
| Webhook signing | parse 3 headers, HMAC-SHA256, base64, timing-safe compare, rotation grace, ±5min skew | verifyWebhookSignature / verify_webhook_signature |
| Error envelope | parse JSON, branch on error.code | catch CiteflowError with typed .code, .requestId |
Webhook verification
The SDKs handle the part most partners get wrong on a first integration.
Node
import { parseWebhookEvent, CiteflowSignatureError } from '@citeflow/sdk';
// In an Express / Next.js Route Handler:
const rawBody = await readRawBody(req); // do NOT JSON-parse first
try {
const event = parseWebhookEvent({
rawBody,
headers: req.headers,
secret: process.env.CITEFLOW_WEBHOOK_SECRET!,
});
// event.type ∈ { 'audit.completed', 'audit.failed', 'audit.cancelled', 'balance.low' }
await processEvent(event);
res.status(200).end();
} catch (err) {
if (err instanceof CiteflowSignatureError) return res.status(400).end();
throw err;
}Python
from flask import request
from citeflow import parse_webhook_event, CiteflowSignatureError
@app.post("/citeflow-webhook")
def webhook():
try:
event = parse_webhook_event(
raw_body=request.get_data(), # bytes
headers=request.headers,
secret=os.environ["CITEFLOW_WEBHOOK_SECRET"],
)
process_event(event)
return "", 200
except CiteflowSignatureError:
return "", 400The verifier handles the rotation grace window automatically — when you rotate the signing secret in the dashboard, both old and new signatures verify against your old secret for 7 days, then both verify against the new one.
Error handling
Both SDKs raise typed errors on non-2xx responses. Branch on code
(stable) rather than HTTP status (relaxable).
import { CiteflowError } from '@citeflow/sdk';
try {
await client.audits.create({ url: '…', type: 'all' });
} catch (err) {
if (err instanceof CiteflowError) {
if (err.code === 'INSUFFICIENT_CREDITS') {
// err.required tells you how many credits short you are.
console.warn(`Need ${err.required} more credits`);
}
console.error(err.requestId); // include in support tickets
}
}from citeflow import CiteflowError
try:
client.audits.create(url="…", type="all")
except CiteflowError as err:
if err.code == "INSUFFICIENT_CREDITS":
print(f"Need {err.required} more credits")
print(err.request_id)Configuration knobs
new Citeflow({
apiKey: 'ckf_…',
baseUrl: 'https://www.citeflow.io/api/v1', // staging override
timeoutMs: 30_000,
maxRetries: 3,
});Citeflow(
api_key="ckf_…",
base_url="https://www.citeflow.io/api/v1",
timeout=30.0,
max_retries=3,
session=my_requests_session, # custom adapter / proxy
)Source
- Node SDK:
packages/sdk-node/in the CiteFlow monorepo. - Python SDK:
packages/sdk-python/. - Issues / requests:
partners@citeflow.io.