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

# User Management (RBAC)

When the service runs with `CYBORGDB_SERVICE_ROOT_KEY` set, `*EncryptedIndex` can create, list, and revoke per-index users. These methods require a client created with the root key. They work on both KMS-backed indexes and indexes created with an `IndexKey`.

<Note>See [Multi-Tenancy & RBAC](../../guides/advanced/multi-tenancy) for the operator-side playbook (modes, key kinds, SDK-supplied indexes).</Note>

## CreateUser

Creates a user scoped to this index and returns their API key.

```go theme={null}
func (e *EncryptedIndex) CreateUser(ctx context.Context, permissions []string) (*CreatedUser, error)
```

### Parameters

| Parameter | Type | Description |
| - | - | - |
| `ctx` | `context.Context` | Context for cancellation and deadlines. |
| `permissions` | `[]string` | Non-empty subset of `{"read", "write"}`. |

### Returns

`*CreatedUser`:

| Field | Type | Description |
| - | - | - |
| `UserID` | `string` | Hex identifier for the new user. |
| `APIKey` | `string` | The user's API key, starting with `cdbk_`. |

<Warning>The service returns `APIKey` only in this response and never stores it. Give it to the user over a secure channel and don't log it. If it's lost, delete the user and create a new one.</Warning>

### Example

```go theme={null}
package main

import (
    "context"
    "encoding/hex"
    "fmt"
    "log"

    "github.com/cyborginc/cyborgdb-go"
)

func main() {
    ctx := context.Background()
    rootKey := "your-service-root-key"

    key, err := hex.DecodeString("your-64-character-hex-key")
    if err != nil {
        log.Fatal(err)
    }

    admin, err := cyborgdb.NewClient("http://localhost:8000", rootKey)
    if err != nil {
        log.Fatal(err)
    }
    index, err := admin.LoadIndex(ctx, "documents", key)
    if err != nil {
        log.Fatal(err)
    }

    user, err := index.CreateUser(ctx, []string{"read", "write"})
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(len(user.UserID), user.APIKey[:5])
    // Output: 32 cdbk_

    // The user connects with their own key
    userClient, err := cyborgdb.NewClient("http://localhost:8000", user.APIKey)
    if err != nil {
        log.Fatal(err)
    }
    _ = userClient
}
```

***

## ListUsers

Lists the users created for this index.

```go theme={null}
func (e *EncryptedIndex) ListUsers(ctx context.Context) ([]UserInfo, error)
```

### Returns

A `[]UserInfo`, each with `UserID string` and `Permissions []string` (a subset of `{"read", "write"}`).

### Example

```go theme={null}
if _, err := index.CreateUser(ctx, []string{"read"}); err != nil {
    log.Fatal(err)
}

users, err := index.ListUsers(ctx)
if err != nil {
    log.Fatal(err)
}
for _, u := range users {
    fmt.Println(u.Permissions)
}
// Output: [read]
```

<Note>Deleting an index doesn't delete its user records. If you create a new index with the same name, `ListUsers` on it still returns the old users. They can't read the new index, because their keys don't unwrap its data key; delete them with `DeleteUser`.</Note>

***

## DeleteUser

Revokes a user. Their access keys for this index are erased, so their `cdbk_` key stops working on the next request.

```go theme={null}
func (e *EncryptedIndex) DeleteUser(ctx context.Context, userID string) error
```

### Parameters

| Parameter | Type | Description |
| - | - | - |
| `ctx` | `context.Context` | Context for cancellation and deadlines. |
| `userID` | `string` | `UserID` from `CreateUser` or `ListUsers`. Deleting an ID that doesn't exist succeeds without an error. |

### Example

```go theme={null}
user, err := index.CreateUser(ctx, []string{"read"})
if err != nil {
    log.Fatal(err)
}
if err := index.DeleteUser(ctx, user.UserID); err != nil {
    log.Fatal(err)
}

users, err := index.ListUsers(ctx)
if err != nil {
    log.Fatal(err)
}
fmt.Println(len(users))
// Output: 0
```

***

## Errors

<AccordionGroup>
  <Accordion title="*AuthenticationError">
    The client isn't using the root key (HTTP `403`), or its `apiKey` is invalid (HTTP `401`).
  </Accordion>

  <Accordion title="*ValidationError">
    `permissions` is empty or contains a value other than `"read"` or `"write"`, or `userID` isn't hex (HTTP `400`).
  </Accordion>

  <Accordion title="*NotFoundError">
    The index doesn't exist (HTTP `404`).
  </Accordion>

  <Accordion title="*ServiceError / *TransportError">
    The service returns `5xx` or can't be reached.
  </Accordion>
</AccordionGroup>

See [Errors](../errors).


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