---
title: Batch RLS Management API
description: API reference for bulk updating Row-Level Security (RLS) permissions across entities of a given type
date: 2026-03-15
tags:
  - api
  - rls
  - permissions
  - developer
---

The batch RLS endpoint allows project administrators to update Row-Level Security (RLS) permissions across multiple entities of a given type in a single operation.

## Endpoint

```http
POST /api/projects/{projectId}/types/{typeId}/batch-rls
```

**Required permission:** `RLS_UPDATE_PERMISSION` on the project.

## Request body

```typescript
interface BatchRlsRequest {
  action: "setPermission" | "removePermission" | "addUserId" | "removeUserId" | "resetToDefault";
  operations?: ("read" | "update" | "delete")[];  // required for all actions except resetToDefault
  permission?: string;   // required for setPermission / removePermission
  userId?: string;       // required for addUserId / removeUserId
  filter?: {
    rlsOperation?: "read" | "update" | "delete";
    rlsPermission?: string;
    rlsUserId?: string;
  };
  dryRun?: boolean;      // preview matching entities without modifying
}
```

## Actions

| Action | Description | Required fields |
|--------|-------------|-----------------|
| `setPermission` | Set the permission string on specified RLS operations | `operations`, `permission` |
| `removePermission` | Remove the permission from specified RLS operations | `operations`, `permission` |
| `addUserId` | Add a user ID to the allowed users list on specified operations | `operations`, `userId` |
| `removeUserId` | Remove a user ID from the allowed users list on specified operations | `operations`, `userId` |
| `resetToDefault` | Reset all matching entities to the type's `defaultAccess` configuration | — |

The `permission` field should be provided **without** the project prefix — the API adds `{projectId}::` automatically. If the permission already contains `::`, it is used as-is.

## Dry run (preview)

Set `dryRun: true` to preview how many entities match the filter without modifying anything.

```json
// Request
{
  "action": "setPermission",
  "operations": ["read"],
  "permission": "viewer",
  "dryRun": true
}

// Response
{
  "matchingCount": 42,
  "action": "setPermission",
  "operations": ["read"],
  "dryRun": true
}
```

## Filtering

Use the `filter` object to target a subset of entities:

- **`rlsOperation`** — match entities that have a specific RLS operation configured (e.g. `"read"`).
- **`rlsPermission`** — match entities with a specific permission value. When combined with `rlsOperation`, matches that exact operation; otherwise matches any operation.
- **`rlsUserId`** — match entities that include a specific user ID. Scoping follows the same rules as `rlsPermission`.

Without a filter, the operation applies to **all non-deleted entities** of the type.

## Response

### Dry run

```json
{
  "matchingCount": 42,
  "action": "setPermission",
  "operations": ["read"],
  "dryRun": true
}
```

### Execute

```json
{
  "matchingCount": 42,
  "modifiedCount": 42,
  "action": "setPermission",
  "operations": ["read"],
  "dryRun": false
}
```

## Error responses

| Status | Condition |
|--------|-----------|
| 400 | Missing or invalid `action`, `operations`, `permission`, or `userId` |
| 400 | Type has no `defaultAccess` configured (for `resetToDefault`) |
| 404 | Type not found in the specified project |

## UI

The batch RLS management tool is available in the backoffice under **Settings → Types → [Type] → Manage Access** tab. The UI enforces a two-step workflow: users must first **Preview** (dry run) before they can **Apply Changes**.
