Agentic API
Agentic API is Ratify’s initial managed-product wedge. Use it when an AI agent is about to call an MCP tool, send an A2A request, invoke a REST endpoint, or trigger another consequential programmatic action.
Ratify Verify returns the authorization decision and reason. Your gateway, MCP server, or application middleware decides whether the protected action executes. The managed audit trail records the verification attempt. The open-source SDKs let you build the same check fully offline; the managed Ratify Verify API adds metering, hosted revocation checks, and the recorded audit trail. This is an integration pattern using the managed Verify API, not a prebuilt commercial gateway.
This is the surface you use when an agent platform needs to authorize:
- MCP tool calls
- A2A requests
- REST API actions
- financial actions such as
payments:send - data reads and writes
- regulated internal tools
The gateway pattern is:
- Map each route, tool, or operation to a required Ratify scope.
- Extract the proof bundle from the request.
- Reconstruct verifier context from observable request data.
- Call the SDK verifier.
- Reject failed proofs before the request reaches the protected handler.
Header convention
Section titled “Header convention”Use a single proof header unless the transport has a native auth envelope:
X-Ratify-Proof: <base64-encoded-proof-bundle-json>Scope mapping
Section titled “Scope mapping”routes: "GET /v1/accounts/:id": required_scope: "data:read" "POST /v1/payments": required_scope: "payments:send" "POST /mcp/tools/send_email": required_scope: "execute:tool" "POST /v1/ledger/post": required_scope: "payments:send" "PATCH /v1/customers/:id": required_scope: "data:write"Enforcement rule
Section titled “Enforcement rule”If verification fails, return 401 for missing proof and 403 for invalid, expired, revoked, under-scoped, or constraint-denied proof.
Never let callers provide their own constraint context for high-stakes checks. The gateway should derive amount, route, IP, tenant, and request body hash from the request it actually received.
Gateway code example
Section titled “Gateway code example”result := ratify.Verify(bundle, ratify.VerifyOptions{ RequiredScope: ratify.ScopePaymentsSend, Context: ratify.VerifierContext{ // populate amount, route, tenant, etc from the request },})if !result.Valid { http.Error(w, result.ErrorReason, http.StatusForbidden) return}const result = await verifyBundle(bundle, { required_scope: SCOPE_PAYMENTS_SEND, context: { // populate amount, route, tenant, etc from the request },});if (!result.valid) { return new Response(result.error_reason, { status: 403 });}result = verify_bundle(bundle, VerifyOptions(required_scope=SCOPE_PAYMENTS_SEND))if not result.valid: raise PermissionError(result.error_reason)let result = verify_bundle( &bundle, &VerifyOptions { required_scope: SCOPE_PAYMENTS_SEND.into(), ..Default::default() },);assert!(result.valid, "{}", result.error_reason);/* Extract and base64-decode X-Ratify-Proof header, then verify before passing to the route handler. */const char *proof_hdr = http_get_header(req, "X-Ratify-Proof");if (!proof_hdr) { http_respond(req, 401, "missing proof"); return; }
char bundle_json[MAX_BUNDLE];if (base64_decode(proof_hdr, bundle_json, sizeof(bundle_json)) < 0) { http_respond(req, 400, "malformed proof"); return;}
RatifyVerifyResult *result = NULL;char *err = NULL;ratify_verify_bundle(bundle_json, "payments:send", (int64_t)time(NULL), &result, &err);
if (!ratify_verify_result_is_valid(result)) { char *status = ratify_verify_result_identity_status(result); /* 401 for missing (handled above), 403 for all verification failures */ http_respond(req, 403, status); ratify_string_free(status); ratify_verify_result_free(result); ratify_error_free(err); return;}
ratify_verify_result_free(result);ratify_error_free(err);/* proceed to route handler */