> ## 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.

# Create User

Mint a per-user API key scoped to a single index. Requires RBAC enabled on the service (`CYBORGDB_SERVICE_ROOT_KEY` set) and the request must be authenticated with the root key.

<Note>See [Multi-Tenancy & RBAC](../../guides/advanced/multi-tenancy) for the full operator playbook.</Note>

## Authentication

Required — root API key in the `X-API-Key` header:

```http theme={null}
X-API-Key: cyborg_your_root_api_key_here
```

The legacy single API key (`CYBORGDB_API_KEY`) is **not** accepted on this route; it returns 403.

## Path Parameters

| Parameter    | Type     | Description                                   |
| ------------ | -------- | --------------------------------------------- |
| `index_name` | `string` | Name of the index the user will be scoped to. |

## Request Body

```json theme={null}
{
  "permissions": ["read", "write"],
  "index_key": "64_character_hex_string_representing_32_bytes"
}
```

<Note>For `POST`, the index key rides in the JSON body as `index_key` (alongside `permissions`). The sibling `GET /v1/indexes/{index_name}/users` and `DELETE /v1/indexes/{index_name}/users/{user_id}` endpoints have no request body, so they take the same key via the `X-Index-Key` header instead.</Note>

<Expandable title="parameters">
  <ParamField body="permissions" type="array[string]" required="true">
    Non-empty subset of `["read", "write"]`. The grant is enforced cryptographically by the service — the wrapped data-encryption keys that exist for a user *are* their permission set.
  </ParamField>

  <ParamField body="index_key" type="string">
    32-byte index KEK as a hex string. Required for SDK-supplied indexes (`provider: none`) so the service can unwrap the root DEK and re-wrap it under the new user. Omit for KMS-backed indexes — the service resolves the KEK via the stored `KMSBlob`.

    Note: even though `index_key` is accepted here, per-user keys only **work** against KMS-backed indexes (the service can't resolve the KEK for a user on later requests). See [the KMS-backed constraint](../../guides/advanced/multi-tenancy#kms-backed-constraint).
  </ParamField>
</Expandable>

## Response

```json theme={null}
{
  "user_id": "a1b2c3d4e5f6...",
  "api_key": "cdbk_..."
}
```

<Expandable title="response fields">
  <ResponseField name="user_id" type="string">
    Hex-encoded identifier for the new user.
  </ResponseField>

  <ResponseField name="api_key" type="string">
    The user's API key. Begins with `cdbk_`. **Returned exactly once and never stored** — capture it now, it cannot be recovered.
  </ResponseField>
</Expandable>

<Warning>
  The returned `api_key` is shown only in this response and is never persisted by the service. If you lose it, revoke the user (`DELETE`) and mint a new one.
</Warning>

## Exceptions

* `400`: `permissions` is missing, empty, or contains values outside `{"read", "write"}`.
* `401`: Authentication failed (invalid root API key).
* `403`: RBAC is not enabled (`CYBORGDB_SERVICE_ROOT_KEY` unset), or the caller is not using the root key.
* `404`: Index not found.
* `500`: Internal server error.

## Example Usage

```bash theme={null}
curl -X POST "http://localhost:8000/v1/indexes/documents/users" \
     -H "X-API-Key: cyborg_your_root_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{
       "permissions": ["read", "write"]
     }'
```

**Read-only user:**

```bash theme={null}
curl -X POST "http://localhost:8000/v1/indexes/documents/users" \
     -H "X-API-Key: cyborg_your_root_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{
       "permissions": ["read"]
     }'
```

**SDK-supplied index (legacy path):**

```bash theme={null}
curl -X POST "http://localhost:8000/v1/indexes/documents/users" \
     -H "X-API-Key: cyborg_your_root_api_key_here" \
     -H "Content-Type: application/json" \
     -d '{
       "permissions": ["read", "write"],
       "index_key": "your_64_character_hex_key_here"
     }'
```
