AxioRankDocs

Inbound surfaces

Verify the AI agents that reach into the surfaces you operate, a website, an HTTP API, an MCP server, an A2A agent, or a webhook, with one verify endpoint and a per-kind challenge.

The rest of AxioRank governs the calls your agents make outbound. Inbound surfaces are the other direction: the AI agents reaching into something you operate. A surface is a typed entry point you register once, and every request to it is verified, scored, and allowed, challenged, or blocked, with the same audit trail as an outbound tool call.

One endpoint, five kinds

Every surface kind resolves through a single gateway endpoint, POST /api/gateway/verify-request, authenticated with a surface site key (axr_site_...), distinct from your agent key. The SDK helpers build the call for you; you rarely hit the endpoint by hand.

The five surface kinds

KindWhat it protectsHow a caller proves identity
websiteA site or app AI agents browseWeb Bot Auth signature (RFC 9421), reverse-DNS forward-confirm, or a known user-agent
http_apiA REST / RPC APIAn OAuth/OIDC bearer token (JWT verified against the issuer's JWKS), an mTLS/SPIFFE id, or a static API key
mcp_serverAn MCP server you exposeThe connecting agent's signed agent card (JWS, key-domain anchored)
a2a_agentAn A2A agent you exposeThe connecting agent's signed agent card (JWS, key-domain anchored)
webhookA webhook receiverAn HMAC signature scheme, or the same HTTP signals as a website

Register a surface from Settings, Surfaces or with POST /api/surfaces. Each surface counts against your plan's surface limit (1 on Free, 5 on Pro, 25 on Team, unlimited on Enterprise); there is no per-kind gate, so every plan can use every kind.

The verdict

A verified request resolves to one of three decisions, which already reflects the surface's posture:

  • allow: the caller is trusted enough for the operation. Serve the request.
  • challenge: ask the caller to prove more (re-sign, step up, or authenticate).
  • block: refuse the request.

The result also carries a verification block (status, method, and a confidence score) and, for a non-allow verdict, a per-kind challenge instruction so you enforce it in the caller's own protocol:

SurfaceChallenge transportMaps to
website, webhookhttpHTTP 401 (challenge) or 403 (block)
http_apihttp_stepup401 with a WWW-Authenticate: Bearer step-up (RFC 9470)
mcp_serverjsonrpcA JSON-RPC error, code -32001 (challenge) or -32002 (block)
a2a_agenta2a_taskA2A task state auth-required (challenge) or rejected (block)

Confidence

confidence grades how strongly identity was proven, on a 0 to 100 scale:

  • 100: cryptographic proof. A valid signature, a JWT that verifies against the JWKS, an mTLS certificate chain, or a signed card.
  • 70: a reverse-DNS lookup that forward-confirms a known crawler.
  • 40: a user-agent string that matches a known agent but is not proven.
  • 0: spoofed or unknown.

Monitor first, then enforce

A surface starts in monitor posture: AxioRank still computes and logs the verdict, but the response stays allow and enforced is false. Watch the audit log to see what would have been challenged or blocked, then switch to enforce when you are confident. Pair this with inbound policies to scope decisions by surface kind and operation (an MCP tool name, a JSON-RPC method, or an API operationId).

Fail-open by design

Inbound verification sits in the hot path of your own requests, so it fails open. Only a misconfigured site key raises; any timeout or transport failure resolves to a synthetic verdict (allow by default, configurable per call), so a verification outage never takes your surface down.

Verify from the SDK

A website or HTTP request

In TypeScript, verifyRequest takes a standard Request, so it drops into Next.js middleware, Hono, or Workers; axioGuard wraps it as ready-made middleware:

import { verifyRequest } from "@axiorank/sdk";

const result = await verifyRequest(req, { apiKey: process.env.AXIORANK_SITE_KEY! });
if (result.decision !== "allow") {
  return new Response("Verification required", { status: 401 });
}

In Python, verify_request takes the request metadata (the Web Bot Auth signature headers are lifted out for you), with sync and async variants for Flask or FastAPI:

from axiorank import verify_request

result = verify_request(
    method=request.method,
    authority=request.host,
    path=request.path,
    headers=dict(request.headers),
    api_key=os.environ["AXIORANK_SITE_KEY"],
)
if result.decision != "allow":
    abort(401)

An MCP server, A2A agent, HTTP API, or webhook

For an agent-native surface there is no standard HTTP Request to hand over, so you supply the caller's identity material directly. TypeScript:

import { verifySurface } from "@axiorank/sdk";

const result = await verifySurface(
  { surfaceKind: "mcp_server", operation: "tools/call", agentCard: incomingCard },
  { apiKey: process.env.AXIORANK_SITE_KEY! },
);
if (result.decision !== "allow") throw rpcError(result.challenge);

Python (verify_surface, with a verify_surface_async for ASGI servers):

from axiorank import verify_surface

result = verify_surface(
    {"surface_kind": "http_api", "auth_token": bearer_token},
    api_key=os.environ["AXIORANK_SITE_KEY"],
)
if result.decision != "allow":
    raise stepup_required(result.challenge)

Next steps

  • Policies: scope inbound decisions by surface kind and operation.
  • Gateway API: the raw verify-request contract.
  • Protocol adapters: the agent-card formats AxioRank verifies.
  • Claims: publish your own signed identity for others to verify.

On this page