---
title: Isolate tenants and issue keys
description: Provision tenant namespaces and delegate limited access.
doc_version: 0.1.0-preview
last_updated: 2026-09-14
---

# Isolate tenants and issue keys

Provision a namespace for each tenant, issue a key for its services, and delegate access to a specific collection. Keep cluster credentials in your provisioning service.

## Choose the boundary

*Illustration: A cluster key provisions tenant namespaces. A namespace key operates inside one tenant. A collection key further limits the resources and actions available to a service.*

A namespace separates one tenant’s collections from another’s. Decide the namespace after your application authenticates the customer. Do not accept a customer-supplied namespace without checking that relationship.

Use a cluster key to [create the namespace](/engine/reference/create-namespace). Set `exist_ok: true` when provisioning should return an existing namespace. Keep its immutable ID and name in your tenant record.

## Issue a namespace key

**POST https://engine.example.com/keys**

```http
POST /keys HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
Content-Type: application/json

{
  "name": "acme-service",
  "scope": {
    "kind": "namespace",
    "namespace": "acme",
    "actions": [
      "read",
      "write",
      "search",
      "query"
    ]
  }
}
```

**201 Created · secret returned once**

```json
{
  "id": "key_01J8Z3K4N5P6Q7R8S9T0V1W2X3",
  "name": "acme-service",
  "prefix": "gek_",
  "secret": "<NEW_ENGINE_API_KEY>",
  "scope": {
    "kind": "namespace",
    "namespace": "acme",
    "actions": [
      "read",
      "write",
      "search",
      "query"
    ]
  },
  "created_at": "2026-10-06T12:00:00Z"
}
```

Replace `<NEW_ENGINE_API_KEY>` with the actual secret from the response. Store it immediately in the service’s secret store. Retain the separate `key_` ID for management. A later list request cannot recover the secret.

A namespace key requires explicit actions. `write` includes `read`; `search` and `query` are independent. Include only the actions the tenant service needs.

## Delegate collection access

A namespace key can issue a collection key in its own namespace. The new action list must be a subset of the creating key’s effective actions. A collection key cannot issue another key.

**POST https://engine.example.com/keys**

```http
POST /keys HTTP/1.1
Host: engine.example.com
Authorization: Bearer <ACME_NAMESPACE_KEY>
Content-Type: application/json

{
  "name": "incident-search",
  "scope": {
    "kind": "collection",
    "namespace": "acme",
    "collections": [
      "incident-logs"
    ],
    "actions": [
      "search"
    ]
  }
}
```

The result has the same key shape as the namespace example, with the requested collection scope. This key can Search `incident-logs`. It cannot Query, read file content, write files, or access another collection.

| Request | Result with this Search-only key |
| --- | --- |
| Search incident-logs | Allowed. |
| Query incident-logs | 403 forbidden: missing query action. |
| Read a file in incident-logs | 403 forbidden: missing read action. |
| Search another collection | 404 not_found: outside resource scope. |
| Create a collection | Forbidden for a collection key. |

## Replace and revoke keys

Keys remain valid until revoked. Create a replacement key, update the service, and confirm its requests succeed. Then revoke the previous key with its management ID.

**DELETE https://engine.example.com/keys/key_01J8Z3K4N5P6Q7R8S9T0V1W2X3**

```http
DELETE /keys/key_01J8Z3K4N5P6Q7R8S9T0V1W2X3 HTTP/1.1
Host: engine.example.com
Authorization: Bearer <GRAPHON_ENGINE_API_KEY>
```

**204 No Content**

```http
HTTP/1.1 204 No Content
```

Revocation takes effect immediately. Requests using that secret return `401 unauthenticated`. Deleting a key does not delete its namespace or files.

Read [Authentication](/engine/reference/authentication) for the exact scope and action contracts. Add [access rules](/engine/guides/access-rules) when users within a tenant need different retrieval permissions.
## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
