Skip to main content

agentvisa-fastapi

FastAPI middleware for AgentVisa — verify that incoming AI agents were authorized by a real, biometrically authenticated human before granting access.

Install

pip install agentvisa-fastapi

Quick start

from fastapi import FastAPI, Depends
from agentvisa_fastapi import AgentVisaConfig, AgentVisaMiddleware, require_agentvisa

app = FastAPI()

config = AgentVisaConfig(
    api_key=os.environ["AGENTVISA_API_KEY"],   # your Widget Holder API key — server-side only
    widget_id=os.environ["AGENTVISA_WIDGET_ID"],  # from your AgentVisa dashboard
)

# Add middleware — enriches every request with request.state.agentvisa
app.add_middleware(AgentVisaMiddleware, config=config)

# Protected route — agents without a valid AgentVisa token get 401
@app.get("/api/orders")
async def get_orders(av=Depends(require_agentvisa(config))):
    return {"orders": [...], "plan": av.plan}

# Unprotected route — check manually if you want soft enforcement
@app.get("/api/public")
async def public(request: Request):
    av = request.state.agentvisa
    if av.valid:
        return {"message": "Hello, verified agent!", "plan": av.plan}
    return {"message": "Hello — consider getting an AgentVisa for full access."}

How it works

When an AI agent hits your site, AgentVisa requires a two-step handshake:

  1. Your server returns 401 with X-AgentVisa-Required: your_widget_id — this middleware does that automatically via require_agentvisa.
  2. The agent calls AgentVisa to get a short-lived TemporaryToken scoped to your site.
  3. The agent retries with X-AgentVisa-Token: tmp_... in the header.
  4. This middleware calls /v1/verify with your API key and returns the result.

The human behind the agent completed 5-factor verification (email, phone, cross-verification, biometric authentication, and a human assertion) when they got their AgentVisa.

Configuration

AgentVisaConfig(
    api_key="wk_...",            # required — your Widget Holder API key
    widget_id="wgt_...",         # required — your widget ID
    api_base="https://api.agentvisa.ai",  # optional — override for self-hosted
    timeout=5.0,                 # optional — /v1/verify timeout in seconds
)

Security note: Never expose api_key in client-side code, environment variables that get bundled, or logs. Treat it like a database password.

AgentVisaResult fields

Field Type Description
valid bool Whether the agent is verified
reason str "ok", "invalid", "expired", "revoked", "reverification_required", "token_not_present"
plan str "basic" or "pro"
widget_id str Your widget ID
verified_at datetime | None When the token was issued
expires_at datetime | None When the token expires
domain_verified bool | None Whether the widget's registered domain is verified
age_over_18 "y" | "n" | "null" | None Pro plan only — AVS-style flag, no raw DOB
age_over_21 "y" | "n" | "null" | None Pro plan only — AVS-style flag
multiple_agents_authorized "y" | "n" | None Pro plan only
web_bot_auth_bound bool | None Pro plan — token covered by RFC 9421 Signature-Input
skipped bool True when no token was in the request

Using without the middleware

If you don't want to add middleware, use the dependency standalone — it will call /v1/verify directly:

from agentvisa_fastapi import AgentVisaConfig, require_agentvisa

config = AgentVisaConfig(api_key="...", widget_id="...")

@app.post("/checkout")
async def checkout(av=Depends(require_agentvisa(config))):
    # verified agents only
    ...

Using get_agentvisa for soft enforcement

from agentvisa_fastapi import AgentVisaConfig, get_agentvisa, AgentVisaResult

config = AgentVisaConfig(api_key="...", widget_id="...")

@app.get("/search")
async def search(av: AgentVisaResult = Depends(get_agentvisa(config))):
    results = perform_search()
    if not av.valid:
        # Return limited results for unverified agents
        return {"results": results[:3], "note": "Get an AgentVisa for full results"}
    return {"results": results}

Reverification

When an agent's daily verification limit is hit, /v1/verify returns reason: "reverification_required". This middleware propagates that reason in the 401 response so your users know to check their email.

The require_agentvisa dependency returns:

HTTP 401
X-AgentVisa-Required: your_widget_id
{"detail": "AgentVisa reverification required — check email"}

The AgentVisa MCP server handles this automatically — it calls POST /v1/holder/reverify to trigger the re-verification email without the human needing to intervene.

License

MIT

Metadata

Release files for agentvisa-fastapi 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for agentvisa-fastapi 0.1.1
File Size Uploaded Provenance Actions
agentvisa_fastapi-0.1.1.tar.gz 10.2 kB Without provenance Details for agentvisa_fastapi-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for agentvisa-fastapi 0.1.1
File Interpreter ABI Platform Actions
agentvisa_fastapi-0.1.1-py3-none-any.whl Python 3 none any Details for agentvisa_fastapi-0.1.1-py3-none-any.whl

Total release size: 20.5 kB

Release files / agentvisa_fastapi-0.1.1.tar.gz

Download URL agentvisa_fastapi-0.1.1.tar.gz
Size 10.2 kB
Tags Source
SHA-256 checksum
How to use checksums
6f6b3be85dffb669af09a3577452a828bfacb2f6ac1cb3c46e5ce479345649c0
BLAKE2b-256 checksum
How to use checksums
0f6cdac50f9571d7fd4cb3afa189f8a6bc5169358ece1c01afdb009c8dcc10c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Release files / agentvisa_fastapi-0.1.1-py3-none-any.whl

Download URL agentvisa_fastapi-0.1.1-py3-none-any.whl
Size 10.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b538255ad1f8cd8882cbbdc207736554e676f3dcaab1bf7ae70fb8804aec3d4b
BLAKE2b-256 checksum
How to use checksums
a6bd283b6fa826c4430c7c0251ef2b2a7f1dc9bf5e8700000ca6ce8af2a840f0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.4

Security for agentvisa-fastapi 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page