# Block or allow an IP

`POST /v1/service/@id/waf/ip-rules` · scope `waf:write`

Body `value` (IP or range), `action` (block or allow), `note` (optional). Returns HTTP 200 instead of 201 when the entry already exists.

## HTTP request

| Item | Value |
| --- | --- |
| URL | `https://api.tino.vn/v1/service/@id/waf/ip-rules` |
| Method | `POST` |
| Scope | `waf:write` |
| Header | `Authorization: Bearer <token>` |
| Content-Type | `application/json` |
| Tokens that can call it | app tokens (`tinoat_`), personal API tokens (`tinopat_`) |

## Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `id` | path | int | yes | Service ID |
| `value` | body | string | yes | IP address or range (CIDR), e.g. `203.0.113.10` or `203.0.113.0/24`. |
| `action` | body | string | yes | `block` or `allow`. |
| `note` | body | string | no | Note shown in the list. |

## Example request

```bash
curl -X POST "https://api.tino.vn/v1/service/100001/waf/ip-rules" \
  -H "Authorization: Bearer $TINO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "value": "203.0.113.0/24",
  "action": "block",
  "note": "Quét cổng"
}'
```

`$TINO_TOKEN` is a token with the scope `waf:write`. Path parameters in the example are sample values.

SDK ([SDK & examples](/en/docs/sdk)): no dedicated function yet, use `client.request("POST", "/service/@id/waf/ip-rules")`.

## Example response

No live sample: the route changes real data or the test account has no data for it. The answer is a JSON object; errors follow the common shape in [Calling the Tino API](/en/docs/api#errors).
