Skip to content

Shield (WAF, DDoS & Bots)

Per-site web application firewall, DDoS mitigation, and bot detection, backed by Bunny Shield.

Plan-gated. Every Shield endpoint returns 403 shield_not_in_plan when the site's product does not include Shield. Premium-only writes (bot detection update, custom WAF rule create) return 403 shield_premium_required on a non-premium plan. Reads that need a provisioned shield zone return 409 shield_not_active. OAuth scopes: reads sites:read, writes sites:write (deletes need can_destroy). Upstream Bunny errors return 502.


Shield Zone

Get Shield Config

GET /api/sites/:site_id/shield

Returns 409 shield_not_active if the shield zone isn't provisioned.

Returned Params
  • active: Boolean
  • plan: String | basic, advanced, business, enterprise
  • waf: Object | WAF settings
  • ddos: Object | DDoS settings
  • whitelabel_response_pages: Boolean

Activate Shield

POST /api/sites/:site_id/shield

Creates the shield zone. Returns 201. Returns 409 cdn_not_active if there is no pull zone to attach to.

Update Shield

PATCH /api/sites/:site_id/shield

Params (all optional)
  • plan_type: Integer | 0=basic, 1=advanced, 2=business, 3=enterprise
  • premium: Boolean | back-compat alias for plan_type (true=1, false=0)
  • learning_mode: Boolean
  • waf_enabled: Boolean
  • waf_execution_mode: Integer
  • waf_disabled_rules: Array<String> | ruleId strings
  • waf_log_only_rules: Array<String> | ruleId strings
  • ddos_sensitivity: Integer
  • ddos_execution_mode: Integer
  • ddos_challenge_window: Integer
  • whitelabel_response_pages: Boolean

Deactivate Shield

DELETE /api/sites/:site_id/shield

Soft deactivate — disables WAF and DDoS.


WAF

Get WAF Config

GET /api/sites/:site_id/shield/waf

Update WAF Config

PATCH /api/sites/:site_id/shield/waf

Params (all optional)
  • waf_enabled: Boolean
  • waf_execution_mode: Integer | 0=Log, 1=Block
  • waf_disabled_rules: Array<String> | ruleId strings
  • waf_log_only_rules: Array<String> | ruleId strings

List Managed WAF Rules

GET /api/sites/:site_id/shield/waf/rules

Returns a bare array of managed WAF rule groups.


Custom WAF Rules

List

GET /api/sites/:site_id/shield/waf_custom_rules

Create

POST /api/sites/:site_id/shield/waf_custom_rules

Premium-only. Returns 201.

Params
  • rule_name: String (required)
  • rule_description: String (optional)
  • rule_configuration: Object
    • action_type: Integer | 1=Block, 2=Log, 3=Challenge, 4=Allow, 5=Bypass
    • variable_type: String | e.g. REQUEST_HEADERS
    • variable_subselector: String | e.g. "User-Agent"
    • operator_type: Integer
    • severity_type: Integer | 0=NOTICE, 1=WARNING, 2=CRITICAL
    • value: String | the match value

Update

PATCH /api/sites/:site_id/shield/waf_custom_rules/:id

Not premium-gated.

Delete

DELETE /api/sites/:site_id/shield/waf_custom_rules/:id

Returns 204. Requires the can_destroy role.


Bot Detection

Get Config

GET /api/sites/:site_id/shield/bot_detection

Update Config

PATCH /api/sites/:site_id/shield/bot_detection

Premium-only (403 shield_premium_required).

Params (all optional)
  • execution_mode: Integer
  • request_integrity_sensitivity: Integer
  • ip_address_sensitivity: Integer
  • browser_fingerprint_sensitivity: Integer
  • browser_fingerprint_aggression: Integer
  • browser_fingerprint_complex_enabled: Boolean

Rate Limits

List

GET /api/sites/:site_id/shield/rate_limits

Create

POST /api/sites/:site_id/shield/rate_limits

Returns 201.

Params
  • rule_name: String | letters, numbers, and spaces only (see below)
  • rule_description: String | same character set as rule_name; may be empty
  • rule_configuration: Object | forwarded verbatim to Bunny's rate-limit rule schema

Name character set

rule_name and rule_description may contain only ASCII letters, numbers, and spaces — Bunny rejects hyphens, underscores, dots, and non-ASCII. An invalid value is caught pre-flight and returns 422 {"error":"Rule name can only contain letters, numbers, and spaces."} (or "Rule description ..."), not a 502 from Bunny.

Update

PATCH /api/sites/:site_id/shield/rate_limits/:id

Same params and name validation as Create.

Delete

DELETE /api/sites/:site_id/shield/rate_limits/:id

Returns 204. Requires the can_destroy role.


Access Lists

List

GET /api/sites/:site_id/shield/access_lists

List Enums

GET /api/sites/:site_id/shield/access_lists/enums

Available access-list type enum values.

View

GET /api/sites/:site_id/shield/access_lists/:id

Create

POST /api/sites/:site_id/shield/access_lists

Returns 201.

Params
  • name: String
  • description: String
  • type: Integer
  • content: String | newline-delimited entries
  • checksum: String

Update

PATCH /api/sites/:site_id/shield/access_lists/:id

Delete

DELETE /api/sites/:site_id/shield/access_lists/:id

Returns 204. Requires the can_destroy role.


Events

GET /api/sites/:site_id/shield/events

Shield WAF/DDoS event log for a given date.

Params
  • date: String | MM-DD-YYYY (defaults to today)
  • continue: String | continuation token for pagination (optional)
Returned Params
  • logs: Array
  • hasMoreData: Boolean
  • continuationToken: String
  • startToken: String

Shield Metrics

These metric endpoints are not plan-gated, but still return 409 shield_not_active when there is no shield zone or the upstream stats payload comes back empty. Scope: sites:read.

Individual Stats

GET /api/sites/:site_id/metrics/shield

Individual DDoS, bot, and WAF stats for the past 28 days.

Returned Params
  • ddos: Array of series | logged, verified, blocked, challenged
  • bots: Array of series | logged, challenged
  • waf: Array of series | triggered events

Each series: { name: String, data: [ { x: "2026-05-01", y: 0 } ] }.

Overview Stats

GET /api/sites/:site_id/metrics/shield/overview

DDoS attacks + WAF triggers for the past 28 days. Returns a bare array of series: [ { name: "DDoS Attacks", data: [...] }, { name: "WAF Triggers", data: [...] } ].