How AI crawlers and agents use a zone, by category, bot and operator, plus traps, signals, MCP Shield and the bot catalog.
Reports of AI Crawl Control. The edge classifies automated traffic (AI training, AI search, user-triggered AI agents, search engines, unverified automation, spoofed claims) and verifies bots against the catalog. Every endpoint accepts any role, zone tokens included. Configure the behaviour in the ai_agents block of the edge settings . See AI Crawl Control .
# Get AI agents report
GET /v1/orgs/{org}/zones/{zone}/ai-agents/report
Returns in one call the summary, time series, bots, top sources and ai_agents settings of the zone (or of one name with host).
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/report" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsReport({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_report(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"summary" : {
"since" : "2026-10-27T09:30:00Z" ,
"until" : "2026-10-27T09:30:00Z" ,
"prev_since" : "2026-10-27T09:30:00Z" ,
"prev_until" : "2026-10-27T09:30:00Z" ,
"requests" : 128 ,
"prev_requests" : 128 ,
"categories" : [
{
"category" : "ai_training" ,
"requests" : 128 ,
"prev_requests" : 128
}
],
"decisions" : [
{
"decision" : "example" ,
"enforced" : 0 ,
"would" : 0
}
],
"trap" : {
"injected" : 0 ,
"hits" : 128 ,
"prev_injected" : 0 ,
"prev_hits" : 128
}
},
"timeseries" : {
"step" : 0 ,
"points" : [
{}
]
},
"agents" : {
"rows" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"category" : "ai_training" ,
"requests" : 128 ,
"verified" : 0 ,
"unverified" : 0 ,
"spoofed" : 0 ,
"methods" : [
"POST"
],
"last_seen" : "2026-10-27T09:30:00Z"
}
]
},
"top" : {
"ip" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
],
"fingerprint" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
],
"asn" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
]
},
"settings" : {
"enabled" : false ,
"mode" : "log" ,
"spoofed_challenge" : "log" ,
"template" : "search_ok_block_training" ,
"policy" : {
"ai_training" : "allow" ,
"ai_search" : "allow" ,
"ai_user_agent" : "allow" ,
"search_engine" : "allow" ,
"unverified_automation" : "allow" ,
"spoofed" : "allow" ,
"unverified_bot" : "allow" ,
"trap_hit" : "allow" ,
"secret_probe" : "allow" ,
"robots_violation" : "allow" ,
"agent_burst" : "allow"
},
"bot_overrides" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"action" : "block"
}
],
"trap" : {
"enabled" : false
},
"tarpit" : {
"enabled" : false
},
"robots" : {
"enabled" : false ,
"content_signals" : {
"search" : "yes" ,
"ai_input" : "yes" ,
"ai_train" : "yes"
}
},
"markdown" : {
"enabled" : false
},
"block_response" : {
"status" : 403 ,
"message" : ""
},
"endpoints" : [
{
"path_prefix" : "/api/" ,
"methods" : [
"POST"
],
"max_body_bytes" : 0 ,
"rpm_per_ip" : 0 ,
"rpm_per_session" : 0 ,
"session_header" : "X-Session-Id" ,
"session_cookie" : "session" ,
"injection_action" : "log" ,
"limit_action" : "log" ,
"kind" : "mcp" ,
"mcp" : {}
}
]
},
"catalog_version" : "example"
}
# Get AI Crawl Control overview
GET /v1/orgs/{org}/zones/{zone}/ai-agents/overview
Returns the AI Crawl Control overview of the dashboard, highlights, cards with their series and operators.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description sincestring (date-time) untilstring (date-time) stepinteger tsarray of string (date-time) Time of the request. factsobject facts.requestsinteger Requests. facts.prev_requestsinteger facts.status_4xxinteger facts.top_operator_htmlobject or null facts.top_pathobject or null facts.top_crawlerobject or null cardsobject cards.totalAiCard cards.allowedAiCard cards.failedAiCard operatorsarray of object operators[].operatorstring Company that operates the bot. operators[].crawlersarray of object operators[].allowedinteger operators[].prev_allowedinteger
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/overview" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsOverview({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_overview(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"since" : "2026-10-27T09:30:00Z" ,
"until" : "2026-10-27T09:30:00Z" ,
"step" : 0 ,
"ts" : [
"2026-10-27T09:30:00Z"
],
"facts" : {
"requests" : 128 ,
"prev_requests" : 128 ,
"status_4xx" : 0 ,
"top_operator_html" : {},
"top_path" : {},
"top_crawler" : {}
},
"cards" : {
"total" : {
"value" : 0 ,
"prev" : 0 ,
"series" : [
0
]
},
"allowed" : {
"value" : 0 ,
"prev" : 0 ,
"series" : [
0
]
},
"failed" : {
"value" : 0 ,
"prev" : 0 ,
"series" : [
0
]
}
},
"operators" : [
{
"operator" : "OpenAI" ,
"crawlers" : [
{}
],
"allowed" : 0 ,
"prev_allowed" : 0
}
]
}
# Get AI agents summary
GET /v1/orgs/{org}/zones/{zone}/ai-agents/summary
Counts the zone's requests per traffic category and decision, plus the trap, against the previous period.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description sincestring (date-time) untilstring (date-time) prev_sincestring (date-time) prev_untilstring (date-time) requestsinteger Requests. prev_requestsinteger categoriesarray of AiCount decisionsarray of object decisions[].decisionstring decisions[].enforcedinteger decisions[].wouldinteger What would be applied in enforce mode. trapAiTrapSummary
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/summary" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsSummary({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_summary(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"since" : "2026-10-27T09:30:00Z" ,
"until" : "2026-10-27T09:30:00Z" ,
"prev_since" : "2026-10-27T09:30:00Z" ,
"prev_until" : "2026-10-27T09:30:00Z" ,
"requests" : 128 ,
"prev_requests" : 128 ,
"categories" : [
{
"category" : "ai_training" ,
"requests" : 128 ,
"prev_requests" : 128
}
],
"decisions" : [
{
"decision" : "example" ,
"enforced" : 0 ,
"would" : 0
}
],
"trap" : {
"injected" : 0 ,
"hits" : 128 ,
"prev_injected" : 0 ,
"prev_hits" : 128
}
}
# Get AI agents time series
GET /v1/orgs/{org}/zones/{zone}/ai-agents/timeseries
Returns the requests per category over time.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. stepquery integer No Seconds per point (0 = automatic). Minimum 0.
# Response
Field Type Description stepinteger pointsarray of object
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/timeseries" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsTimeseries({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_timeseries(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"step" : 0 ,
"points" : [
{}
]
}
# List seen bots
GET /v1/orgs/{org}/zones/{zone}/ai-agents/agents
Lists the bots seen on the zone, verified, unverified and spoofed.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/agents" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsAgents({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_agents(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"rows" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"category" : "ai_training" ,
"requests" : 128 ,
"verified" : 0 ,
"unverified" : 0 ,
"spoofed" : 0 ,
"methods" : [
"POST"
],
"last_seen" : "2026-10-27T09:30:00Z"
}
]
}
# Get top automated sources
GET /v1/orgs/{org}/zones/{zone}/ai-agents/top
Returns the top IPs, TLS fingerprints and ASNs of the automated traffic.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. limitquery integer No 10 by default. Minimum 0.
# Response
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/top" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsTop({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_top(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"ip" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
],
"fingerprint" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
],
"asn" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"category" : "ai_training" ,
"requests" : 128
}
]
}
# List notable AI events
GET /v1/orgs/{org}/zones/{zone}/ai-agents/events
Lists the notable events (spoofing, trap hits, injections, MCP Shield detections…), newest first.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. kindquery string No Comma-separated kinds (spoofed, trap_hit, injection, cost_limit, automation, wba_invalid, tarpit, blocked, secret_probe, robots_violation, agent_burst; MCP Shield: mcp_blocked_method, mcp_blocked_tool, mcp_injection_request, mcp_injection_response, mcp_dlp, mcp_rate_limited, mcp_invalid). cursorquery string No Cursor of the next page (next_cursor of the previous answer). limitquery integer No 50 by default, at most 500. Minimum 0.
# Response
Field Type Description itemsarray of AiEvent next_cursorstring
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/events?kind=spoofed,trap_hit" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsEvents({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" ,
kind: "spoofed,trap_hit"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_events(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" , kind="spoofed,trap_hit" )
200
{
"items" : [
{
"event_id" : "57c7c826-7db4-42c8-af1d-3ecdfe37182f" ,
"ts" : "2026-10-27T09:30:00Z" ,
"site_id" : 0 ,
"node_id" : "edge-node-1" ,
"host" : "www.example.com" ,
"kind" : "spoofed" ,
"category" : "ai_training" ,
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"verified" : false ,
"verify" : "" ,
"decision" : "example" ,
"enforced" : false ,
"ip" : "203.0.113.10" ,
"country_code" : "ES" ,
"asn" : 0 ,
"user_agent" : "Mozilla/5.0" ,
"tls_fingerprint" : "" ,
"method" : "GET" ,
"path" : "/checkout" ,
"status" : 0 ,
"signals" : [
"example"
],
"detections" : [
{}
],
"token_age_ms" : 0 ,
"mcp" : {
"method" : "GET" ,
"tool" : "search_docs" ,
"token_fp" : "example" ,
"blocked" : false
}
}
],
"next_cursor" : ""
}
# Get AI agents metrics
GET /v1/orgs/{org}/zones/{zone}/ai-agents/metrics
Returns metrics per group (crawler, category, operator, host or content type) with status classes and most requested pages. format=csv downloads CSV instead of JSON.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. statusquery string No Only responses with this status class. One of all, 1xx, 2xx, 3xx, 4xx, 5xx. group_byquery string No Dimension to group by. One of crawler, category, operator, host, content_type. offsetquery integer No Number of rows to skip (pagination). Minimum 0. limitquery integer No 10 by default, at most 100. Minimum 0. formatquery string No csv: download CSV instead of JSON. One of csv.
# Response
Field Type Description stepinteger tsarray of string (date-time) Time of the request. statusstring group_bystring cardsobject requestsarray of AiSeries Requests. bytesarray of AiSeries status_classesarray of object content_typesarray of object top_pathsAiPathPage
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/metrics?group_by=operator" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsMetrics({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" ,
group_by: "operator"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_metrics(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" , group_by="operator" )
200
{
"step" : 0 ,
"ts" : [
"2026-10-27T09:30:00Z"
],
"status" : "example" ,
"group_by" : "example" ,
"cards" : {},
"requests" : [
{
"key" : "/pricing" ,
"label" : "AI training" ,
"total" : 128 ,
"series" : [
0
]
}
],
"bytes" : [
{
"key" : "/pricing" ,
"label" : "AI training" ,
"total" : 128 ,
"series" : [
0
]
}
],
"status_classes" : [
{}
],
"content_types" : [
{}
],
"top_paths" : {
"total" : 128 ,
"items" : [
{
"host" : "www.example.com" ,
"path" : "/checkout" ,
"bytes" : 0 ,
"requests" : 128 ,
"secret_probe" : false
}
]
}
}
# List crawlers
GET /v1/orgs/{org}/zones/{zone}/ai-agents/crawlers
Lists the catalog crawlers with their requests, verified and spoofed requests, bursts and effective action.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. inactivequery string No 1: include the catalog bots without traffic. One of 1.
# Response
Field Type Description stepinteger tsarray of string (date-time) Time of the request. rowsarray of object rows[].bot_idstring rows[].namestring Name. rows[].operatorstring Company that operates the bot. rows[].categorystring rows[].methodsarray of string rows[].bytesinteger rows[].requestsinteger Requests. rows[].allowedinteger rows[].unsuccessfulinteger rows[].seriesarray of integer rows[].verifiedinteger rows[].spoofedinteger rows[].unverifiedinteger rows[].burstsinteger agent_burst events of the bot. rows[].actionstring rows[].action_sourcestring override, category or unverified_bot.
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/crawlers" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsCrawlers({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_crawlers(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"step" : 0 ,
"ts" : [
"2026-10-27T09:30:00Z"
],
"rows" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"category" : "ai_training" ,
"methods" : [
"POST"
],
"bytes" : 0 ,
"requests" : 128 ,
"allowed" : 0 ,
"unsuccessful" : 0 ,
"series" : [
0
],
"verified" : 0 ,
"spoofed" : 0 ,
"unverified" : 0 ,
"bursts" : 0 ,
"action" : "block" ,
"action_source" : "example"
}
]
}
# List spoofers of a bot
GET /v1/orgs/{org}/zones/{zone}/ai-agents/spoofers
Lists the IPs and ASNs that claimed to be a bot without passing its verification. bot is required.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description bot_idstring ipsarray of object ips[].valuestring ips[].country_codestring ISO 3166-1 alpha-2 country code. ips[].asninteger Autonomous system number. ips[].requestsinteger Requests. ips[].last_seenstring (date-time) asnsarray of object asns[].asninteger Autonomous system number. asns[].country_codestring ISO 3166-1 alpha-2 country code. asns[].requestsinteger Requests.
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/spoofers?bot=gptbot" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsSpoofers({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" ,
bot: "gptbot"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_spoofers(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" , bot="gptbot" )
200
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"ips" : [
{
"value" : "4f1c2e9a7b3d" ,
"country_code" : "ES" ,
"asn" : 0 ,
"requests" : 128 ,
"last_seen" : "2026-10-27T09:30:00Z"
}
],
"asns" : [
{
"asn" : 0 ,
"country_code" : "ES" ,
"requests" : 128
}
]
}
# Get AI content optimization
GET /v1/orgs/{org}/zones/{zone}/ai-agents/optimization
Returns the pages AI fetches and the demand for pages that do not exist. format=csv downloads CSV instead of JSON.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters. offsetquery integer No Number of rows to skip (pagination). Minimum 0. limitquery integer No 10 by default, at most 100. Minimum 0. formatquery string No csv: download CSV instead of JSON. One of csv.
# Response
Field Type Description cardsobject cards.retrievalsobject cards.demandobject top_pagesAiPathPage demandAiPathPage operatorsarray of object
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/optimization" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsOptimization({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_optimization(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"cards" : {
"retrievals" : {
"value" : 0 ,
"prev" : 0
},
"demand" : {
"value" : 0 ,
"prev" : 0
}
},
"top_pages" : {
"total" : 128 ,
"items" : [
{
"host" : "www.example.com" ,
"path" : "/checkout" ,
"bytes" : 0 ,
"requests" : 128 ,
"secret_probe" : false
}
]
},
"demand" : {
"total" : 128 ,
"items" : [
{
"host" : "www.example.com" ,
"path" : "/checkout" ,
"bytes" : 0 ,
"requests" : 128 ,
"secret_probe" : false
}
]
},
"operators" : [
{}
]
}
# Get robots.txt signals
GET /v1/orgs/{org}/zones/{zone}/ai-agents/signals
Returns the robots.txt requests, the Content-Signal values served and the violations of its rules.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description robotsarray of object robots[].hoststring robots[].requestsinteger Requests. robots[].okinteger robots[].failedinteger robots[].last_statusinteger robots[].content_signalsboolean violationsarray of object violations[].bot_idstring violations[].namestring Name. violations[].operatorstring Company that operates the bot. violations[].categorystring violations[].hoststring violations[].pathstring violations[].requestsinteger Requests.
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/signals" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsSignals({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_signals(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"robots" : [
{
"host" : "www.example.com" ,
"requests" : 128 ,
"ok" : 0 ,
"failed" : 0 ,
"last_status" : 0 ,
"content_signals" : false
}
],
"violations" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"category" : "ai_training" ,
"host" : "www.example.com" ,
"path" : "/checkout" ,
"requests" : 128
}
]
}
# Get trap activity
GET /v1/orgs/{org}/zones/{zone}/ai-agents/traps
Returns the trap insertions, who followed the trap and the agent bursts.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description injectedinteger hitsinteger prev_injectedinteger prev_hitsinteger burstsinteger prev_burstsinteger stepinteger tsarray of string (date-time) Time of the request. seriesobject series.injectedarray of integer series.hitsarray of integer hittersarray of object hitters[].ipstring hitters[].country_codestring ISO 3166-1 alpha-2 country code. hitters[].asninteger Autonomous system number. hitters[].tls_fingerprintstring TLS fingerprint of the client. hitters[].bot_idstring hitters[].hitsinteger hitters[].last_seenstring (date-time)
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/traps" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsTraps({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_traps(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"injected" : 0 ,
"hits" : 128 ,
"prev_injected" : 0 ,
"prev_hits" : 128 ,
"bursts" : 0 ,
"prev_bursts" : 0 ,
"step" : 0 ,
"ts" : [
"2026-10-27T09:30:00Z"
],
"series" : {
"injected" : [
0
],
"hits" : [
0
]
},
"hitters" : [
{
"ip" : "203.0.113.10" ,
"country_code" : "ES" ,
"asn" : 0 ,
"tls_fingerprint" : "" ,
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"hits" : 128 ,
"last_seen" : "2026-10-27T09:30:00Z"
}
]
}
# List agent bursts
GET /v1/orgs/{org}/zones/{zone}/ai-agents/bursts
Lists the composite bursts of agents in code mode (agent_burst), the clients with an explanation, the bots and the detections.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description burstsinteger prev_burstsinteger clientsarray of object At most 50 items. clients[].ipstring clients[].country_codestring ISO 3166-1 alpha-2 country code. clients[].asninteger Autonomous system number. clients[].tls_fingerprintstring TLS fingerprint of the client. clients[].bot_idstring clients[].burstsinteger clients[].last_seenstring (date-time) clients[].explanationsarray of string Detection labels (distinct_endpoints=23/10s, id_walk=…, pagination=…). At most 3 items. crawlersarray of object crawlers[].bot_idstring crawlers[].namestring Name. crawlers[].operatorstring Company that operates the bot. crawlers[].burstsinteger detectionsarray of object detections[].idstring Id. detections[].labelstring detections[].countinteger
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/bursts" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsBursts({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_bursts(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"bursts" : 0 ,
"prev_bursts" : 0 ,
"clients" : [
{
"ip" : "203.0.113.10" ,
"country_code" : "ES" ,
"asn" : 0 ,
"tls_fingerprint" : "" ,
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"bursts" : 0 ,
"last_seen" : "2026-10-27T09:30:00Z" ,
"explanations" : []
}
],
"crawlers" : [
{
"bot_id" : "948186e3-4508-48d6-a001-c683a3ec9626" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"bursts" : 0
}
],
"detections" : [
{
"id" : "example" ,
"label" : "AI training" ,
"count" : 128
}
]
}
# Get AI endpoints activity
GET /v1/orgs/{org}/zones/{zone}/ai-agents/endpoints
Returns the activity of the site's AI endpoints, injections, limits and blocks.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters. categoryquery string No Only that traffic category. One of ai_training, ai_search, ai_user_agent, search_engine, unverified_automation, spoofed, human. botquery string No Id of a catalog bot (gptbot). At most 253 characters. operatorquery string No Operator (OpenAI). At most 64 characters.
# Response
Field Type Description rowsarray of object rows[].path_prefixstring rows[].requestsinteger Requests. rows[].injectionsinteger rows[].limitedinteger rows[].blockedinteger rows[].would_blockinteger detectionsarray of object detections[].idstring Id. detections[].labelstring detections[].countinteger
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/endpoints" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsEndpoints({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_endpoints(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"rows" : [
{
"path_prefix" : "/api/" ,
"requests" : 128 ,
"injections" : 0 ,
"limited" : 0 ,
"blocked" : 0 ,
"would_block" : 0
}
],
"detections" : [
{
"id" : "example" ,
"label" : "AI training" ,
"count" : 128
}
]
}
# Get MCP Shield activity
GET /v1/orgs/{org}/zones/{zone}/ai-agents/mcp
Returns the MCP Shield activity of the site's MCP endpoints, JSON-RPC messages, blocks, detections and tools. See MCP Shield .
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404). zonepath string (uuid) Yes Zone id (see List zones ). rangequery string No Period up to now: 24h (default), 7d or 30d; not with since. One of 24h, 7d, 30d. sincequery string (date-time) No RFC 3339. untilquery string (date-time) No RFC 3339, exclusive; now by default. At most 31 days of range. hostquery string No Only that name. At most 253 characters.
# Response
Field Type Description endpointsarray of object endpoints[].path_prefixstring endpoints[].requestsinteger Requests. endpoints[].messagesinteger endpoints[].blockedinteger endpoints[].detectionsinteger endpoints[].uninspectedinteger toolsarray of object tools[].path_prefixstring tools[].toolstring tools[].callsinteger tools[].blockedinteger tools[].detectionsinteger kindsarray of object kinds[].kindstring kinds[].countinteger detectionsarray of object detections[].idstring Id. detections[].labelstring detections[].countinteger
# Errors
Status Description 400Malformed request (bad_request). 404Not found, or not visible to the token (not_found). 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/ai-agents/mcp" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIAgentsMCP({
zone: "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d"
});from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_agents_mcp(zone="6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d" )
200
{
"endpoints" : [
{
"path_prefix" : "/api/" ,
"requests" : 128 ,
"messages" : 0 ,
"blocked" : 0 ,
"detections" : 0 ,
"uninspected" : 0
}
],
"tools" : [
{
"path_prefix" : "/api/" ,
"tool" : "search_docs" ,
"calls" : 0 ,
"blocked" : 0 ,
"detections" : 0
}
],
"kinds" : [
{
"kind" : "example" ,
"count" : 128
}
],
"detections" : [
{
"id" : "example" ,
"label" : "AI training" ,
"count" : 128
}
]
}
# Get the AI bot catalog
GET /v1/orgs/{org}/ai-agents/catalog
Returns the AI bot catalog the edge verifies against, each bot's operator, category and verification methods (published IP ranges, reverse DNS, Web Bot Auth signatures), and the state of each official source. The ranges and keys themselves are not included.
Required role: readonly or higher.
# Parameters
Name In Type Required Description orgpath string (uuid) Yes Organization id. Every route checks that it is the token's organization (otherwise 404).
# Response
Field Type Description versionstring Version number. botsarray of object bots[].idstring Id. bots[].namestring Name. bots[].operatorstring Company that operates the bot. bots[].categorystring One of ai_training, ai_search, ai_user_agent, search_engine. bots[].methodsarray of string Items: one of ip, rdns, web_bot_auth. bots[].uaarray of string bots[].rdnsarray of string bots[].cidr_countinteger bots[].signature_agentsarray of string sourcesarray of object sources[].idstring Id. sources[].urlstring sources[].fetched_atstring (date-time) or null sources[].okboolean sources[].errorstring sources[].itemsinteger sources[].baselineboolean No stored download: the built-in data is used.
# Errors
Status Description 503Not available right now (unavailable); retry later.
# Example
curl TypeScript Python
curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/ai-agents/catalog" \
-H "Authorization: Bearer $OPENWAF_TOKEN" import { OpenWAF } from "./openwaf" ;
const owf = new OpenWAF({ baseUrl: "https://dash.openwaf.dev" }); // token from OPENWAF_TOKEN
const result = await owf.getAIBotCatalog();from openwaf import OpenWAF
owf = OpenWAF(base_url="https://dash.openwaf.dev" ) # token from OPENWAF_TOKEN
result = owf.get_ai_bot_catalog()
200
{
"version" : "example" ,
"bots" : [
{
"id" : "example" ,
"name" : "example.com" ,
"operator" : "OpenAI" ,
"category" : "ai_training" ,
"methods" : [
"POST"
],
"ua" : [
"example"
],
"rdns" : [
"example"
],
"cidr_count" : 128 ,
"signature_agents" : [
"example"
]
}
],
"sources" : [
{
"id" : "example" ,
"url" : "https://www.example.com/" ,
"fetched_at" : "2026-10-27T09:30:00Z" ,
"ok" : false ,
"error" : "" ,
"items" : 0 ,
"baseline" : false
}
]
}