Update Policy Rule

PUT /v1/endpoints/{uuid}/policies/{policy_uuid}/rules/{rule_uuid}

Edit a rule's fields. Updates require the whole-feature traffic_policies entitlement (403 without it) but do not re-check the per-rule-type plan gating — admins on a downgraded plan can keep editing rules of types they no longer have access to (but can't add new ones via create).

Every field is optional and applied only when present (a partial patch): name, expression, config, priority, enabled, and also phase and rule_type — both are mutable on update (when you send them they replace the stored value). The resulting config is re-validated against the (possibly new) rule type's schema and re-run through the AI safety check before persistence.

Path parameters

uuid string (uuid) Req
The endpoint's uuid from /endpoints.
policy_uuid string (uuid) Req
The policy's uuid. Resolved under this endpoint only.
rule_uuid string (uuid) Req
The rule's uuid (from the policy's rules). Resolved under this policy only.

Deprecated: legacy integer ids are still accepted in the path until the sunset, answered with Deprecation and Sunset headers. Use the uuids.

Request body

Same fields as create — all optional. Any of name, expression, config, priority, enabled, phase, rule_type that you send is applied; omitted fields keep their stored value. Strict decoding rejects unknown fields. A config you send replaces the whole stored config, so send every field you keep.

A verify-webhook or jwt-validation rule's config.secret (reads answer it as "****"):

  • **** keeps the secret saved on the rule, as long as the rule keeps its rule_type and has a secret. Any other **** is refused with 400 on config.secret (see Errors).
  • "", or no secret key, removes it: for a jwt-validation rule on an RS*/ES* algorithm, which checks tokens with its jwks_url. A verify-webhook rule requires a secret, so "" is refused (secret is required).
  • Any other value replaces it.

A config left out keeps the whole stored config, secret included (e.g. {"enabled": false}).

Response (200 OK)

The updated rule (with uuid and policy_uuid). A saved secret answers "secret": "****".

Deprecated: until the sunset this response also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Errors

400 Bad Request
Schema-invalid config, AI safety check failed, invalid JSON, or an integer policy / rule id after the sunset (integer_id_unsupported).
400 masked secret
config.secret is **** but there is no saved secret it can keep: the rule has none, or the update changes its rule_type. Keyed to config.secret in fields: "****" is the masked placeholder of a saved secret, not a secret: send the secret (sending "****" keeps a saved secret only on an update of the same rule with the same rule_type).
401 Unauthorized
Missing auth.
403 Forbidden
Plan doesn't include traffic_policies.
404 Not Found
Endpoint doesn't exist (Endpoint not found), the policy isn't one of this endpoint's (Policy not found), or the rule isn't one of this policy's (Rule not found).
Request — bump rate limit
curl -X PUT "https://api.ngris.com/v1/endpoints/019bb1e4-e785-77d2-9966-c3cff31d0a0e/policies/019b74e7-6fe8-7784-9d8a-9b7f9cb99a89/rules/019b7fe5-336a-7789-aeab-182ddfcd5711" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ -d '{ "name": "200rps-per-ip", "config": {"limit": 200, "window": 1, "scope": "ip"}, "priority": 0, "enabled": true }'
Python
from ngris import Ngris client = Ngris(api_key="<your_api_key>") client.traffic_policies.update_rule( "019bb1e4-e785-77d2-9966-c3cff31d0a0e", "019b74e7-6fe8-7784-9d8a-9b7f9cb99a89", "019b7fe5-336a-7789-aeab-182ddfcd5711", { "name": "200rps-per-ip", "config": {"limit": 200, "window": 1, "scope": "ip"}, "enabled": True, }, )
Request — change a verify-webhook rule, keep its secret
curl -X PUT "https://api.ngris.com/v1/endpoints/019bb1e4-e785-77d2-9966-c3cff31d0a0e/policies/019b74e7-6fe8-7784-9d8a-9b7f9cb99a89/rules/019b7fe5-336a-7789-aeab-182ddfcd5712" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ -d '{ "config": { "provider": "generic", "secret": "****", "signature_header": "X-Signature", "algorithm": "sha256", "signature_prefix": "sha256=" } }'
Response — 200 OK
{ "uuid": "019b7fe5-336a-7789-aeab-182ddfcd5711", "policy_uuid": "019b74e7-6fe8-7784-9d8a-9b7f9cb99a89", "phase": "on_http_request", "rule_type": "rate-limit", "name": "200rps-per-ip", "config": {"limit": 200, "window": 1, "scope": "ip"}, "priority": 0, "enabled": true, "created_at": "2026-04-29T13:00:00Z", "updated_at": "2026-04-29T13:10:00Z" }
Was this helpful?
On this page
Update Policy Rule
Was this helpful?