API Reference Summary
Quick reference for key WebDecoy API endpoints.
Overview
Section titled “Overview”The WebDecoy API uses REST architecture with JSON payloads. There are two services with different credentials:
| Service | Base URL | Credential |
|---|---|---|
| Management API (everything on this page except the last section) | https://api.webdecoy.com/api |
Auth0 session JWT (the token the dashboard uses) |
| Ingest API (SDKs, sensors, detection scripts) | https://in.webdecoy.com/api for server-side sensors; https://ingest.webdecoy.com/api for the browser tag |
Organization API key (sk_live_...) or a public site key, depending on the route |
Authentication
Section titled “Authentication”Management API:
Authorization: Bearer <auth0_jwt_token>Ingest API (routes that take an API key):
Authorization: Bearer sk_live_your_api_keyAuthentication Endpoints
Section titled “Authentication Endpoints”Callback (Complete Auth0 Login)
Section titled “Callback (Complete Auth0 Login)”POST /auth/callbackAuthorization: Bearer <auth0_jwt>Response:
{ "id": "user-uuid", "auth0_id": "auth0|123", "name": "User Name"}Get Current User
Section titled “Get Current User”GET /auth/meAuthorization: Bearer <token>Organizations
Section titled “Organizations”Create Organization
Section titled “Create Organization”POST /organizationsAuthorization: Bearer <token>
{ "name": "My Organization"}List Organizations
Section titled “List Organizations”GET /organizations?page=1&page_size=50Authorization: Bearer <token>Get Organization
Section titled “Get Organization”GET /organizations/{organization_id}Authorization: Bearer <token>Update Organization
Section titled “Update Organization”PUT /organizations/{organization_id}Authorization: Bearer <token>
{ "name": "Updated Name"}Properties
Section titled “Properties”Create Property
Section titled “Create Property”POST /organizations/{organization_id}/propertiesAuthorization: Bearer <token>
{ "name": "Production Website", "owner_id": "user-uuid"}owner_id (the user UUID of the property owner) is required.
List Properties
Section titled “List Properties”GET /organizations/{organization_id}/properties?page=1&page_size=50Authorization: Bearer <token>Get Property
Section titled “Get Property”GET /properties/{property_id}Authorization: Bearer <token>Custom Domains
Section titled “Custom Domains”Create Domain
Section titled “Create Domain”POST /organizations/{organization_id}/domainsAuthorization: Bearer <token>
{ "domain": "decoy.example.com", "record_type": "A"}List Domains
Section titled “List Domains”GET /organizations/{organization_id}/domainsAuthorization: Bearer <token>Verify Domain
Section titled “Verify Domain”POST /domains/{domain_id}/verifyAuthorization: Bearer <token>
{ "dns_record": "..."}record_type on create is A or CNAME (default CNAME). The verify body requires dns_record.
SSL Certificates (ACME)
Section titled “SSL Certificates (ACME)”POST /domains/{domain_id}/acme/challenge # start a DNS-01 challengePOST /domains/{domain_id}/acme/verify-dns # check the TXT recordPOST /domains/{domain_id}/acme/verify # complete issuancePOST /domains/{domain_id}/acme/reset # start overPOST /domains/{domain_id}/ssl/http01/initiate # HTTP-01 alternative (A-record domains)POST /domains/{domain_id}/ssl/http01/completeAuthorization: Bearer <token>Check SSL Status
Section titled “Check SSL Status”POST /domains/{domain_id}/ssl-statusAuthorization: Bearer <token>Decoys
Section titled “Decoys”Create Decoy
Section titled “Create Decoy”POST /decoysAuthorization: Bearer <token>
{ "custom_domain_id": "domain-uuid", "name": "Admin Backup Trap", "path": "/admin/backup.zip", "trigger_action": "log", "decoy_type": "link"}trigger_action is one of log, block, poison, redirect. decoy_type is link or endpoint. Omit custom_domain_id and pass organization_id for a shared-domain decoy.
List Decoys
Section titled “List Decoys”GET /decoys?page=1&page_size=50Authorization: Bearer <token>Get Decoy
Section titled “Get Decoy”GET /decoys/{decoy_id}Authorization: Bearer <token>Update Decoy
Section titled “Update Decoy”PATCH /decoys/{decoy_id}Authorization: Bearer <token>
{ "name": "Updated Name", "is_active": false}List and Get report state (live, paused, expired or click_limit_reached) and, when resuming would remove a limit, resume_clears (expires_at, click_limit). Sending "is_active": true resumes the decoy and removes the limit that stopped it, the ones resume_clears names. "is_active": false pauses it and leaves both limits alone.
Delete Decoy
Section titled “Delete Decoy”DELETE /decoys/{decoy_id}Authorization: Bearer <token>Detection Scripts
Section titled “Detection Scripts”Create Detection Script
Section titled “Create Detection Script”POST /organizations/{organization_id}/bot-scannersAuthorization: Bearer <token>
{ "property_id": "property-uuid", "name": "Main Scanner", "enabled": true, "tier": "lite"}property_id is required. tier is lite (default) or pro.
List Detection Scripts
Section titled “List Detection Scripts”GET /organizations/{organization_id}/bot-scannersAuthorization: Bearer <token>Get Scanner Snippet
Section titled “Get Scanner Snippet”GET /organizations/{organization_id}/bot-scanners/{scanner_id}/snippetAuthorization: Bearer <token>Toggle Scanner
Section titled “Toggle Scanner”PATCH /organizations/{organization_id}/bot-scanners/{scanner_id}/toggleAuthorization: Bearer <token>Detections
Section titled “Detections”List Detections
Section titled “List Detections”GET /organizations/{organization_id}/detections?page=1&page_size=50Authorization: Bearer <token>Query Parameters:
| Parameter | Description |
|---|---|
property_id |
Filter by property |
source |
Detection source, repeatable (for example decoy_link, endpoint, bot_scanner, sdk, wordpress_plugin, php_sensor, edge_worker) |
min_unified_score |
Minimum unified score (0-100) |
max_unified_score |
Maximum unified score (0-100) |
threat_category |
Threat category, repeatable |
action |
Action taken, repeatable |
ip_address |
Exact IP address |
actor_id |
Detections correlated to one actor |
ai_scraper_name |
AI crawler name (for example GPTBot) |
is_test |
true for test detections only, false to hide them |
country |
Country code, repeatable |
is_proxy |
true/false |
is_vpn |
true/false |
is_tor |
true/false |
start_date |
ISO 8601 date |
end_date |
ISO 8601 date |
sort_by |
timestamp (default), unified_score, bot_score |
sort_order |
asc, desc (default) |
The response is { "items": [...], "total", "page", "page_size", "has_more", "next_cursor" }.
Get Detection
Section titled “Get Detection”GET /organizations/{organization_id}/detections/{detection_id}Authorization: Bearer <token>Get Detection Stats
Section titled “Get Detection Stats”GET /organizations/{organization_id}/detections/statsAuthorization: Bearer <token>Get Hourly Stats
Section titled “Get Hourly Stats”GET /organizations/{organization_id}/detections/stats/hourlyAuthorization: Bearer <token>Get Filter Options
Section titled “Get Filter Options”GET /organizations/{organization_id}/detections/filter-optionsAuthorization: Bearer <token>Export Detections
Section titled “Export Detections”GET /organizations/{organization_id}/detections/export?format=csvAuthorization: Bearer <token>Formats: csv (default), json. Respects the same filters as List Detections. limit defaults to 5,000 rows (maximum 10,000).
More Stats Endpoints
Section titled “More Stats Endpoints”GET /organizations/{organization_id}/detections/geoGET /organizations/{organization_id}/detections/stats/rule-executionsGET /organizations/{organization_id}/detections/stats/signalsGET /organizations/{organization_id}/detections/stats/ai-scrapersGET /organizations/{organization_id}/detections/stats/ai-scrapers/by-nameGET /organizations/{organization_id}/detections/stats/llm-referralsGET /organizations/{organization_id}/detections/stats/llm-referrals/by-platformGET /organizations/{organization_id}/detections/stats/llm-referrals/top-pagesGET /organizations/{organization_id}/detections/stats/page-crawlersGET /organizations/{organization_id}/detections/stats/radarGET /organizations/{organization_id}/detections/stats/categoriesGET /organizations/{organization_id}/detections/stats/top-sourcesAuthorization: Bearer <token>llm-referrals/by-platform returns { platform, count, likely } per platform. count is confirmed referrals; likely is the separate likely-referral estimate, never part of count. A platform with only an estimate is listed with count: 0.
Actors
Section titled “Actors”Persistent cross-IP adversary identities. See Actors.
GET /organizations/{organization_id}/actors # list; sort=threat|ip|property|detections|probes|new (default: last seen), filter=returning|secret_probe|impersonator|rotating|enforced|readyGET /organizations/{organization_id}/actors/stats # org summary for the dashboard hero rowGET /organizations/{organization_id}/actors/{actor_id} # actor + IP/UA footprint + recent detectionsAuthorization: Bearer <token>Enforcement
Section titled “Enforcement”The WAF-enforcement pipeline (see Session Clearance). All routes are org-scoped.
POST /organizations/{organization_id}/enforcement/cloudflare/preflight # harmless zone live-testGET /organizations/{organization_id}/enforcement/mode # monitor | enforcePUT /organizations/{organization_id}/enforcement/modeGET /organizations/{organization_id}/enforcement/signatures # active composite signatures (+ pushed count)GET /organizations/{organization_id}/enforcement/denylist # clearance deny-listPOST /organizations/{organization_id}/enforcement/denylistDELETE /organizations/{organization_id}/enforcement/denylist/{device_fp}GET /organizations/{organization_id}/enforcement/routes # token-enforced route scopePOST /organizations/{organization_id}/enforcement/routesDELETE /organizations/{organization_id}/enforcement/routes/{route_id}GET /organizations/{organization_id}/enforcement/allowlist # verified-crawler categoriesPUT /organizations/{organization_id}/enforcement/allowlistGET /organizations/{organization_id}/enforcement/credentials # machine service tokensPOST /organizations/{organization_id}/enforcement/credentialsDELETE /organizations/{organization_id}/enforcement/credentials/{credential_id}GET /organizations/{organization_id}/enforcement/audit # append-only change logAuthorization: Bearer <token>Response Actions
Section titled “Response Actions”WHEN→THEN automations (see Response Actions).
GET /organizations/{organization_id}/response-actionsPOST /organizations/{organization_id}/response-actionsPUT /organizations/{organization_id}/response-actions/{id}DELETE /organizations/{organization_id}/response-actions/{id}Authorization: Bearer <token>MITRE ATT&CK
Section titled “MITRE ATT&CK”List Tactics
Section titled “List Tactics”GET /mitre/tacticsGet Tactic Stats
Section titled “Get Tactic Stats”GET /organizations/{organization_id}/mitre/statsAuthorization: Bearer <token>Integrations
Section titled “Integrations”Cloudflare
Section titled “Cloudflare”Create Integration
Section titled “Create Integration”POST /organizations/{organization_id}/integrations/cloudflareAuthorization: Bearer <token>
{ "api_token": "cloudflare_token", "account_id": "account_id", "zone_id": "zone_id", "zone_name": "example.com"}Slack, Vercel, Datadog, Splunk, AWS WAF, Fastly, and CrowdStrike each have
equivalent org-scoped CRUD + test endpoints under
/organizations/{organization_id}/integrations/{provider}.
Webhooks
Section titled “Webhooks”Create Webhook
Section titled “Create Webhook”POST /organizations/{organization_id}/integrations/webhooksAuthorization: Bearer <token>
{ "name": "My Webhook", "url": "https://example.com/webhook", "on_detection": true, "min_score": 70}Test Webhook
Section titled “Test Webhook”POST /organizations/{organization_id}/integrations/webhooks/{webhook_id}/testAuthorization: Bearer <token>API Keys
Section titled “API Keys”Create API Key
Section titled “Create API Key”POST /organizations/{organization_id}/api-keysAuthorization: Bearer <token>
{ "name": "Production SDK", "scopes": ["detections:read", "detections:write"], "expires_in": 365}Response:
{ "id": "key-uuid", "name": "Production SDK", "api_key": "sk_live_xxxxxxx", "key_prefix": "sk_live_xxx", "scopes": ["detections:read", "detections:write"]}Important: The full
api_keyis only returned once. Store it securely.
List API Keys
Section titled “List API Keys”GET /organizations/{organization_id}/api-keysAuthorization: Bearer <token>Revoke API Key
Section titled “Revoke API Key”DELETE /organizations/{organization_id}/api-keys/{key_id}Authorization: Bearer <token>Billing
Section titled “Billing”Get Plans
Section titled “Get Plans”GET /billing/plansAuthorization: Bearer <token>Create Checkout Session
Section titled “Create Checkout Session”POST /billing/checkout-sessionAuthorization: Bearer <token>
{ "organization_id": "org-uuid", "price_id": "price_xxx", "success_url": "https://app.example.com/billing/success", "cancel_url": "https://app.example.com/billing"}Get Subscription
Section titled “Get Subscription”GET /organizations/{organization_id}/subscriptionAuthorization: Bearer <token>Get Usage
Section titled “Get Usage”GET /organizations/{organization_id}/billing/usageAuthorization: Bearer <token>Ingest & SDK API
Section titled “Ingest & SDK API”These endpoints live on the ingest service (host https://in.webdecoy.com for server-to-server calls, https://ingest.webdecoy.com for the browser tag; the paths below include /api) and are what the SDKs, detection scripts, and edge validators talk to.
Building a sensor for a stack we do not ship one for? The full wire contract (fields, the client signals block, client-IP resolution, and the fail-open behaviour a sensor must implement) is documented in the Sensor Protocol.
POST /api/v1/detect # submit a detection (Authorization: Bearer sk_live_..., scope detections:write)POST /api/v1/detect/public # browser tag only (aid + sid, unauthenticated)POST /api/v1/clearance # mint a wd_clearance token (publishable site key: aid)GET /api/v1/clearance/config # edge-validator configPOST /api/v1/page-serve # page-serve telemetryPOST /api/v1/verify-js # JS-execution verificationGET /api/v1/auth/validate-key # validate an API keyPOST /api/v1/sdk/detect # SDK detection submissionsPOST /api/v1/sdk/violations/batch # SDK rules-engine violation batchesGET /api/v1/sdk/ip/{address}/enrichment # IP enrichment for SDK filter rulesResponse Formats
Section titled “Response Formats”Paginated Response
Section titled “Paginated Response”List endpoints return:
{ "items": [ ... ], "total": 100, "page": 1, "page_size": 50, "has_more": true}Single-resource endpoints return the object itself.
Error Response
Section titled “Error Response”Most errors return:
{ "error": "Error message"}Some routes return a structured error instead:
{ "code": "ERROR_CODE", "message": "Error message"}Common Status Codes
Section titled “Common Status Codes”| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 429 | Rate Limited |
| 500 | Server Error |
Rate Limits
Section titled “Rate Limits”Rate limits apply per client IP to selected routes, not to the whole API. For example, the auth routes allow 10 requests per minute, and the ingest detection routes (/api/v1/detect, /api/v1/detect/public, /api/v1/clearance) allow 100 per minute with a burst of 20. A limited request gets 429 with {"error": "rate limit exceeded"}. No X-RateLimit-* headers are sent.