FastAPI middleware for AgentVisa AI agent verification
Project description
agentvisa-fastapi
FastAPI middleware for AgentVisa — verify that incoming AI agents were authorized by a real, 5-factor biometric-verified 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": [...], "verified_human": av.human_name}
# 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:
- Your server returns 401 with
X-AgentVisa-Required: your_widget_id— this middleware does that automatically viarequire_agentvisa. - The agent calls AgentVisa to get a short-lived TemporaryToken scoped to your site.
- The agent retries with
X-AgentVisa-Token: tmp_...in the header. - This middleware calls
/v1/verifywith your API key and returns the result.
The human behind the agent completed 5-factor biometric verification (email, phone, cross-verification, Face ID / Touch ID, 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 |
human_name |
str | None |
Pro plan only |
five_factor |
"y" | "n" | None |
Pro plan only |
age_over_18 |
"y" | "n" | "null" | None |
Pro plan only |
age_over_21 |
"y" | "n" | "null" | None |
Pro plan only |
multiple_agents_authorized |
"y" | "n" | None |
Pro plan only |
verifications_today |
int | None |
Pro plan only |
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentvisa_fastapi-0.1.0.tar.gz.
File metadata
- Download URL: agentvisa_fastapi-0.1.0.tar.gz
- Upload date:
- Size: 9.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a816c0f81b0732cfcf6846bd328e36ac764678ab63c4865948041087693580f9
|
|
| MD5 |
c35b57f6368680733b54287ae43befe1
|
|
| BLAKE2b-256 |
84f11e548c2abe9be23115d98d3b15ad4c6ec189ef963a985e88592ec3f14cf4
|
File details
Details for the file agentvisa_fastapi-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agentvisa_fastapi-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4a0160c52631f32bbd7e71336e9c1381418e714b1d74b4391322fcb881fdb83b
|
|
| MD5 |
9ba18ab5ecd383ded08c4c5508909d5e
|
|
| BLAKE2b-256 |
242e58639fe2f16a97fcea23ca828ccff12dba81b3d26f115535b29588fd3fe7
|