> ## Documentation Index
> Fetch the complete documentation index at: https://docs.technified.xyz/llms.txt
> Use this file to discover all available pages before exploring further.

# Bindings

> Read and manage the role bindings that map Roblox data to Discord roles.

Bindings assign Discord roles from Roblox data. These endpoints let you read the configured bindings and manage them programmatically. For the concept and the dashboard UI, see [Bindings](/dashboard/roblox/bindings).

`list` reads the guild from the `X-Guild-ID` header. The write endpoints take `guild_id` in the body.

## Binding types

| `binding_type` | Required fields                                            |
| -------------- | ---------------------------------------------------------- |
| `group_rank`   | `roblox_group_id`, `min_rank`, `max_rank` (ranks 0 to 255) |
| `gamepass`     | `roblox_gamepass_id`                                       |
| `asset`        | `roblox_asset_id`                                          |
| `badge`        | `roblox_badge_id`                                          |
| `account_age`  | `account_age_platform`, `account_age_min_days`             |

## List bindings

```http theme={null}
GET /bindings/list
```

<ParamField header="X-Guild-ID" type="string" required>
  The guild to read. Must match your key's guild.
</ParamField>

Each binding is enriched with the resolved Discord role name and, for group bindings, the Roblox group name.

<ResponseField name="data" type="object">
  <Expandable title="binding properties">
    <ResponseField name="id" type="number" />

    <ResponseField name="discord_role_id" type="string" />

    <ResponseField name="discord_role_name" type="string" />

    <ResponseField name="binding_type" type="string" />

    <ResponseField name="roblox_group_id" type="number | null" />

    <ResponseField name="roblox_group_name" type="string" />

    <ResponseField name="min_rank" type="number | null" />

    <ResponseField name="max_rank" type="number | null" />

    <ResponseField name="gamepass_id" type="number | null" />
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.technified.xyz/api/v1/bindings/list" \
    -H "X-API-Key: $TECHNIFIED_API_KEY" \
    -H "X-Guild-ID: $GUILD_ID"
  ```
</RequestExample>

## Add a binding

```http theme={null}
POST /bindings/add
```

<ParamField body="guild_id" type="string" required />

<ParamField body="discord_role_id" type="string" required>
  The Discord role to assign.
</ParamField>

<ParamField body="binding_type" type="string" required>
  One of `group_rank`, `gamepass`, `asset`, `badge`, `account_age`.
</ParamField>

<ParamField body="roblox_group_id" type="number">
  Required for `group_rank`.
</ParamField>

<ParamField body="min_rank" type="number">
  Required for `group_rank`. 0 to 255.
</ParamField>

<ParamField body="max_rank" type="number">
  Required for `group_rank`. Must be at least `min_rank`.
</ParamField>

<ParamField body="roblox_gamepass_id" type="number">
  Required for `gamepass`.
</ParamField>

<ParamField body="roblox_asset_id" type="number">
  Required for `asset`.
</ParamField>

<ParamField body="roblox_badge_id" type="number">
  Required for `badge`.
</ParamField>

<ParamField body="account_age_platform" type="string">
  `discord` or `roblox`. Required for `account_age`.
</ParamField>

<ParamField body="account_age_min_days" type="number">
  Required for `account_age`.
</ParamField>

<ParamField body="priority" type="number">
  Optional ordering hint when bindings overlap.
</ParamField>

The Roblox group, gamepass, asset, or badge is validated against Roblox before the binding is saved. An invalid ID returns `400`.

<RequestExample>
  ```bash Group rank theme={null}
  curl "https://api.technified.xyz/api/v1/bindings/add" \
    -H "X-API-Key: $TECHNIFIED_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "guild_id": "'$GUILD_ID'",
      "discord_role_id": "111111111111111111",
      "binding_type": "group_rank",
      "roblox_group_id": 1200769,
      "min_rank": 50,
      "max_rank": 99
    }'
  ```

  ```bash Gamepass theme={null}
  curl "https://api.technified.xyz/api/v1/bindings/add" \
    -H "X-API-Key: $TECHNIFIED_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "guild_id": "'$GUILD_ID'",
      "discord_role_id": "222222222222222222",
      "binding_type": "gamepass",
      "roblox_gamepass_id": 123456
    }'
  ```
</RequestExample>

## Update a binding

```http theme={null}
PATCH /bindings/update
```

<ParamField body="binding_id" type="number" required />

<ParamField body="min_rank" type="number" />

<ParamField body="max_rank" type="number" />

<ParamField body="priority" type="number" />

## Remove a binding

```http theme={null}
DELETE /bindings/remove/:bindingId
```

<ParamField path="bindingId" type="number" required>
  The `id` of the binding to delete.
</ParamField>

## Test a binding against a user

Check whether a specific verified member would match an existing group binding. Useful for debugging "why does this person not have the role".

```http theme={null}
POST /bindings/test
```

<ParamField body="guild_id" type="string" required />

<ParamField body="discord_id" type="string" required>
  The member to test. Must be verified in the guild.
</ParamField>

<ParamField body="binding_id" type="number" required>
  The binding to test against.
</ParamField>

<ResponseField name="data.matches" type="boolean" />

<ResponseField name="data.reason" type="string">
  A human-readable explanation, for example "User rank 12 is below minimum 50".
</ResponseField>

<ResponseField name="data.user_rank" type="number">
  The member's rank in the group, when applicable.
</ResponseField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "status": "success",
    "code": 200,
    "message": "Binding test complete",
    "data": {
      "matches": false,
      "reason": "User rank 12 is below minimum 50",
      "user_rank": 12
    }
  }
  ```
</ResponseExample>

## Validate a group binding config

Check a group rank configuration before saving it. This validates the group exists and the ranks are sane. It is group-rank specific.

```http theme={null}
POST /bindings/validate
```

<ParamField body="roblox_group_id" type="number" required />

<ParamField body="min_rank" type="number">
  0 to 255.
</ParamField>

<ParamField body="max_rank" type="number">
  0 to 255, and at least `min_rank`.
</ParamField>

<ResponseExample>
  ```json 200 theme={null}
  {
    "status": "success",
    "code": 200,
    "message": "Binding configuration is valid",
    "data": {
      "valid": true,
      "group_name": "Acme Corp",
      "group_id": 1200769
    }
  }
  ```
</ResponseExample>
