Ajustes de borde

Ver en Markdown

Consulta y cambia los ajustes de borde de una zona (WAF, origen, TLS, caché, agentes IA…) y la configuración efectiva de un nombre.

En esta página

Los ajustes de borde controlan cómo sirve el borde los nombres con proxy de una zona: modo y nivel del WAF, origen y TLS hacia el origen, HSTS, caché, puerta de acceso, agentes IA, RUM y más. Se aplican a todos los nombres con proxy de la zona, y cada nombre puede redefinirlos en hosts.

OperaciónRuta
Ver los ajustes de bordeGET /v1/orgs/{org}/zones/{zone}/edge
Cambiar los ajustes de bordePATCH /v1/orgs/{org}/zones/{zone}/edge
Ver la configuración efectiva de un nombreGET /v1/orgs/{org}/zones/{zone}/hosts/{host}/effective

Ver los ajustes de borde

GET /v1/orgs/{org}/zones/{zone}/edge

Devuelve los ajustes de borde de la zona (los valores por defecto si nunca se guardaron). La cabecera ETag lleva la versión de configuración actual.

Rol necesario: readonly o superior.

Parámetros

NombreEnTipoObligatorioDescripción
orgrutastring (uuid)SíId de la organización. Cada ruta comprueba que es la del token (si no, 404).
zonerutastring (uuid)SíId de la zona (consulta Listar zonas).

Respuesta

