# Folders API Reference

Kloudfuse provides REST endpoints under `/grafana/api/` and `/grafana/apis/` for folder lifecycle management (create, rename, delete) and permission assignment.

All examples on this page use a Service Account token. Replace `<your-instance>` with your Kloudfuse hostname and `<sa-token>` with a valid Service Account token.

For the Favorite Facets GraphQL API, see [Favorite Facets API Reference](https://docs.kloudfuse.com/platform/4.1.0/reference/api/facets/).

## Authentication

Kloudfuse APIs accept Service Account tokens in the `Authorization` header:

```bash
Authorization: Bearer <sa-token>
```

Service Account tokens are created in the Kloudfuse UI under **Admin > Service Accounts**. The account must have at minimum **Editor** role for write operations, and must have **Admin** folder permission on any folder whose permissions it manages.

## Folders

### List Folders

Returns all top-level folders the caller can access.

```bash
curl -H "Authorization: Bearer <sa-token>" \
  https://<your-instance>/grafana/api/folders
```

Add `?permission=Edit` to return only folders the caller can edit:

```bash
curl -H "Authorization: Bearer <sa-token>" \
  "https://<your-instance>/grafana/api/folders?permission=Edit"
```

Response

```json
[\
  {\
    "id": 1,\
    "uid": "ffec62bbr7v28d",\
    "title": "kfuse-cp"\
  },\
  {\
    "id": 17,\
    "uid": "bfec62n4wfpq8e",\
    "title": "kfuse-asm"\
  }\
]
```

### List All Folders with Hierarchy

Returns all folders (paginated, up to 2000 per request) including parent/child relationships and full path metadata.

```bash
curl -H "Authorization: Bearer <sa-token>" \
  "https://<your-instance>/grafana/apis/folder.grafana.app/v1beta1/namespaces/default/folders?limit=2000"
```

Use the `continue` token from `metadata.continue` to fetch the next page when the result set is large.

Response

```json
{
  "kind": "FolderList",
  "apiVersion": "folder.grafana.app/v1beta1",
  "metadata": {},
  "items": [\
    {\
      "kind": "Folder",\
      "apiVersion": "folder.grafana.app/v1beta1",\
      "metadata": {\
        "name": "cfj9y7mmsra4gd",\
        "namespace": "default",\
        "creationTimestamp": "2026-04-16T15:40:29Z",\
        "annotations": {\
          "grafana.app/folder": "afj9y67x5gw74d",\
          "grafana.app/fullpath": "java-service/demo-java-service",\
          "grafana.app/fullpathUIDs": "afj9y67x5gw74d/cfj9y7mmsra4gd"\
        }\
      },\
      "spec": {\
        "title": "demo-java-service",\
        "description": ""\
      }\
    }\
  ]
}
```

Key annotations on each item:

| Annotation | Meaning |
| --- | --- |
| `grafana.app/folder` | UID of the parent folder (absent for root-level folders) |
| `grafana.app/fullpath` | Full slash-separated path of display names |
| `grafana.app/fullpathUIDs` | Full slash-separated path of UIDs |

### Create a Folder

Creates a new folder. To create a sub-folder, include the parent folder UID in the `annotations`.

```bash
# Create a root-level folder
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/apis/folder.grafana.app/v1beta1/namespaces/default/folders" \
     -d '{\
       "spec": { "title": "my-new-folder" },\
       "metadata": {}\
     }'

# Create a sub-folder inside parent UID "ffec62bbr7v28d"
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/apis/folder.grafana.app/v1beta1/namespaces/default/folders" \
     -d '{\
       "spec": { "title": "my-sub-folder" },\
       "metadata": {\
         "annotations": { "grafana.app/folder": "ffec62bbr7v28d" }\
       }\
     }'
```

Response (201 Created)

```json
{
  "kind": "Folder",
  "apiVersion": "folder.grafana.app/v1beta1",
  "metadata": {
    "name": "cfjsa58pgf5z4a",
    "namespace": "default",
    "uid": "9qqppS8H2TyW0jMehIkRjGng6Xgpkg4iJcbfplkVaBUX",
    "creationTimestamp": "2026-04-21T18:58:24Z",
    "annotations": {
      "grafana.app/createdBy": "user:3",
      "grafana.app/updatedTimestamp": "2026-04-21T18:58:24Z"
    }
  },
  "spec": {
    "title": "my-new-folder",
    "description": ""
  }
}
```

The `metadata.name` value is the folder UID to use in all subsequent API calls for this folder.

### Rename a Folder

Updates the folder title. The `metadata.name` in the body must match the UID in the URL path.

```bash
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X PUT \
     "https://<your-instance>/grafana/apis/folder.grafana.app/v1beta1/namespaces/default/folders/cfjsa58pgf5z4a" \
     -d '{\
       "spec": { "title": "my-renamed-folder" },\
       "metadata": { "name": "cfjsa58pgf5z4a" }\
     }'
```

Response

```json
{
  "kind": "Folder",
  "apiVersion": "folder.grafana.app/v1beta1",
  "metadata": {
    "name": "cfjsa58pgf5z4a",
    "namespace": "default",
    "generation": 2,
    "creationTimestamp": "2026-04-21T18:58:24Z",
    "annotations": {
      "grafana.app/updatedTimestamp": "2026-04-21T18:58:34Z"
    }
  },
  "spec": {
    "title": "my-renamed-folder",
    "description": ""
  }
}
```

### Delete a Folder

Deletes a folder. The folder must be empty (no dashboards, alerts, or sub-folders) unless the underlying Grafana instance allows forced deletion. Kloudfuse blocks deletion of folders containing Kloudfuse objects (favorite facets, scheduled views, etc.).

```bash
curl -H "Authorization: Bearer <sa-token>" \
     -X DELETE \
     "https://<your-instance>/grafana/api/folders/cfjsa58pgf5z4a?forceDeleteRules=false"
```

Response

```json
{
  "message": "Folder deleted"
}
```

### Get Folder Item Counts

Returns the number of items of each type contained in the folder.

```bash
curl -H "Authorization: Bearer <sa-token>" \
  "https://<your-instance>/grafana/api/folders/ffec62bbr7v28d/counts"
```

Response

```json
{
  "alertrule": 0,
  "dashboard": 18,
  "folder": 0,
  "librarypanel": 0
}
```

## Folder Permissions

Folder permissions control which users, teams, and roles can view, edit, or administer a folder. The caller must have **Admin** permission on the folder to read or modify its permissions.

Permission levels are:

| Value | Effect |
| --- | --- |
| `Admin` | Full access including managing the folder’s own permissions. |
| `Edit` | Create, modify, and delete content within the folder. |
| `View` | Read-only access to the folder and its contents. |
| `""` (empty string) | Remove the permission assignment. |

### Get Folder Permissions

Returns all permission assignments for a folder.

```bash
curl -H "Authorization: Bearer <sa-token>" \
  "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d"
```

Response

```json
[\
  {\
    "id": 887,\
    "roleName": "managed:users:3:permissions",\
    "isManaged": true,\
    "isInherited": false,\
    "isServiceAccount": true,\
    "userId": 3,\
    "userLogin": "sa-1-test",\
    "permission": "Admin"\
  },\
  {\
    "id": 820,\
    "roleName": "basic:admin",\
    "isManaged": false,\
    "isInherited": false,\
    "isServiceAccount": false,\
    "builtInRole": "Admin",\
    "permission": "Admin"\
  },\
  {\
    "id": 44,\
    "roleName": "managed:builtins:editor:permissions",\
    "isManaged": true,\
    "isInherited": false,\
    "isServiceAccount": false,\
    "builtInRole": "Editor",\
    "permission": "Edit"\
  }\
]
```

Each entry includes:

| Field | Type | Description |
| --- | --- | --- |
| `builtInRole` | string | Present for role-based entries: `Admin`, `Editor`, or `Viewer`. |
| `userId` / `userLogin` | number / string | Present for user and service account entries. |
| `teamId` / `team` | number / string | Present for team entries. |
| `isInherited` | boolean | `true` if the permission is inherited from a parent folder. |
| `isServiceAccount` | boolean | `true` if the user entry is a service account. |
| `permission` | string | Effective permission level: `Admin`, `Edit`, or `View`. |

### Update a Built-in Role Permission

Sets the permission for all users with a given built-in role (`Admin`, `Editor`, or `Viewer`).

```bash
# Grant Viewer role View access
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d/builtInRoles/Viewer" \
     -d '{"permission": "View"}'

# Remove Editor role access (set to No Access)
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d/builtInRoles/Editor" \
     -d '{"permission": ""}'
```

Response

```json
{
  "message": "Permission updated"
}
```

### Update a Team Permission

Sets the permission for all members of a team. The team ID is the `local_grafana_id` returned by the [List Teams](https://docs.kloudfuse.com/platform/4.1.0/reference/api/teams/#teams-list) endpoint.

```bash
# Grant a team Edit access
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d/teams/4" \
     -d '{"permission": "Edit"}'

# Remove a team's access (empty string)
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d/teams/4" \
     -d '{"permission": ""}'
```

Response when setting a permission

```json
{
  "message": "Permission updated"
}
```

Response when removing a permission

```json
{
  "message": "Permission removed"
}
```

### Update a User Permission

Sets the permission for a specific user. Use the numeric user ID from **Admin > Users**.

```bash
curl -H "Authorization: Bearer <sa-token>" \
     -H "Content-Type: application/json" \
     -X POST \
     "https://<your-instance>/grafana/api/access-control/folders/ffec62bbr7v28d/users/12" \
     -d '{"permission": "View"}'
```

Response

```json
{
  "message": "Permission updated"
}
```

## Error Codes

| HTTP Status | Meaning |
| --- | --- |
| `200` | Success. |
| `201` | Resource created successfully. |
| `400` | Bad request — check the request body. Common cause: referenced team or user ID does not exist. |
| `401` | Missing or invalid `Authorization` header. |
| `403` | Token does not have sufficient permissions for the requested operation. |
| `404` | Folder or resource not found. |
| `409` | Conflict — folder cannot be deleted because it contains objects. |
| `500` | Internal server error.
