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

# Replace Account Permissions

> Replace Account Permissions using the granular CAD v2 permissions API.

`PUT` `https://api.sonorancad.com/v2/general/permissions/accounts/{accountId}`

Authenticate with your community API key using `Authorization: Bearer YOUR_API_KEY`. All SDK examples use the existing authenticated request and rate-limit handling.

Replace the account's complete explicit grant list in the authenticated community. `accountId` is the account UUID, not a community user ID. This operation does not add to the existing list: omitted grants are removed. The request must contain `grants`; `version` is `2` (the server also defaults an omitted version to `2`).

Use exact, case-sensitive grant IDs from [Get Permission Catalog](/cad/api-integration/api-endpoints-v2/general/accounts/get-permission-catalog). To retain existing permissions, first [read the account](/cad/api-integration/api-endpoints-v2/general/accounts/get-account-permissions), check that the read succeeded, and build the complete desired list. Concurrent replacements can overwrite each other; coordinate writers.

Only pending or active non-owner memberships can be edited. Nonempty grants activate pending memberships, subject to the community member limit. An empty array clears grants and makes an active membership pending. This endpoint does not ban, unban, restore removed memberships, or reactivate expired memberships. Unknown grants, owner edits, missing/noneditable accounts, and membership-limit failures return HTTP `400`.

A granular replacement ends legacy category inheritance for future record templates. Refresh the catalog and explicitly grant access to new templates when needed. Existing legacy integrations remain supported, but new integrations should use this endpoint.

## Selecting limited editing

After the catalog exposes `record.<templateId>.edit.selected`, include that grant to permit only fields marked **Allow limited editing** on another account's records. Include `read` and required page access separately. Retain or add `edit.own` only if own-record editing is also intended. Remove that template's `edit.any` grant when limiting access: full editing takes precedence, regardless of field opt-in. Preserve every unrelated grant when building the replacement list.

`supervise` remains an additional requirement for supervisor-only fields, including opted-in fields. It does not expand a selected-field user's editable field list. Existing records and field flags need no migration. Existing Edit any grants are retained and mean full editing on the updated backend. Do not send this new grant to a server whose catalog does not include it.

## Request Body

```json theme={null}
{"version": 2, "grants": ["global.police"]}
```

To clear all permissions, explicitly send:

```json theme={null}
{"version": 2, "grants": []}
```

## Example Request

**Sonoran.lua**

```lua theme={null}
-- luarocks install sonoran.lua
-- For SonoranCADFiveM in-game usage, see the SonoranCADFiveM tab for the export-based client.
local Sonoran = require("sonoran")

local sonoran = Sonoran.createClient({
  product = Sonoran.productEnums.CAD,
  communityId = "YOUR_COMMUNITY_ID",
  apiKey = "YOUR_API_KEY",
  defaultServerId = 1
})

local response = sonoran.cad:replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", { "global.police" })

-- Inspect response.success, response.data, or response.reason as needed.
print(response.success)
```

**SonoranCADFiveM**

Use this tab only when calling the v2 API from the server side of an in-game FiveM resource.

* **Sonoran.lua** and **Sonoran.js:** use the `sonorancad` export to get the ready CAD client.
* **Sonoran.Net:** FiveM exports do not return a .NET client. Read the Sonoran CAD convars and create a fresh client.
* **Sonoran.py:** FiveM does not run Python resources; use the Python tab for external integrations.

The API key is stored in `sonoran_apiKey` as a protected FiveM convar. FiveM restricts a convar after `add_convar_permission` is configured, so only explicitly permitted resources can read it. Grant another resource access with `add_convar_permission your-resource-name read sonoran_apiKey`. If you change the API key in `config.json`, fully restart the `sonorancad` resource before reading the updated convar value.

**Sonoran.lua**

```lua theme={null}
local cad = exports["sonorancad"]:getCadClient()
```

**Sonoran.js**

```javascript theme={null}
const cad = exports["sonorancad"].getCadClient();
```

**Sonoran.Net**

```csharp theme={null}
// dotnet add package Sonoran.Net
using CitizenFX.Core.Native;
using Sonoran;

var communityId = API.GetConvar("sonoran_communityID", "");
var apiKey = API.GetConvar("sonoran_apiKey", "");
var serverIdRaw = API.GetConvar("sonoran_serverId", "1");
var serverId = int.TryParse(serverIdRaw, out var parsedServerId) ? parsedServerId : 1;

using var sonoran = new SonoranClient(new SonoranClientOptions
{
    product = SonoranProduct.CAD,
    communityId = communityId,
    apiKey = apiKey,
    defaultServerId = serverId
});
```