CampoTipoDescripción
zone_idstring (uuid)Id de la zona.
modestringUno de active, log, off. Por defecto active.
waf_levelstringUno de off, low, medium, high. Por defecto medium.
rate_limit_rpmintegerLímite básico por IP y minuto; 0 = desactivado. Por defecto 0. Mínimo 0.
timeout_msintegerPor defecto 0. Mínimo 0.
enable_feedbooleanPor defecto true.
stackstringUno de generic, wordpress, nextjs, static. Por defecto generic.
block_page_modestringUno de nginx, branded, apache, generic, custom. Por defecto branded.
fake_server_headerstringPor defecto "".
block_page_htmlstringComo mucho 262144 caracteres.
access_gateobject
access_gate.enabledbooleanPor defecto false.
access_gate.pathstringPor defecto /.
access_gate.ttl_hoursintegerPor defecto 0. Mínimo 0.
access_gate.emailsarray de stringCorreos que pueden pasar la puerta de acceso.
max_body_mbintegerPor defecto 0. Mínimo 0.
redirect_allow_hostsarray de string
cors_allow_originsarray de string
hstsobject
hsts.max_ageintegerPor defecto 0. De 0 a 63072000.
hsts.include_subdomainsboolean
hsts.preloadboolean
compressionbooleanPor defecto false.
originobjectupstream_url del sitio = scheme://<contenido del registro>[:port] (IPv6 entre corchetes).
origin.schemestringUno de http, https. Por defecto https.
origin.portinteger0 = el del esquema. Por defecto 0. De 0 a 65535.
origin.tls_verifystringVerificación del certificado de un origen https: full cifra sin verificar; full_strict verifica la cadena (raíces públicas + OpenWAF Origin CA), las fechas, el nombre y la revocación (fallo = 526). Zonas nuevas: full_strict; las anteriores a la función: full. Solo afecta a orígenes https. Uno de full, full_strict.
origin.server_namestringNombre de SNI y de la verificación; vacío = el host del origen (o el dominio del sitio si el origen es una IP). Como mucho 253 caracteres.
origin.client_certbooleanEl borde presenta su certificado de cliente al origen (mTLS). Por defecto false.
hostsHostSettingsMapAjustes propios de algunos nombres de la zona: el sitio de cada nombre usa los de la zona mezclados con los suyos campo a campo. {} sin ninguno (siempre presente en las respuestas). En un PATCH es un JSON merge patch (RFC 7396) por nombre.
redirectsarray de objectReglas de redirección: el borde responde status con Location = target (+ el resto de la ruta tras path_prefix si preserve_path, + la query si preserve_query) sin llegar al origen. Gana el prefijo más largo del nombre. [] sin ninguna (siempre presente en las respuestas). En un PATCH se sustituye entera. El nombre necesita un registro con proxy. Como mucho 50 elementos.
redirects[].hoststringNombre completo de la zona (la zona o por debajo, sin comodín); se pasa a minúsculas.
redirects[].path_prefixstringEmpieza por /; sin ?, #, espacios ni caracteres de control. Se guarda en forma canónica (lo no ASCII y los reservados con %XX en mayúsculas: /año → /a%C3%B1o). /blog casa con /blog y /blog/x, no con /blogging. Por defecto /. Como mucho 1024 caracteres.
redirects[].targetstringURL http(s) absoluta sin credenciales, fragmento ni espacios; puede llevar query. Se guarda con el esquema en minúsculas y lo no ASCII de ruta y query con %XX; el host en ASCII (punycode). No puede apuntar a una ruta que la propia regla captura. Como mucho 2048 caracteres.
redirects[].preserve_pathbooleanPor defecto true.
redirects[].preserve_querybooleanPor defecto true.
redirects[].statusintegerUno de 301, 302, 307, 308. Por defecto 301.
cacheEdgeCacheCaché de respuestas en el borde, desactivada por defecto. En un PATCH es un JSON merge patch: los objetos se mezclan, las listas (rules, query.params) se sustituyen, "dev_mode_until": null apaga el modo desarrollo y "cache": null vuelve a los valores por defecto.
cache.enabledbooleanSin reglas solo son elegibles las extensiones estáticas (nunca HTML ni JSON); se respeta el Cache-Control del origen. El WAF va siempre antes. Por defecto false.
cache.dev_mode_untilstring (date-time) o nullModo desarrollo: hasta entonces no se usa la caché (no se borra nada); null = apagado.
cache.queryCacheQuery
cache.browser_ttlintegerTTL mínimo hacia el navegador en segundos (un max-age mayor del origen gana); 0 = respetar el origen. Por defecto 0. De 0 a 31536000.
cache.deception_armorbooleanNo guardar respuestas cuyo Content-Type no encaja con la extensión. Por defecto true.
cache.serve_staleCacheServeStale
cache.max_object_mbintegerPor defecto 100. De 1 a 512.
cache.rulesarray de EdgeCacheRuleEn orden; si varias coinciden, la última gana en cada ajuste. Como mucho 25 elementos.
early_hintsEdgeEarlyHints103 Early Hints, desactivadas por defecto. En un PATCH es un JSON merge patch: los campos se mezclan, extra_origins se sustituye y "early_hints": null vuelve a los valores por defecto.
early_hints.enabledbooleanResponder con 103 a las navegaciones HTML que van al origen. Por defecto false.
early_hints.modestringDe dónde se aprenden los enlaces: cabeceras Link del origen, los primeros 32 KiB del HTML o ambos. Uno de origin_links, html_head, both. Por defecto both.
early_hints.extra_originsarray de stringOrígenes además del propio del sitio cuyos recursos se pueden anunciar: https://host[:puerto], sin ruta. Se normalizan (espacios, minúsculas, una / final y :443 fuera); repetidos o no https dan 422. Como mucho 10 elementos.
ai_agentsZoneEdgeAIAgents
rumZoneEdgeRUMMedición de usuarios reales de las Core Web Vitals, desactivada por defecto. En un PATCH es un JSON merge patch: los campos dados sustituyen a los actuales (exclude_paths entera), un campo a null vuelve a su valor por defecto y "rum": null al objeto por defecto. Se valida aunque esté desactivada.
rum.enabledbooleanEl borde inyecta /__waf/rum.js en las páginas HTML del sitio y recibe sus balizas en /__waf/rum. Por defecto false.
rum.sample_ratenumberFracción de las páginas vistas que llevan el script, (0, 1]. Por defecto 1. Máximo 1.
rum.exclude_pathsarray de stringPrefijos de ruta que nunca llevan el script (se recortan los espacios; las entradas vacías se descartan). Por defecto []. Como mucho 50 elementos. Elementos con el patrón ^/[^?#]*$.
rate_rulesarray de EdgeRateRuleLímites de peticiones por ruta, en orden de evaluación; ninguno por defecto. En un PATCH la lista se sustituye entera ([] los quita todos). Cada nombre puede tener su propia lista en hosts.<nombre>.rate_rules. Como mucho 25 elementos.
updated_atstring (date-time)Último cambio.

Cabeceras de la respuesta: ETag.

Errores

EstadoDescripción
404No existe o el token no lo ve (not_found).

Ejemplo

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/edge" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "mode": "active",
  "waf_level": "medium",
  "rate_limit_rpm": 0,
  "timeout_ms": 0,
  "enable_feed": true,
  "stack": "generic",
  "block_page_mode": "branded",
  "fake_server_header": "",
  "block_page_html": "",
  "access_gate": {
    "enabled": false,
    "path": "/checkout",
    "ttl_hours": 0,
    "emails": [
      "[email protected]"
    ]
  },
  "max_body_mb": 0,
  "redirect_allow_hosts": [
    "www.example.com"
  ],
  "cors_allow_origins": [
    "https://app.example.com"
  ],
  "hsts": {
    "max_age": 0,
    "include_subdomains": false,
    "preload": false
  },
  "compression": false,
  "origin": {
    "scheme": "https",
    "port": 0,
    "tls_verify": "full",
    "server_name": "",
    "client_cert": false
  },
  "hosts": {},
  "redirects": [
    {
      "host": "www.example.com",
      "path_prefix": "/api/",
      "target": "https://www.example.com/new",
      "preserve_path": true,
      "preserve_query": true,
      "status": 301
    }
  ],
  "cache": {
    "enabled": false,
    "dev_mode_until": "2026-10-27T09:30:00Z",
    "query": {
      "mode": "all",
      "sort": false,
      "params": [
        "example"
      ]
    },
    "browser_ttl": 0,
    "deception_armor": true,
    "serve_stale": {
      "while_revalidate": true,
      "on_error_max_s": 86400
    },
    "max_object_mb": 100,
    "rules": [
      {
        "id": "example",
        "hosts": [],
        "match": {},
        "action": "block",
        "edge_ttl": {},
        "browser_ttl": {},
        "query": {},
        "serve_stale": {},
        "vary_bypass_if_present": []
      }
    ]
  },
  "early_hints": {
    "enabled": false,
    "mode": "both",
    "extra_origins": [
      "https://cdn.example.com"
    ]
  },
  "ai_agents": {
    "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": {}
      }
    ]
  },
  "rum": {
    "enabled": false,
    "sample_rate": 1,
    "exclude_paths": []
  },
  "rate_rules": [
    {
      "id": "example",
      "name": "example.com",
      "enabled": true,
      "hosts": [
        "www.example.com"
      ],
      "path_prefix": "/auth/login",
      "path_exact": "/login",
      "methods": [
        "POST"
      ],
      "header_present": "X-Api-Key",
      "query_present": "example",
      "key": "/pricing",
      "key_name": "X-Api-Key",
      "requests": 128,
      "period": 1,
      "algorithm": "sliding_window",
      "action": "block",
      "mitigation_timeout": 0,
      "per_node_divisor": true
    }
  ],
  "updated_at": "2026-10-27T09:30:00Z"
}

