Skip to content
nsin docs

Enable or disable a rate limit rule

PATCH
/domains/{domain}/rules/rate-limit/{ruleId}/toggle
curl --request PATCH \
--url https://api.nsin.ir/domains/example.com/rules/rate-limit/1/toggle \
--header 'Authorization: Bearer <token>'

Flips the rule’s enabled flag. Takes no request body — the new state is always the opposite of the current one, and is returned. Requires rules.edit.

Switching a rule on is refused with 402 when the domain’s plan does not include its type; switching it off always works.

domain
required
string

The domain name (for example example.com) — not a numeric id.

Example
example.com
ruleId
required
integer

Numeric id of the rule.

The rule in its new state.

Media type application/json
object
id
integer
domain_id
integer
record_id

Deprecated single-record scope. Prefer record_ids. Absent for zone-wide rules.

integer
record_ids

The proxied DNS records this rule applies to. Empty or absent means zone-wide — every proxied record of the domain.

Array<integer>
type
string
Allowed values: cache drop redirect rewrite waf captcha rate_limit bot_route origin_pool origin_route fingerprint error_page optimize basic_auth header
enabled
boolean
priority

Evaluation order; lower runs first. Defaults to 100.

integer
host_pattern

Legacy single-hostname filter, kept for rules written before host_includes existed. It is evaluated as one more entry of host_includes; prefer the lists.

string
host_match_type

How the host filter — host_pattern, host_includes and host_excludes — is matched. One strategy covers all three, exactly as one path_match_type covers both path lists.

The empty string means “no host filter”, and is the only valid value when the pattern and both lists are empty. Set a list without a match type and the API defaults it to wildcard.

A wildcard entry matches subdomains, not the label itself: *.example.com covers shop.example.com but not example.com — the same reading as the DNS wildcard. Add the bare name as its own entry to include it.

string
Allowed values: "" exact wildcard regex
host_includes

Hostnames the rule applies to. Empty or absent means every host the scoped record(s) serve — which on a wildcard-proxied zone (*.example.com) is every subdomain.

Array<string>
host_excludes

Hostnames carved back out of host_includes. An exclude always wins over an include, so “everything except staging” is an empty include list plus one exclude.

Array<string>
ip_includes

Client addresses the rule applies to. Empty or absent means every address — the rule is not scoped by IP at all unless ip_excludes is set.

Entries are returned canonicalised, which may differ from what was sent: CIDR host bits are masked off (10.0.0.5/8 reads back as 10.0.0.0/8), range endpoints are ordered low-to-high, IPv4-mapped IPv6 is unmapped, and duplicates are dropped. The order of the remaining entries is preserved.

The address matched is the TCP peer seen by the edge. X-Forwarded-For is never consulted, so a visitor cannot spoof a header to put themselves inside or outside a scope.

Array<string>
<= 256 items
ip_excludes

Client addresses carved back out of ip_includes. An exclude always wins over an include. Canonicalised on the way in, exactly like ip_includes.

Array<string>
<= 256 items
action_mode
  • enforce — the rule acts (block, redirect, challenge, …).
  • dry_run — the rule matches and is logged as “would have acted”, but the request reaches the origin unchanged. Use it to test a rule safely.

Not every rule type honours this; cache ignores it.

string
Allowed values: enforce dry_run
created_at
string format: date-time
updated_at
string format: date-time
path_match_type

How path_includes and path_excludes are interpreted.

string
Allowed values: wildcard regex
path_includes

Paths the rule applies to. Defaults to ["/*"] — everything.

Array<string>
path_excludes

Paths carved back out of path_includes.

Array<string>
limit

Requests allowed per window_sec for one key.

integer
window_sec

Length of the counting window, in seconds.

integer
default: 60
key_by

How requests are bucketed. ip counts everything from one address together; ip_path counts each path separately per address.

string
default: ip
Allowed values: ip ip_path
on_breach

What happens to requests above the limit.

string
default: drop
Allowed values: drop captcha
burst

Extra requests tolerated momentarily above limit.

integer
methods

Only count requests with these HTTP methods. Empty or omitted counts every method. A request with another method skips this rule and is checked against the next rate limit rule in priority order.

Array<string>
Allowed values: GET HEAD POST PUT PATCH DELETE OPTIONS
key_parts

