Overview
Custom integrations are a single HTTP POST per order. There is no SDK to install, no library version to keep up with — just a stable JSON contract and an HMAC signature.
Step 1 — Issue credentials
Create an API key for your store in Settings → API keys. You'll receive:
- An API key (begins with
fcc_live_). - An HMAC secret, shown once. Store it somewhere safe — you can't recover it later, only rotate.
Step 2 — Build the request
Construct the canonical string and HMAC-SHA256 it with your secret:
canonical = "{timestamp}.{nonce}.{body}"
signature = hmac_sha256(hmac_secret, canonical).hexdigest()Python example
import time, uuid, hmac, hashlib, json, requests
API_KEY = "fcc_live_..."
HMAC_SECRET = "..." # the secret you received once
def score_order(order):
body = json.dumps(order, separators=(",", ":"))
timestamp = str(int(time.time()))
nonce = str(uuid.uuid4())
canonical = f"{timestamp}.{nonce}.{body}"
signature = hmac.new(
HMAC_SECRET.encode(),
canonical.encode(),
hashlib.sha256,
).hexdigest()
return requests.post(
"https://api.fraudcommandcenter.com/v1/analyze",
data=body,
headers={
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}",
"X-Fraudshield-Key": API_KEY,
"X-Fraudshield-Timestamp": timestamp,
"X-Fraudshield-Nonce": nonce,
"X-Fraudshield-Signature": signature,
},
timeout=5,
).json()Node example
import { createHmac, randomUUID } from "node:crypto";
async function scoreOrder(order) {
const body = JSON.stringify(order);
const timestamp = Math.floor(Date.now() / 1000).toString();
const nonce = randomUUID();
const canonical = `${timestamp}.${nonce}.${body}`;
const signature = createHmac("sha256", HMAC_SECRET).update(canonical).digest("hex");
const res = await fetch("https://api.fraudcommandcenter.com/v1/analyze", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
"X-Fraudshield-Key": API_KEY,
"X-Fraudshield-Timestamp": timestamp,
"X-Fraudshield-Nonce": nonce,
"X-Fraudshield-Signature": signature,
},
body,
});
return res.json();
}Step 3 — Act on the verdict
The response has risk_score, risk_level, and recommended_action. Wire your storefront to:
- approve — capture as normal.
- review — surface in your ops queue (or leave the dashboard to handle it).
- hold — don't capture; the order sits pending until a human decides.
Idempotency
Send the same order_id twice and you'll get the same score back. The analyzer is deterministic on identical inputs and de-duplicates within an hour via Redis keyed by (store_id, order_id).
Retries
On 5xx, retry with the same body and headers — the nonce will be invalidated, but a fresh nonce and timestamp are fine. On 401 due to bad signature, the nonce is deliberately released so a legitimate retry isn't blocked.
Limits
- Per-store rate limit: 100 requests / minute by default. Email us to raise.
- Request body: 256 KB max.
- Timestamp skew: 300 seconds.