Cambiar los ajustes de borde

PATCH /v1/orgs/{org}/zones/{zone}/edge

Cambia cualquier subconjunto de los ajustes de borde. Los objetos anidados (access_gate, hsts, origin…) se mezclan campo a campo y las listas se sustituyen. Los ajustes se aplican a todos los nombres con proxy de la zona, salvo lo que cada nombre redefina en hosts.

hosts es un JSON merge patch (RFC 7396) por nombre: {"hosts": {"tienda.example.com": {"stack": "nextjs"}}} se mezcla con los ajustes propios de ese nombre; null en un nombre quita los suyos, null en una clave la devuelve al valor de la zona (también anidada, p. ej. "access_gate": {"enabled": null}), y "hosts": null los quita todos. Los nombres se pasan a minúsculas sin punto final, deben ser la zona o estar por debajo, y caben 100. Un nombre sin registro con proxy se admite con un aviso (el borde no lo sirve).

Rol necesario: tech o superior.

Controles de cambio: dry_run · If-Match (opcional) · X-Change-Reason (obligatorio)

Parámetros

NombreEnTipoObligatorioDescripción
orgrutastring (uuid)SíId de la organización. Cada ruta comprueba que es la del token (si no, 404).
zonerutastring (uuid)SíId de la zona (consulta Listar zonas).
X-Change-ReasoncabecerastringSíMotivo del cambio: 1-500 caracteres UTF-8 tras recortar espacios, sin caracteres de control. Si falta o no es válido: 422 reason_required. De 1 a 500 caracteres.
If-MatchcabecerastringNoVersión de configuración esperada, p. ej. "12" (se admite W/). Si no es la actual: 412 version_conflict.
dry_runconsultastringNo1/true simula el cambio: responde 200 con el plan (Applied) y no guarda nada. Admite 0/false; otro valor: 400. Uno de 1, true, 0, false.

Cuerpo de la petición

Tipo de contenido application/json. Esquema: ZoneEdgeSettings.