What one counter is keyed by: up to 4 parts combined into one key. When set it replaces key_by (which is still returned, as ip, or ip_path for exactly [ip, path], for edges that predate this field). A part a request lacks counts as empty, so every request without that cookie or header shares one counter — often exactly what you want against bots. Counting is per edge location.

Array<object>
<= 4 items
object
part
required

ip_prefix is the client’s /24 (IPv4) or /64 (IPv6); asn the client IP’s AS number; header, cookie and query the value of the one named in key.

string
Allowed values: ip ip_prefix path host method ja4 ja4h country asn header cookie query user_agent
key

The header, cookie or query parameter name. Required for those three parts, absent for every other.

string
<= 128 characters
match

How match_conditions combine.

string
default: all
Allowed values: all any
match_conditions

Only count requests that match these conditions (the custom rule condition objects). Empty means every request in scope counts.

Array<object>
<= 10 items

One test on the request. TRUE when ANY of values matches; negate flips the result. A missing cookie, header, query parameter or referer makes every op except exists false — so a negated contains on a missing cookie is true.

object
field
required

What to test. bot_score is the edge’s bot score of the request, 1 (bot) to 99 (human-like); a request the edge did not score never matches. path is the request path before any rewrite, host is lowercased without the port, ip is the TCP peer (never X-Forwarded-For), country the visitor’s GeoIP country (XX when unknown), asn the client IP’s autonomous system number (an address with no known ASN never matches), ja4/ja4h NSIN’s own fingerprints as shown in the request logs.

string
Allowed values: cookie header query path method host user_agent referer ip country asn ja4 ja4h bot_score
key

The cookie or header name — required for cookie and header. For query, a parameter name, or empty for the whole raw query string. Must be empty for every other field.

string
<= 128 characters
op
required

bot_score takes only lt or gt with exactly one value, a whole number 1–99 (expression bot_score lt "30"); it is accepted once the edge update that computes bot scores is live everywhere (until then 400). ip, country and asn take only in. Every other field takes exists, equals, contains, starts_with, ends_with or matches (an RE2 regex of up to 256 characters). exists is only for cookie, header, referer and query with a key.

string
Allowed values: exists equals contains starts_with ends_with matches in lt gt
values

1–100 values, empty for exists. ip: single addresses or CIDRs (v4 or v6), stored canonicalized. country: ISO 3166-1 alpha-2 codes, stored uppercase. asn: AS numbers 1–4294967295 (an AS prefix is accepted), stored as plain decimals. An empty value is refused for contains, starts_with, ends_with and matches (it would match every request).

Array<string>
<= 100 items
negate

Flip the result — “is not”, “does not contain”, “does not exist”.

boolean
ignore_case

Compare text case-insensitively. Not allowed on ip, country or asn; method and host always compare case-insensitively.

boolean
block_for_sec

After a key breaches the limit, keep answering on_breach for that key this many seconds. 0 = only while it is over the limit.

integer
0 <= 86400
Example
{
"type": "cache",
"host_match_type": "",
"action_mode": "enforce",
"path_match_type": "wildcard",
"window_sec": 60,
"key_by": "ip",
"on_breach": "drop",
"methods": [
"GET"
],
"key_parts": [
{
"part": "ip"
}
],
"match": "all",
"match_conditions": [
{
"field": "cookie",
"op": "exists",
"negate": false,
"ignore_case": false
}
],
"block_for_sec": 0
}

Missing, malformed, revoked or expired API key. (A valid key whose account has been deactivated gets 403 account is inactive instead.)

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example invalidKey
{
"error": "invalid API key"
}

The request would switch on a rule whose type the domain’s plan does not include, or the domain has no active plan at all. Such a rule can be created, edited and switched off, but it stays off until the plan includes its type: buy or upgrade the domain’s plan, then switch it on.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
{
"error": "This rule type is not on this domain's plan. The rule is saved switched off — buy or upgrade this domain's plan to switch it on."
}

The key is read-only and this endpoint is a write. Read-only keys may only issue GET, HEAD and OPTIONS.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example readOnly
{
"error": "read-only API key"
}

The domain or the rule does not exist, the rule belongs to another domain or another rule type, or your role does not permit this operation.

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Example
{
"error": "read-only API key"
}

The key exceeded its request budget (300 requests per minute by default).

Media type application/json

The single error shape used by every endpoint.

object
error
required

Human-readable description of what went wrong.

string
Examples
Example limited
{
"error": "rate limit exceeded"
}