Getting Started
Quickstart
From zero to a signed, audited verdict in three calls. Everything below runs against the production engine at https://api.fidacy.com.
1 · Create an API key
Sign in to the console, create an organization (one click), and mint a key scoped to assess:write and assess:read. The raw key is shown once, store it as a secret.
# the console at app.fidacy.com → API Keys → Create (mode: test) fky_test_35nB… (shown once, keep it secret)
test mode, keys are fky_test_… (sandbox, never billed). Switch to fky_live_… for production. Either key authenticates every call, never embed a secret key in client-side code or a public repo.2 · Assess a mandate
Send the AP2 mandate. Authenticate with a Bearer token (or the x-api-key header). The engine validates, scores, signs, and audits, then returns the verdict.
curl https://api.fidacy.com/v1/assess \
-H "Authorization: Bearer $FIDACY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"mandate": {
"vct": "mandate.payment.1",
"transaction_id": "5f3c…",
"payee": { "id": "merchant_42", "name": "Acme Corp" },
"payment_amount": { "amount": 4299, "currency": "EUR" },
"payment_instrument": { "id": "pi_1", "type": "card" }
}
}'The response carries the decision and the full rich outcome:
{
"decision": "approve",
"score": 12,
"assessmentId": "asmt_0Kc…",
"mandateId": "mnd_9aZ…",
"riskPayloadJws": "eyJhbGciOiJFZERTQSJ9.eyJ…",
"mandate": { …, "risk_data": { "fidacy": { … } } }, // ready to forward
"outcome": { "object": "assessment", "outcome": { "risk_level": "normal" }, … }
}3 · Forward the signed mandate
The response's mandate already has the signed Risk Payload injected into risk_data. Forward it to the payment rail. The receiving party verifies the JWS against your public JWKS, no call back to Fidacy needed.
The verify URL travels inside the payload (risk_payload.verify_url), so any party can fetch the public key by kid and check the signature offline.
Or: the SDK, two packages, ten lines
Prefer code over curl? Install the SDK and the verifier. Both are Apache-2.0, dependency-light, and default to https://api.fidacy.com, zero config.
npm i @fidacy/sdk @fidacy/verify
import { Fidacy } from "@fidacy/sdk";
const fidacy = new Fidacy({ apiKey: process.env.FIDACY_API_KEY }); // fky_test_… to start
// before any agent action that spends money or commits authority:
const verdict = await fidacy.assess({
mandate: {
vct: "mandate.payment.1",
transaction_id: "5f3c…",
payee: { id: "merchant_42", name: "Acme Corp" },
payment_amount: { amount: 4299, currency: "EUR" },
payment_instrument: { id: "pi_1", type: "card" },
},
});
if (verdict.decision === "approve") { /* proceed */ }
else if (verdict.decision === "review") { /* step up to human / stronger auth */ }
else { /* deny, do not clear */ }Verify the signature yourself
Every verdict is an EdDSA-signed JWS. Anyone, a payment rail, a public agency, an auditor, can verify it against the public JWKS without trusting you and without calling Fidacy back. The default JWKS URL is already api.fidacy.com, so it is one line:
import { verifyRiskPayload } from "@fidacy/verify";
const { valid, claims } = await verifyRiskPayload(verdict.riskPayloadJws);
// valid === true → Fidacy signed this verdict, and nobody tampered with it.Read it back
Assessments are first-class objects. The same rich outcome is reconstructed deterministically from the stored record, useful for dashboards, disputes, and replay.
curl https://api.fidacy.com/v1/assessments/asmt_0Kc… \ -H "Authorization: Bearer $FIDACY_API_KEY"
Reading the decision
- ·approve, low risk, proceed.
- ·review, ambiguous; step up to human or stronger auth before clearing.
- ·deny, a hard violation or unacceptable risk; do not clear.
reviewas "not yet", never as a soft approve. It is also the safe fallback the engine returns on any internal fault, so a reviewalways means "don't clear without more".