Concepts
UCP Protocol
Fidacy is a UCP-native trust layer. Send any assessment from a Universal Commerce Protocol flow, with a ucp block or the UCP-Agent header, and the engine returns the verdict the UCP way: as an independently-verifiable trust signal under com.fidacy.trust_verdict, embedding the signed verifiable credential anyone can check against our public JWKS.
/v1/assess call behaves exactly as before, and the verdict core is protocol-blind (the same decision powers AP2, A2A, and UCP).Engagement & version
UCP semantics engage when the request carries the UCP-Agent header (which advertises the platform profile) or a ucp block in the body. Unlike A2A, UCP has no version header, the version lives in the body. This engine speaks 2026-04-08. A version asserted in ucp.ucp_version is validated; an unsupported one is rejected before any work is done.
POST /v1/assess UCP-Agent: profile="https://platform.example/profiles/shopping-agent.json" Content-Type: application/json Authorization: Bearer fky_live_…
→ 400
{ "errors": [
{ "type": "VersionNotSupportedError",
"message": "UCP version 2099-01-01 not supported (this engine speaks 2026-04-08)." }
]}The request
The AP2 payment mandate the UCP transaction carries is assessed by the core exactly as always, top-level mandate, with kind: ap2_payment. The ucp block only binds the assessment to the checkout. Every field is optional.
| Field | Meaning |
|---|---|
ucp.checkout_id | The UCP checkout this assessment belongs to (id is also accepted). |
ucp.profile | The platform profile URL advertised via UCP-Agent. |
ucp.ucp_version | Protocol version asserted by the caller (else the engine's pinned release). |
idempotency_key | Echoed back; the mandate content_hash governs idempotency. |
{
"mandate": { "vct": "mandate.payment.1", … },
"ucp": { "checkout_id": "checkout_123", "ucp_version": "2026-04-08" }
}The verdict, as a UCP signal
With UCP engaged, the response carries a ucp block. The verdict is placed in UCP signals, the protocol's mechanism for independently-verifiable third-party attestations, under the reverse-domain namespace com.fidacy.trust_verdict. The signal embeds the signed credential (jws) and the public JWKS (provider_jwks) needed to verify it. A platform reads recommended_action and maps it to its own checkout state.
→ 200
{
"decision": "review",
"riskPayloadJws": "eyJ…",
"ucp": {
"version": "2026-04-08",
"checkout_id": "checkout_123",
"recommended_action": "step_up",
"signals": {
"com.fidacy.trust_verdict": {
"format": "application/vc+jws",
"jws": "eyJ…",
"provider_jwks": "https://api.fidacy.com/.well-known/jwks.json",
"kid": "1zoM57brjllufNTzCwI5-j5jFkiAslyzVDbPAcR_f-M",
"payload": { /* the full signed outcome */ }
}
},
"idempotency_key": null
}
}Decision → recommended action
Fidacy returns an advisory action, it does not own the checkout. The merchant or PSP sets the final UCP status; step_up corresponds to the UCP requires_escalation state.
| Decision | Recommended action | Meaning |
|---|---|---|
| approve | proceed | Trust signal is green, safe to finalize the checkout. |
| review | step_up | Escalate, require buyer input or stronger auth (≈ requires_escalation). |
| deny | decline | Do not proceed with this agent on this transaction. |
provider_jwks and verify the embedded jws (EdDSA) before acting on the verdict.Verify the signal
The embedded credential is the same EdDSA-signed risk payload Fidacy issues everywhere, a self-contained verifiable credential. Verify it against the public JWKS with one call; no Fidacy account or secret needed.
import { verifyRiskPayload } from "@fidacy/verify";
const sig = res.ucp.signals["com.fidacy.trust_verdict"];
const verdict = await verifyRiskPayload(sig.jws); // checks EdDSA vs public JWKS
// → throws if tampered; returns the trusted claims otherwiseBinding spec
The full, dereferenceable Fidacy Trust-Verdict Binding (UCP) documents the com.fidacy.trust_verdict signal, its schema, the advisory action, and the verification flow. The signed jws is the source of truth, and Fidacy does not publish a /.well-known/ucp profile (that is for businesses and platforms); key discovery is the provider_jwks inline.
Pluggable by design
UCP, A2A, and AP2 differ only at the protocol edge, engagement and verdict packaging. Internally they dispatch through a single adapter registry over a protocol-blind core. A new protocol is one adapter and one line, the verdict engine never changes.