CampoTipoObligatorioDescripción
zone_idstring (uuid)NoId de la zona.
modestringNoUno de active, log, off. Por defecto active.
waf_levelstringNoUno de off, low, medium, high. Por defecto medium.
rate_limit_rpmintegerNoLímite básico por IP y minuto; 0 = desactivado. Por defecto 0. Mínimo 0.
timeout_msintegerNoPor defecto 0. Mínimo 0.
enable_feedbooleanNoPor defecto true.
stackstringNoUno de generic, wordpress, nextjs, static. Por defecto generic.
block_page_modestringNoUno de nginx, branded, apache, generic, custom. Por defecto branded.
fake_server_headerstringNoPor defecto "".
block_page_htmlstringNoComo mucho 262144 caracteres.
access_gateobjectNo
access_gate.enabledbooleanNoPor defecto false.
access_gate.pathstringNoPor defecto /.
access_gate.ttl_hoursintegerNoPor defecto 0. Mínimo 0.
access_gate.emailsarray de stringNoCorreos que pueden pasar la puerta de acceso.
max_body_mbintegerNoPor defecto 0. Mínimo 0.
redirect_allow_hostsarray de stringNo
cors_allow_originsarray de stringNo
hstsobjectNo
hsts.max_ageintegerNoPor defecto 0. De 0 a 63072000.
hsts.include_subdomainsbooleanNo
hsts.preloadbooleanNo
compressionbooleanNoPor defecto false.
originobjectNoupstream_url del sitio = scheme://<contenido del registro>[:port] (IPv6 entre corchetes).
origin.schemestringNoUno de http, https. Por defecto https.
origin.portintegerNo0 = el del esquema. Por defecto 0. De 0 a 65535.
origin.tls_verifystringNoVerificación del certificado de un origen https: full cifra sin verificar; full_strict verifica la cadena (raíces públicas + OpenWAF Origin CA), las fechas, el nombre y la revocación (fallo = 526). Zonas nuevas: full_strict; las anteriores a la función: full. Solo afecta a orígenes https. Uno de full, full_strict.
origin.server_namestringNoNombre de SNI y de la verificación; vacío = el host del origen (o el dominio del sitio si el origen es una IP). Como mucho 253 caracteres.
origin.client_certbooleanNoEl borde presenta su certificado de cliente al origen (mTLS). Por defecto false.
hostsHostSettingsMapNoAjustes propios de algunos nombres de la zona: el sitio de cada nombre usa los de la zona mezclados con los suyos campo a campo. {} sin ninguno (siempre presente en las respuestas). En un PATCH es un JSON merge patch (RFC 7396) por nombre.
redirectsarray de objectNoReglas de redirección: el borde responde status con Location = target (+ el resto de la ruta tras path_prefix si preserve_path, + la query si preserve_query) sin llegar al origen. Gana el prefijo más largo del nombre. [] sin ninguna (siempre presente en las respuestas). En un PATCH se sustituye entera. El nombre necesita un registro con proxy. Como mucho 50 elementos.
redirects[].hoststringSíNombre completo de la zona (la zona o por debajo, sin comodín); se pasa a minúsculas.
redirects[].path_prefixstringNoEmpieza por /; sin ?, #, espacios ni caracteres de control. Se guarda en forma canónica (lo no ASCII y los reservados con %XX en mayúsculas: /año → /a%C3%B1o). /blog casa con /blog y /blog/x, no con /blogging. Por defecto /. Como mucho 1024 caracteres.
redirects[].targetstringSíURL http(s) absoluta sin credenciales, fragmento ni espacios; puede llevar query. Se guarda con el esquema en minúsculas y lo no ASCII de ruta y query con %XX; el host en ASCII (punycode). No puede apuntar a una ruta que la propia regla captura. Como mucho 2048 caracteres.
redirects[].preserve_pathbooleanNoPor defecto true.
redirects[].preserve_querybooleanNoPor defecto true.
redirects[].statusintegerNoUno de 301, 302, 307, 308. Por defecto 301.
cacheEdgeCacheNoCaché de respuestas en el borde, desactivada por defecto. En un PATCH es un JSON merge patch: los objetos se mezclan, las listas (rules, query.params) se sustituyen, "dev_mode_until": null apaga el modo desarrollo y "cache": null vuelve a los valores por defecto.
cache.enabledbooleanNoSin reglas solo son elegibles las extensiones estáticas (nunca HTML ni JSON); se respeta el Cache-Control del origen. El WAF va siempre antes. Por defecto false.
cache.dev_mode_untilstring (date-time) o nullNoModo desarrollo: hasta entonces no se usa la caché (no se borra nada); null = apagado.
cache.queryCacheQueryNo
cache.query.modestringSíall: la query entera (Standard); ignore: sin query en la clave (solo extensiones estáticas); none: solo se usa la caché sin query; include/exclude: solo/todos menos params. Uno de all, ignore, none, include, exclude.
cache.query.sortbooleanNoPor defecto false.
cache.query.paramsarray de stringNoNombres de parámetro (include/exclude); un * final casa por prefijo (utm_*). Como mucho 32 elementos.
cache.browser_ttlintegerNoTTL mínimo hacia el navegador en segundos (un max-age mayor del origen gana); 0 = respetar el origen. Por defecto 0. De 0 a 31536000.
cache.deception_armorbooleanNoNo guardar respuestas cuyo Content-Type no encaja con la extensión. Por defecto true.
cache.serve_staleCacheServeStaleNo
cache.serve_stale.while_revalidatebooleanNoServir caducado (UPDATING) mientras se revalida en segundo plano. Por defecto true.
cache.serve_stale.on_error_max_sintegerNoSegundos tras caducar en que se sirve caducado si el origen falla (0 = nunca). Por defecto 86400. De 0 a 2592000.
cache.max_object_mbintegerNoPor defecto 100. De 1 a 512.
cache.rulesarray de EdgeCacheRuleNoEn orden; si varias coinciden, la última gana en cada ajuste. Como mucho 25 elementos.
cache.rules[].idstringNoÚnico; por defecto r1, r2…. Patrón ^[A-Za-z0-9_-]{1,64}$.
cache.rules[].hostsarray de stringNoNombres de la zona a los que se aplica (vacío = todos; no se admite en la lista propia de un nombre).
cache.rules[].matchobjectNoCasan todas las listas presentes y, dentro de cada una, cualquier valor; sin listas casa con todo (solo GET y HEAD).
cache.rules[].match.path_prefixarray de stringNoLa ruta empieza por el valor (forma canónica). Como mucho 32 elementos.
cache.rules[].match.path_exactarray de stringNoComo mucho 32 elementos.
cache.rules[].match.extensionsarray de stringNoSin punto, minúsculas; "" = sin extensión. Como mucho 32 elementos.
cache.rules[].match.cookie_presentarray de stringNoNombre de cookie; un * final casa por prefijo. Como mucho 32 elementos.
cache.rules[].match.query_presentarray de stringNoLa query trae un parámetro con ese nombre (decodificado); un * final casa por prefijo. Como mucho 32 elementos.
cache.rules[].actionstringSíbypass: nunca cachear (sin más parámetros); cache: elegible aunque la extensión no sea estática. Uno de bypass, cache.
cache.rules[].edge_ttlobjectNo
cache.rules[].edge_ttl.modestringNooverride ignora el CC del origen, quita Set-Cookie y desactiva la armadura anti-engaño. Uno de respect_origin, bypass_by_default, override.
cache.rules[].edge_ttl.ttl_sintegerNoSolo con override (1..31536000). De 0 a 31536000.
cache.rules[].edge_ttl.statusarray de objectNoComo mucho 10 elementos.
cache.rules[].edge_ttl.status[].fromintegerNoDe 100 a 599.
cache.rules[].edge_ttl.status[].tointegerNoDe 100 a 599.
cache.rules[].edge_ttl.status[].ttl_sintegerNo-1 = no guardar; 0 = guardar y revalidar siempre. De -1 a 31536000.
cache.rules[].browser_ttlobjectNo
cache.rules[].browser_ttl.modestringNoUno de respect_origin, override.
cache.rules[].browser_ttl.ttl_sintegerNoDe 0 a 31536000.
cache.rules[].queryCacheQueryNo
cache.rules[].query.modestringSíall: la query entera (Standard); ignore: sin query en la clave (solo extensiones estáticas); none: solo se usa la caché sin query; include/exclude: solo/todos menos params. Uno de all, ignore, none, include, exclude.
cache.rules[].query.sortbooleanNoPor defecto false.
cache.rules[].query.paramsarray de stringNoNombres de parámetro (include/exclude); un * final casa por prefijo (utm_*). Como mucho 32 elementos.
cache.rules[].serve_staleCacheServeStaleNo
cache.rules[].serve_stale.while_revalidatebooleanNoServir caducado (UPDATING) mientras se revalida en segundo plano. Por defecto true.
cache.rules[].serve_stale.on_error_max_sintegerNoSegundos tras caducar en que se sirve caducado si el origen falla (0 = nunca). Por defecto 86400. De 0 a 2592000.
cache.rules[].vary_bypass_if_presentarray de stringNoSolo con cache. Cabeceras de petición (se guardan en minúsculas; no accept-encoding, accept ni origin): una petición que trae alguna ni se busca ni se guarda (DYNAMIC); el Vary del origen puede listarlas sin provocar BYPASS. Cambiar la lista vuelve a claves nuevas la caché del nombre. Como mucho 32 elementos.
early_hintsEdgeEarlyHintsNo103 Early Hints, desactivadas por defecto. En un PATCH es un JSON merge patch: los campos se mezclan, extra_origins se sustituye y "early_hints": null vuelve a los valores por defecto.
early_hints.enabledbooleanNoResponder con 103 a las navegaciones HTML que van al origen. Por defecto false.
early_hints.modestringNoDe dónde se aprenden los enlaces: cabeceras Link del origen, los primeros 32 KiB del HTML o ambos. Uno de origin_links, html_head, both. Por defecto both.
early_hints.extra_originsarray de stringNoOrígenes además del propio del sitio cuyos recursos se pueden anunciar: https://host[:puerto], sin ruta. Se normalizan (espacios, minúsculas, una / final y :443 fuera); repetidos o no https dan 422. Como mucho 10 elementos.
ai_agentsZoneEdgeAIAgentsNo
ai_agents.enabledbooleanNoPor defecto false.
ai_agents.modestringNolog: solo cuenta lo que haría (enforced=false). Uno de log, enforce. Por defecto log.
ai_agents.spoofed_challengestringNoenforce: solo los rastreadores verificados se saltan el reto PoW. Uno de log, enforce. Por defecto log.
ai_agents.templatestringNoUno de search_ok_block_training, verified_only, block_unverified_automation.
ai_agents.policyobjectNo
ai_agents.policy.ai_trainingstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.ai_searchstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.ai_user_agentstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.search_enginestringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.unverified_automationstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.spoofedstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.unverified_botstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.trap_hitstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.secret_probestringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.robots_violationstringNoUno de allow, log, challenge, block, tarpit.
ai_agents.policy.agent_burststringNoUno de allow, log, challenge, block, tarpit.
ai_agents.bot_overridesarray de objectNoComo mucho 100 elementos.
ai_agents.bot_overrides[].bot_idstringSí
ai_agents.bot_overrides[].actionstringSíUno de allow, log, challenge, block, tarpit.
ai_agents.trapobjectNoEnlace trampa; la clave HMAC de la zona se genera al publicar y nunca sale por la API.
ai_agents.trap.enabledbooleanNo
ai_agents.tarpitobjectNo
ai_agents.tarpit.enabledbooleanNo
ai_agents.robotsobjectNo
ai_agents.robots.enabledbooleanNo
ai_agents.robots.content_signalsobjectNo
ai_agents.robots.content_signals.searchstringNoUno de yes, no, "".
ai_agents.robots.content_signals.ai_inputstringNoUno de yes, no, "".
ai_agents.robots.content_signals.ai_trainstringNoUno de yes, no, "".
ai_agents.markdownobjectNo
ai_agents.markdown.enabledbooleanNo
ai_agents.block_responseobjectNo
ai_agents.block_response.statusintegerNoUno de 401, 402, 403, 404, 410, 429, 451, 503. Por defecto 403.
ai_agents.block_response.messagestringNoComo mucho 1024 caracteres.
ai_agents.endpointsarray de objectNoComo mucho 20 elementos.
ai_agents.endpoints[].path_prefixstringNoComo mucho 256 caracteres. Patrón ^/.
ai_agents.endpoints[].methodsarray de stringNoPOST, PUT, PATCH, GET; con kind mcp, POST, GET y DELETE (con POST; vacío = los tres).
ai_agents.endpoints[].max_body_bytesintegerNo1-1048576; 0 con kind mcp. De 0 a 1048576.
ai_agents.endpoints[].rpm_per_ipintegerNoDe 0 a 100000.
ai_agents.endpoints[].rpm_per_sessionintegerNoDe 0 a 100000.
ai_agents.endpoints[].session_headerstringNo
ai_agents.endpoints[].session_cookiestringNo
ai_agents.endpoints[].injection_actionstringNoVacío con kind mcp. Uno de log, block, "".
ai_agents.endpoints[].limit_actionstringNoVacío con kind mcp. Uno de log, block, "".
ai_agents.endpoints[].kindstringNoAusente = endpoint de IA; mcp = servidor MCP protegido por MCP Shield (los campos de endpoint de IA a 0 o vacíos). Uno de mcp.
ai_agents.endpoints[].mcpAiMcpPolicyNo
ai_agents.endpoints[].mcp.methods_allowedarray de stringNoMétodos JSON-RPC exactos o prefijos x/; por defecto initialize, ping, notifications/, tools/list, tools/call, resources/list, resources/read, resources/templates/list, prompts/list, prompts/get, completion/complete, logging/setLevel. De 1 a 64 elementos. Elementos con el patrón ^[A-Za-z0-9_.-]+(/[A-Za-z0-9_.-]+)*(/\*)?$.
ai_agents.endpoints[].mcp.tools_allowedarray de stringNo[] = cualquier tool no denegada. Como mucho 200 elementos. Elementos con el patrón ^[A-Za-z0-9_.:/-]{1,128}$.
ai_agents.endpoints[].mcp.tools_deniedarray de stringNoComo mucho 200 elementos. Elementos con el patrón ^[A-Za-z0-9_.:/-]{1,128}$.
ai_agents.endpoints[].mcp.max_request_kbintegerNoPor defecto 256. De 1 a 1024.
ai_agents.endpoints[].mcp.inspect_requestsstringNoUno de off, log, block. Por defecto log.
ai_agents.endpoints[].mcp.inspect_responsesstringNoUno de off, log, block. Por defecto log.
ai_agents.endpoints[].mcp.rate_per_tokenintegerNoPeticiones por minuto por token (Authorization); 0 = sin límite. Por defecto 0. De 0 a 100000.
rumZoneEdgeRUMNoMedición de usuarios reales de las Core Web Vitals, desactivada por defecto. En un PATCH es un JSON merge patch: los campos dados sustituyen a los actuales (exclude_paths entera), un campo a null vuelve a su valor por defecto y "rum": null al objeto por defecto. Se valida aunque esté desactivada.
rum.enabledbooleanNoEl borde inyecta /__waf/rum.js en las páginas HTML del sitio y recibe sus balizas en /__waf/rum. Por defecto false.
rum.sample_ratenumberNoFracción de las páginas vistas que llevan el script, (0, 1]. Por defecto 1. Máximo 1.
rum.exclude_pathsarray de stringNoPrefijos de ruta que nunca llevan el script (se recortan los espacios; las entradas vacías se descartan). Por defecto []. Como mucho 50 elementos. Elementos con el patrón ^/[^?#]*$.
rate_rulesarray de EdgeRateRuleNoLímites de peticiones por ruta, en orden de evaluación; ninguno por defecto. En un PATCH la lista se sustituye entera ([] los quita todos). Cada nombre puede tener su propia lista en hosts.<nombre>.rate_rules. Como mucho 25 elementos.
rate_rules[].idstringNoÚnico en la lista; vacío = derivado del nombre (login, login-2…). Los eventos lo llevan como rule_name rate_rule:<id>. Patrón ^[a-z0-9][a-z0-9-]{0,39}$.
rate_rules[].namestringNoNombre. Como mucho 100 caracteres.
rate_rules[].enabledbooleanNoPor defecto true.
rate_rules[].hostsarray de stringNoNombres de la zona a los que se aplica; [] = todos (siempre [] en la lista de un nombre).
rate_rules[].path_prefixstringNoRutas que empiezan por él en un límite de segmento; / = todas. Se guarda en minúsculas, sin / final. Como mucho 512 caracteres.
rate_rules[].path_exactstringNoSolo esta ruta (una / final no cuenta). Se guarda en minúsculas. Como mucho 512 caracteres.
rate_rules[].methodsarray de stringNoMétodos; [] = cualquiera. Por defecto []. Como mucho 16 elementos.
rate_rules[].header_presentstringNoSolo si la petición lleva esta cabecera. Como mucho 64 caracteres.
rate_rules[].query_presentstringNoSolo si la petición lleva este parámetro. Como mucho 64 caracteres.
rate_rules[].keystringNoQué se cuenta: IP (IPv6 por /64), cabecera, cookie o campo del cuerpo JSON (sin valor, se cuenta por IP). Uno de ip, header, cookie, body_field. Por defecto ip.
rate_rules[].key_namestringNoCabecera, cookie o ruta del campo JSON (a.b, hasta 4 niveles); vacío con ip. Como mucho 64 caracteres.
rate_rules[].requestsintegerSíPeticiones. De 1 a 1000000.
rate_rules[].periodintegerSíSegundos. De 1 a 86400.
rate_rules[].algorithmstringNoUno de sliding_window, gcra. Por defecto sliding_window.
rate_rules[].actionstringNoUno de block, challenge, log. Por defecto block.
rate_rules[].mitigation_timeoutintegerNoSegundos que la acción sigue aplicándose a la clave tras pasarse; 0 = solo mientras se pasa. Por defecto 0. De 0 a 86400.
rate_rules[].per_node_divisorbooleanNoDividir requests entre los puntos de entrada del borde que sirven el sitio, para que el límite se aplique al total. Por defecto true.
updated_atstring (date-time)NoÚltimo cambio.

Respuesta

  • 200: Ajustes guardados (con X-Config-Version y ETag) o, con dry_run, el plan (Applied). Devuelve ZoneEdgeSettings o Applied.
CampoTipoDescripción
zone_idstring (uuid)Id de la zona.
modestringUno de active, log, off. Por defecto active.
waf_levelstringUno de off, low, medium, high. Por defecto medium.
rate_limit_rpmintegerLímite básico por IP y minuto; 0 = desactivado. Por defecto 0. Mínimo 0.
timeout_msintegerPor defecto 0. Mínimo 0.
enable_feedbooleanPor defecto true.
stackstringUno de generic, wordpress, nextjs, static. Por defecto generic.
block_page_modestringUno de nginx, branded, apache, generic, custom. Por defecto branded.
fake_server_headerstringPor defecto "".
block_page_htmlstringComo mucho 262144 caracteres.
access_gateobject
access_gate.enabledbooleanPor defecto false.
access_gate.pathstringPor defecto /.
access_gate.ttl_hoursintegerPor defecto 0. Mínimo 0.
access_gate.emailsarray de stringCorreos que pueden pasar la puerta de acceso.
max_body_mbintegerPor defecto 0. Mínimo 0.
redirect_allow_hostsarray de string
cors_allow_originsarray de string
hstsobject
hsts.max_ageintegerPor defecto 0. De 0 a 63072000.
hsts.include_subdomainsboolean
hsts.preloadboolean
compressionbooleanPor defecto false.
originobjectupstream_url del sitio = scheme://<contenido del registro>[:port] (IPv6 entre corchetes).
origin.schemestringUno de http, https. Por defecto https.
origin.portinteger0 = el del esquema. Por defecto 0. De 0 a 65535.
origin.tls_verifystringVerificación del certificado de un origen https: full cifra sin verificar; full_strict verifica la cadena (raíces públicas + OpenWAF Origin CA), las fechas, el nombre y la revocación (fallo = 526). Zonas nuevas: full_strict; las anteriores a la función: full. Solo afecta a orígenes https. Uno de full, full_strict.
origin.server_namestringNombre de SNI y de la verificación; vacío = el host del origen (o el dominio del sitio si el origen es una IP). Como mucho 253 caracteres.
origin.client_certbooleanEl borde presenta su certificado de cliente al origen (mTLS). Por defecto false.
hostsHostSettingsMapAjustes propios de algunos nombres de la zona: el sitio de cada nombre usa los de la zona mezclados con los suyos campo a campo. {} sin ninguno (siempre presente en las respuestas). En un PATCH es un JSON merge patch (RFC 7396) por nombre.
redirectsarray de objectReglas de redirección: el borde responde status con Location = target (+ el resto de la ruta tras path_prefix si preserve_path, + la query si preserve_query) sin llegar al origen. Gana el prefijo más largo del nombre. [] sin ninguna (siempre presente en las respuestas). En un PATCH se sustituye entera. El nombre necesita un registro con proxy. Como mucho 50 elementos.
redirects[].hoststringNombre completo de la zona (la zona o por debajo, sin comodín); se pasa a minúsculas.
redirects[].path_prefixstringEmpieza por /; sin ?, #, espacios ni caracteres de control. Se guarda en forma canónica (lo no ASCII y los reservados con %XX en mayúsculas: /año → /a%C3%B1o). /blog casa con /blog y /blog/x, no con /blogging. Por defecto /. Como mucho 1024 caracteres.
redirects[].targetstringURL http(s) absoluta sin credenciales, fragmento ni espacios; puede llevar query. Se guarda con el esquema en minúsculas y lo no ASCII de ruta y query con %XX; el host en ASCII (punycode). No puede apuntar a una ruta que la propia regla captura. Como mucho 2048 caracteres.
redirects[].preserve_pathbooleanPor defecto true.
redirects[].preserve_querybooleanPor defecto true.
redirects[].statusintegerUno de 301, 302, 307, 308. Por defecto 301.
cacheEdgeCacheCaché de respuestas en el borde, desactivada por defecto. En un PATCH es un JSON merge patch: los objetos se mezclan, las listas (rules, query.params) se sustituyen, "dev_mode_until": null apaga el modo desarrollo y "cache": null vuelve a los valores por defecto.
cache.enabledbooleanSin reglas solo son elegibles las extensiones estáticas (nunca HTML ni JSON); se respeta el Cache-Control del origen. El WAF va siempre antes. Por defecto false.
cache.dev_mode_untilstring (date-time) o nullModo desarrollo: hasta entonces no se usa la caché (no se borra nada); null = apagado.
cache.queryCacheQuery
cache.browser_ttlintegerTTL mínimo hacia el navegador en segundos (un max-age mayor del origen gana); 0 = respetar el origen. Por defecto 0. De 0 a 31536000.
cache.deception_armorbooleanNo guardar respuestas cuyo Content-Type no encaja con la extensión. Por defecto true.
cache.serve_staleCacheServeStale
cache.max_object_mbintegerPor defecto 100. De 1 a 512.
cache.rulesarray de EdgeCacheRuleEn orden; si varias coinciden, la última gana en cada ajuste. Como mucho 25 elementos.
early_hintsEdgeEarlyHints103 Early Hints, desactivadas por defecto. En un PATCH es un JSON merge patch: los campos se mezclan, extra_origins se sustituye y "early_hints": null vuelve a los valores por defecto.
early_hints.enabledbooleanResponder con 103 a las navegaciones HTML que van al origen. Por defecto false.
early_hints.modestringDe dónde se aprenden los enlaces: cabeceras Link del origen, los primeros 32 KiB del HTML o ambos. Uno de origin_links, html_head, both. Por defecto both.
early_hints.extra_originsarray de stringOrígenes además del propio del sitio cuyos recursos se pueden anunciar: https://host[:puerto], sin ruta. Se normalizan (espacios, minúsculas, una / final y :443 fuera); repetidos o no https dan 422. Como mucho 10 elementos.
ai_agentsZoneEdgeAIAgents
rumZoneEdgeRUMMedición de usuarios reales de las Core Web Vitals, desactivada por defecto. En un PATCH es un JSON merge patch: los campos dados sustituyen a los actuales (exclude_paths entera), un campo a null vuelve a su valor por defecto y "rum": null al objeto por defecto. Se valida aunque esté desactivada.
rum.enabledbooleanEl borde inyecta /__waf/rum.js en las páginas HTML del sitio y recibe sus balizas en /__waf/rum. Por defecto false.
rum.sample_ratenumberFracción de las páginas vistas que llevan el script, (0, 1]. Por defecto 1. Máximo 1.
rum.exclude_pathsarray de stringPrefijos de ruta que nunca llevan el script (se recortan los espacios; las entradas vacías se descartan). Por defecto []. Como mucho 50 elementos. Elementos con el patrón ^/[^?#]*$.
rate_rulesarray de EdgeRateRuleLímites de peticiones por ruta, en orden de evaluación; ninguno por defecto. En un PATCH la lista se sustituye entera ([] los quita todos). Cada nombre puede tener su propia lista en hosts.<nombre>.rate_rules. Como mucho 25 elementos.
updated_atstring (date-time)Último cambio.

Cabeceras de la respuesta: ETag, X-Config-Version.

Errores

EstadoDescripción
400Petición mal formada (bad_request).
409zone_merged: la zona está fusionada en otra.
412version_conflict: If-Match no coincide con la versión actual.
422Error de validación (invalid) o motivo ausente/no válido (reason_required).

Ejemplo

curl -X PATCH "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/edge" \
  -H "Authorization: Bearer $OPENWAF_TOKEN" \
  -H "X-Change-Reason: Enable the WAF in block mode" \
  -H 'If-Match: "12"' \
  -H "Content-Type: application/json" \
  --data '{
    "mode": "active",
    "waf_level": "high",
    "hsts": {
      "max_age": 31536000,
      "include_subdomains": true
    }
  }'
200
{
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "mode": "active",
  "waf_level": "medium",
  "rate_limit_rpm": 0,
  "timeout_ms": 0,
  "enable_feed": true,
  "stack": "generic",
  "block_page_mode": "branded",
  "fake_server_header": "",
  "block_page_html": "",
  "access_gate": {
    "enabled": false,
    "path": "/checkout",
    "ttl_hours": 0,
    "emails": [
      "[email protected]"
    ]
  },
  "max_body_mb": 0,
  "redirect_allow_hosts": [
    "www.example.com"
  ],
  "cors_allow_origins": [
    "https://app.example.com"
  ],
  "hsts": {
    "max_age": 0,
    "include_subdomains": false,
    "preload": false
  },
  "compression": false,
  "origin": {
    "scheme": "https",
    "port": 0,
    "tls_verify": "full",
    "server_name": "",
    "client_cert": false
  },
  "hosts": {},
  "redirects": [
    {
      "host": "www.example.com",
      "path_prefix": "/api/",
      "target": "https://www.example.com/new",
      "preserve_path": true,
      "preserve_query": true,
      "status": 301
    }
  ],
  "cache": {
    "enabled": false,
    "dev_mode_until": "2026-10-27T09:30:00Z",
    "query": {
      "mode": "all",
      "sort": false,
      "params": [
        "example"
      ]
    },
    "browser_ttl": 0,
    "deception_armor": true,
    "serve_stale": {
      "while_revalidate": true,
      "on_error_max_s": 86400
    },
    "max_object_mb": 100,
    "rules": [
      {
        "id": "example",
        "hosts": [],
        "match": {},
        "action": "block",
        "edge_ttl": {},
        "browser_ttl": {},
        "query": {},
        "serve_stale": {},
        "vary_bypass_if_present": []
      }
    ]
  },
  "early_hints": {
    "enabled": false,
    "mode": "both",
    "extra_origins": [
      "https://cdn.example.com"
    ]
  },
  "ai_agents": {
    "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": {}
      }
    ]
  },
  "rum": {
    "enabled": false,
    "sample_rate": 1,
    "exclude_paths": []
  },
  "rate_rules": [
    {
      "id": "example",
      "name": "example.com",
      "enabled": true,
      "hosts": [
        "www.example.com"
      ],
      "path_prefix": "/auth/login",
      "path_exact": "/login",
      "methods": [
        "POST"
      ],
      "header_present": "X-Api-Key",
      "query_present": "example",
      "key": "/pricing",
      "key_name": "X-Api-Key",
      "requests": 128,
      "period": 1,
      "algorithm": "sliding_window",
      "action": "block",
      "mitigation_timeout": 0,
      "per_node_divisor": true
    }
  ],
  "updated_at": "2026-10-27T09:30:00Z"
}

