# Create a banning rule (/en/api-reference/api-ref/rtc/create-ban-rule)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Creates a rule for banning specified user privileges.

- OpenAPI: /openapi/rtc/channel-management.en.yaml
- Operation ID: cma-create-ban-rule
- Method: POST
- Path: /dev/v1/kicking-rule
- Endpoint: https://api.agora.io/dev/v1/kicking-rule

## Servers

- https://api.agora.io

Use this endpoint to create a rule for banning specified user privileges.


## Authorization

This endpoint requires authentication.

- `basicAuth`

## Parameters

No parameters.

### Request

- The request URL and request body is case-sensitive. All requests must use HTTPS.

- `Content-Type`: `application/json`

- The request header must contain the `Authorization` field. For details, see [RESTful authentication](/en/api-reference/api-ref/rtc/authentication).


## Request body

- `appid` (string, required) - The App ID of the project. You can get it through one of the following methods:
- Copy from the [Agora Console](https://console.agora.io)
- Call the Get all projects API, and read the value of the
  `vendor_key` field in the response body.
- `cname` (string) - The channel name.
- `uid` (number) - The user ID. Do not set it to `0`.
- `ip` (string) - The IP address of the user. Do not set it to `0`.
- `time` (number) - The time duration (in minutes) to ban the user. Values outside the range [1,1440] are clamped to the nearest bound. Setting this to `0` disables the rule: users are set offline but can rejoin immediately.
  - Range: `[1, 1440]`
- `time_in_seconds` (number) - The time duration (in seconds) to ban the user. Values outside the range [10,86430] are clamped to the nearest bound. Setting this to `0` disables the rule: users are set offline but can rejoin immediately.
`time_in_seconds` takes effect. If neither is set, the default ban duration is 60 minutes (3600 seconds).
  - Range: `[10, 86430]`

  :::info[Note]
  Use either `time` or `time_in_seconds`, not both. If both are set,
  :::
- `privileges` (array, required) - The user privileges you want to block. Possible values:
- `join_channel`: Bans a user from joining a channel or
  kicks a user out of a channel.

- `publish_audio`: Bans a user from publishing audio.
- `publish_video`: Bans a user from publishing video.

To ban a user from both publishing audio and video, specify both `publish_audio` and `publish_video`.
  - `privileges.items` (string)
    - Allowed: `join_channel` | `publish_audio` | `publish_video`

### Request body example

```json
{
  "appid": "4855xxxxxxxxxxxxxxxxxxxxxxxxeae2",
  "cname": "channel1",
  "uid": 589517928,
  "ip": "",
  "time": 60,
  "privileges": [
    "join_channel"
  ]
}
```

## Request examples

### curl

```bash
curl --request POST \
  --url https://api.sd-rtn.com/dev/v1/kicking-rule \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <your_base64_encoded_credentials>' \
  --header 'Content-Type: application/json' \
  --data '{
  "appid": "4855xxxxxxxxxxxxxxxxxxxxxxxxeae2",
  "cname": "channel1",
  "uid": 589517928,
  "ip": "",
  "time": 60,
  "privileges": [
    "join_channel"
  ]
}'
```

### Node.js

```javascript
const https = require('https');

const options = {
  method: 'POST',
  hostname: 'api.sd-rtn.com',
  port: null,
  path: '/dev/v1/kicking-rule',
  headers: {
    Authorization: 'Basic <your_base64_encoded_credentials>',
    'Content-Type': 'application/json',
    Accept: 'application/json'
  }
};

const req = https.request(options, function (res) {
  const chunks = [];
  res.on('data', function (chunk) {
    chunks.push(chunk);
  });

  res.on('end', function () {
    const body = Buffer.concat(chunks);
    console.log(body.toString());
  });
});

req.write(JSON.stringify({
  appid: '4855xxxxxxxxxxxxxxxxxxxxxxxxeae2',
  cname: 'channel1',
  uid: 589517928,
  ip: '',
  time: 60,
  privileges: ['join_channel']
}));
req.end();
```

### Python

```python
import http.client
import json

conn = http.client.HTTPSConnection("api.sd-rtn.com")

payload = {
    "appid": "4855xxxxxxxxxxxxxxxxxxxxxxxxeae2",
    "cname": "channel1",
    "uid": 589517928,
    "ip": "",
    "time": 60,
    "privileges": [
        "join_channel"
    ]
}

headers = {
    'Authorization': "Basic <your_base64_encoded_credentials>",
    'Content-Type': "application/json",
    'Accept': "application/json"
}

conn.request("POST", "/dev/v1/kicking-rule", json.dumps(payload), headers)

res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))
```


### Response

- A `200` status code indicates success. The response body contains the following parameters:

- If the status code is not `200`, the request fails. See the `message` field in the response body for the reason for this failure. Refer to [Response status codes](/en/api-reference/api-ref/rtc/response-status-codes) for details.


## Responses

### 200

A `200` status code indicates success. The response body contains the result of the request.

- `status` (string) - The status of this request. `success` means the request succeeds.
- `id` (number) - The rule ID. Save the rule ID to update or delete this rule later.
### default

The request failed. See the `message` field in the response body for the reason. Refer to Response status codes for details.

No schema.

### Reference

### Banning rule behavior

The banning rule behavior depends on which combination of `cname`, `uid`, and `ip` fields you set.

**When `privileges` is `join_channel`:**

| `ip` | `cname` | `uid` | Rule |
|:----:|:-------:|:-----:|:-----|
| ✔ | ✘ | ✘ | All users with this `ip` cannot join any channel in the app. Using `ip` as a filter field may incorrectly block users who should not be blocked, for example, in a use-case where multiple users share an IP address. |
| ✘ | ✔ | ✘ | No one can join the channel specified by the `cname` field. Using `cname` as a filter field directly blocks the named channel. |
| ✘ | ✘ | ✔ | The user with the `uid` cannot join any channel in the app. |
| ✘ | ✔ | ✔ | The user with the `uid` cannot join the channel specified by the `cname` field. |


**When `privileges` is `publish_audio` or `publish_video`:**

| `ip` | `cname` | `uid` | Rule |
|:----:|:-------:|:-----:|:-----|
| ✔ | ✘ | ✘ | The users with this `ip` cannot publish audio or video in any channel of the app. |
| ✘ | ✔ | ✘ | No one can publish audio or video in the channel specified by the `cname` field. |
| ✘ | ✘ | ✔ | The user with the `uid` cannot publish audio or video in any channel of the app. |
| ✘ | ✔ | ✔ | The user with the `uid` cannot publish audio or video in the channel specified by the `cname` field. |


### Client callbacks for `join_channel` bans

A user who is kicked out of a channel when `privileges` is set to `join_channel` receives one of the following callbacks based on their platform:

- **Android**: The `onConnectionStateChanged` callback reports `CONNECTION_CHANGED_BANNED_BY_SERVER(3)`.
- **iOS/macOS**: The `connectionChangedToState` callback reports `AgoraConnectionChangedBannedByServer(3)`.
- **Web (3.x)**: The `Client.on("client-banned")` callback.
- **Web (4.x)**: The `Client.on("connection-state-change")` callback.
- **Windows**: The `onConnectionStateChanged` callback reports `CONNECTION_CHANGED_BANNED_BY_SERVER(3)`.
- **Electron**: The `AgoraRtcEngine.on("connectionStateChanged")` callback reports `3`.
- **Unity**: The `OnConnectionStateChangedHandler` callback reports `CONNECTION_CHANGED_BANNED_BY_SERVER(3)`.
- **React Native**: The `ConnectionStateChanged` callback reports `BannedByServer(3)`.
- **Flutter**: The `ConnectionStateChanged` callback reports `BannedByServer(3)`.
- **Cocos Creator**: The `onConnectionStateChanged` callback reports `CONNECTION_CHANGED_BANNED_BY_SERVER(3)`.
- **Applets**: `on(event: "client-banned")`.

### Best practices for rule management

To maximize the success rate of create, update, and delete operations, query requests are assigned a lower priority. Under poor network conditions, the success rate and accuracy of GET requests may degrade and some request records may be missing from the results.

When you call POST to create a rule where `time` is not set to `0`, use the following best practices to update or delete it later:

- Save the rule ID returned in the POST request on your server, and rely on this ID for subsequent update and delete operations.
- To ensure that you can still obtain the rule ID under poor network conditions, set the timeout for the POST request to 20 seconds or higher. Make sure that the timeout is set to no less than 5 seconds.
- In case the POST request times out or returns a `504` error, use the response of the GET method to obtain the rule ID. If the rule exists, it indicates that the POST request was successful, and you can save the rule ID on your server.


### Response

See Banning rule behavior for details.

See Client callbacks for join_channel bans for details.


## Response examples

### 200

```json
{
  "status": "success",
  "id": 1953
}
```