After getting the Lua export client:

```lua theme={null}
local response = cad:replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", { "global.police" })

-- Inspect response.success, response.data, or response.reason as needed.
print(response.success)
```

After getting the JavaScript export client:

```javascript theme={null}
const response = await cad.replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", ["global.police"]);
console.log(response);
```

After constructing the .NET client from protected convars:

```csharp theme={null}
var response = await sonoran.Cad.replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", new[] { "global.police" });
Console.WriteLine(response.success);
```

**Sonoran.js**

```javascript theme={null}
// npm install @sonoransoftware/sonoran.js
// For SonoranCADFiveM in-game usage, see the SonoranCADFiveM tab for the export-based client.
const Sonoran = require('@sonoransoftware/sonoran.js');

(async () => {
  const instance = new Sonoran.Instance({
    communityId: 'YOUR_COMMUNITY_ID',
    apiKey: 'YOUR_API_KEY',
    product: Sonoran.productEnums.CAD,
    serverId: 1,
  });

  const response = await instance.cad.replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", ["global.police"]);
  console.log(response);
})();
```

**Sonoran.py**

```python theme={null}
# pip install Sonoran.py
# Sonoran.py is for external Python integrations; FiveM resources should use the SonoranCADFiveM tab.
from sonoran import Instance, productEnums

instance = Instance(
    apiKey="YOUR_API_KEY",
    communityId="YOUR_COMMUNITY_ID",
    product=productEnums.CAD,
    serverId=1,
)

response = instance.cad.replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", ["global.police"])

print(response.success)
print(response.data if response.success else response.reason)
```

**Sonoran.Net**

```csharp theme={null}
// dotnet add package Sonoran.Net
// For SonoranCADFiveM in-game usage, see the SonoranCADFiveM tab; .NET creates a fresh client from convars.
using Sonoran;

using var sonoran = new SonoranClient(new SonoranClientOptions
{
    product = SonoranProduct.CAD,
    communityId = "YOUR_COMMUNITY_ID",
    apiKey = "YOUR_API_KEY",
    defaultServerId = 1
});

var response = await sonoran.Cad.replaceAccountPermissionsV2("00000000-0000-0000-0000-000000000000", new[] { "global.police" });

Console.WriteLine(response.success);
var result = response.success ? response.data?.ToObject<CadReplaceAccountPermissionsV2Response>() : null;
Console.WriteLine(result);
```

**OpenAPI**

Import this YAML into Postman with **Import -> Raw text**.

```yaml theme={null}
openapi: "3.0.3"
info:
  title: Sonoran CAD v2 - Replace Account Permissions
  version: 1.0.0
servers:
- url: https://api.sonorancad.com
paths:
  /v2/general/permissions/accounts/{accountId}:
    put:
      summary: Replace Account Permissions
      operationId: replaceAccountPermissionsV2
      security:
      - bearerAuth: []
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                type: object
                properties:
                  accountUuid:
                    type: string
                    format: uuid
                  permissions:
                    type: object
                    properties:
                      version:
                        type: integer
                        enum:
                        - 2
                      grants:
                        type: array
                        items:
                          type: string
              example:
                accountUuid: 00000000-0000-0000-0000-000000000000
                permissions:
                  version: 2
                  grants:
                  - global.police
        '400':
          description: Invalid request or account cannot be edited
        '401':
          description: Missing or invalid API key
        '429':
          description: Rate limited; follow Retry-After before retrying
      parameters:
      - name: accountId
        in: path
        required: true
        schema:
          type: string
          format: uuid
        example: 00000000-0000-0000-0000-000000000000
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - grants
              properties:
                version:
                  type: integer
                  enum:
                  - 2
                  default: 2
                grants:
                  type: array
                  uniqueItems: true
                  items:
                    type: string
            example:
              version: 2
              grants:
              - global.police
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
```

**cURL**

```bash theme={null}
curl --request PUT \
  --url "https://api.sonorancad.com/v2/general/permissions/accounts/00000000-0000-0000-0000-000000000000" \
  --header "Authorization: Bearer YOUR_API_KEY" \
  --header "Accept: application/json" \
  --header "Content-Type: application/json" \
  --data '{"version": 2, "grants": ["global.police"]}'
```

## Response

```json theme={null}
{
  "accountUuid": "00000000-0000-0000-0000-000000000000",
  "permissions": {
    "version": 2,
    "grants": [
      "global.police"
    ]
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.