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

# Assign Semantic Layer Permissions

> Grant, change, and revoke access to Semantic Layer catalogs, folders, and documents.

The same declarative bulk upsert as the other two axes, applied to the Semantic Layer. Each assignment is a cross product of recipients and resources, and `permission_level: null` revokes.

## Request body

| Parameter        | Type             | Required | Description                                         |
| ---------------- | ---------------- | -------- | --------------------------------------------------- |
| `assignments`    | array of objects | Yes      | One or more assignment blocks. Must not be empty.   |
| `notify_members` | boolean          | No       | Email the recipients. **This axis actually sends.** |
| `message`        | string           | No       | A note included in the notification email.          |

Each object in `assignments`:

| Parameter          | Type                                     | Required | Description                         |
| ------------------ | ---------------------------------------- | -------- | ----------------------------------- |
| `permission_level` | `viewer`, `editor`, `manager`, or `null` | Yes      | The level to apply. `null` revokes. |
| `users`            | array of UUIDs                           | No       | Recipient users.                    |
| `groups`           | array of UUIDs                           | No       | Recipient permission groups.        |
| `catalogs`         | array of UUIDs                           | No       | Target the Semantic Layer root.     |
| `folders`          | array of UUIDs                           | No       | Target folders.                     |
| `documents`        | array of UUIDs                           | No       | Target documents.                   |

<Note>
  Unlike [Assign Permissions](/platform-api/permissions/catalog/assign) on the Catalog axis, `notify_members` on this endpoint **does** send email. If you are provisioning in bulk and do not want to flood inboxes, leave it at its default of `false`.
</Note>

## The three resource levels

`catalogs`, `folders`, and `documents` are the same hierarchy the Semantic Layer shows in the app, from coarsest to finest. A grant on the catalog root reaches everything; a grant on a folder reaches the documents inside it. Prefer the coarsest resource that expresses the intent — it survives documents being added later.

Resource ids come from [Read the Semantic Layer](/platform-api/permissions/semantic-layer/resources).

## Grant a group access to one folder

```bash theme={null}
curl --request POST \
  --url https://api.nekt.ai/api/v1/semantic-layer/permissions/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "assignments": [
      {
        "permission_level": "viewer",
        "groups": ["b8c5e1e3-6d02-4f45-ad20-8f4b6e2d0e13"],
        "folders": ["a1b2c3d4-e5f6-4718-9a0b-1c2d3e4f5061"]
      }
    ]
  }'
```

## Open the whole Semantic Layer to a group

```bash theme={null}
curl --request POST \
  --url https://api.nekt.ai/api/v1/semantic-layer/permissions/ \
  --header "x-api-key: YOUR_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "assignments": [
      {
        "permission_level": "viewer",
        "groups": ["b8c5e1e3-6d02-4f45-ad20-8f4b6e2d0e13"],
        "catalogs": ["7d8e9f0a-1b2c-43d4-85e6-f708192a3b4c"]
      }
    ]
  }'
```

## Response

```json theme={null}
{ "created": [ … ], "updated": [], "revoked": [] }
```

## Errors

| Status | When                                                                                                                                                     |
| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | Two assignments conflict on the same recipient and resource, a recipient's membership is deactivated, or a referenced id is not visible to your API key. |
| `403`  | The key's ceiling does not allow the grant. See [Permissions flow](/platform-api/permissions/overview).                                                  |

## Related

* [Permissions flow](/platform-api/permissions/overview) — the ceiling rules and the upsert semantics in full.
* [List Recipients](/platform-api/permissions/semantic-layer/recipients) — where recipient ids come from.
* [Read the Semantic Layer](/platform-api/permissions/semantic-layer/resources) — where resource ids come from.


## OpenAPI

````yaml POST /api/v1/semantic-layer/permissions/
openapi: 3.0.3
info:
  title: Nekt API
  version: v1
  description: Nekt API Documentation
  contact:
    email: support@nekt.ai
servers:
  - url: https://api.nekt.ai
security: []
paths:
  /api/v1/semantic-layer/permissions/:
    post:
      tags:
        - v1
      description: Grants CRUD, mirroring LakehousePermissionsViewSet.
      operationId: v1_semantic_layer_permissions_create
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/AssignSemanticLayerPermission'
          application/x-www-form-urlencoded:
            schema:
              $ref: '#/components/schemas/AssignSemanticLayerPermission'
          multipart/form-data:
            schema:
              $ref: '#/components/schemas/AssignSemanticLayerPermission'
        required: true
      responses:
        '201':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AssignSemanticLayerPermission'
          description: ''
      security:
        - ApiKeyAuth: []
components:
  schemas:
    AssignSemanticLayerPermission:
      type: object
      description: >-
        One request handles a whole share modal.


        Every recipient x every resource inside an assignment gets that level,
        and

        `permission_level: null` revokes. The frontend sends the diff as ONE
        call.
      properties:
        assignments:
          type: array
          items:
            $ref: '#/components/schemas/SemanticLayerAssignment'
          writeOnly: true
        notify_members:
          type: boolean
          writeOnly: true
          default: false
        message:
          type: string
          writeOnly: true
        created:
          type: array
          items:
            $ref: '#/components/schemas/SemanticLayerPermission'
          readOnly: true
        updated:
          type: array
          items:
            $ref: '#/components/schemas/SemanticLayerPermission'
          readOnly: true
        revoked:
          type: array
          items:
            $ref: '#/components/schemas/SemanticLayerPermission'
          readOnly: true
      required:
        - assignments
        - created
        - revoked
        - updated
    SemanticLayerAssignment:
      type: object
      properties:
        users:
          type: array
          items:
            type: integer
          default: []
        groups:
          type: array
          items:
            type: string
            format: uuid
          default: []
        permission_level:
          nullable: true
          oneOf:
            - $ref: '#/components/schemas/PermissionLevelEnum'
            - $ref: '#/components/schemas/NullEnum'
        catalogs:
          type: array
          items:
            type: string
            format: uuid
          default: []
        folders:
          type: array
          items:
            type: string
            format: uuid
          default: []
        documents:
          type: array
          items:
            type: string
            format: uuid
          default: []
      required:
        - permission_level
    SemanticLayerPermission:
      type: object
      properties:
        id:
          type: string
          format: uuid
          readOnly: true
        user:
          type: string
          readOnly: true
          description: User (Expandable)
        group:
          type: string
          readOnly: true
          description: Group (Expandable)
        permission_level:
          $ref: '#/components/schemas/PermissionLevelEnum'
        catalog:
          type: string
          format: uuid
          readOnly: true
          nullable: true
        folder:
          type: string
          readOnly: true
          description: Folder (Expandable)
        document:
          type: string
          readOnly: true
          description: Document (Expandable)
        granted_by:
          type: string
          readOnly: true
          description: Granted by (Expandable)
        created_at:
          type: string
          format: date-time
          readOnly: true
        updated_at:
          type: string
          format: date-time
          readOnly: true
      required:
        - catalog
        - created_at
        - document
        - folder
        - granted_by
        - group
        - id
        - permission_level
        - updated_at
        - user
    PermissionLevelEnum:
      enum:
        - manager
        - editor
        - viewer
      type: string
      description: |-
        * `manager` - Manager
        * `editor` - Editor
        * `viewer` - Viewer
    NullEnum:
      enum:
        - null
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: 'API Key authentication. Format: ''x-api-key: api_key'''

````