Ver la configuración efectiva de un nombre

GET /v1/orgs/{org}/zones/{zone}/hosts/{host}/effective

Muestra la configuración que recibe un nombre de la zona en el borde, tal y como la reciben los nodos, los ajustes de la zona mezclados con los propios del nombre, las reglas que le aplican y sus redirecciones. La cabecera ETag lleva la versión de la zona.

Rol necesario: readonly o superior.

Parámetros

NombreEnTipoObligatorioDescripción
orgrutastring (uuid)SíId de la organización. Cada ruta comprueba que es la del token (si no, 404).
zonerutastring (uuid)SíId de la zona (consulta Listar zonas).
hostrutastringSíNombre completo (la zona o por debajo).

Respuesta

CampoTipoDescripción
zone_idstring (uuid)Id de la zona.
hoststring
proxiedbooleanfalse: el nombre no tiene registro con proxy y site es una vista previa sin upstream_url.
itemsarray de object
items[].siteEdgeSite o any o null

Cabeceras de la respuesta: ETag.

Errores

EstadoDescripción
404Zona inexistente o host_not_in_zone: el nombre no es la zona ni está por debajo.
422Error de validación (invalid).

Ejemplo

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/hosts/www.example.com/effective" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "zone_id": "6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d",
  "host": "www.example.com",
  "proxied": false,
  "items": [
    {
      "site": {
        "id": 0,
        "hostname": "www.example.com",
        "upstream_url": "https://203.0.113.10",
        "rules": [],
        "redirects": [],
        "cache": {},
        "early_hints": {},
        "rum": {},
        "rate_rules": []
      }
    }
  ]
}

Última actualización:

↑↓ para moverte↵ para abriresc para cerrar