Scopes & Auth
Scopes, permissions, and tokens are Cinch's core access primitives. Together they answer three questions: where can you access,what can you do, and who are you.
The mental model
Scopes are the "where." A scope is a boundary that contains databases and child scopes. If you are not inside a scope, you cannot see anything in it.
Permissions are the "what." Three levels: read, write, admin. They control whether you can query data, modify data, or manage infrastructure (create databases, issue tokens).
Tokens are the "who." A token encodes both a scope (where) and a permission (what). Hand someone a token and they get exactly that access, nothing more.
Scopes: where you can access
Every database belongs to exactly one scope. Scopes nest up to 10 levels deep, forming a tree. A token for a parent scope grants access to everything in its descendants. A token for a child scope cannot see anything in its parent or siblings.
# Scope hierarchy
acme (org) / api (project) / production (environment)
│
├── scope: web-app
│ ├── db: sessions (redis)
│ └── db: cache (redis)
│
├── scope: agents
│ ├── db: shared-memory (redis)
│ │
│ ├── scope: agent-task-001
│ │ ├── db: scratch (redis)
│ │ └── db: findings (sql)
│ │
│ └── scope: agent-task-002
│ └── db: scratch (redis)
│
└── scope: analytics
└── db: events (sql)In this example, a token for the agents scope can see shared-memory,agent-task-001/*, andagent-task-002/*. But it cannot see web-app oranalytics. A token for agent-task-001 can only see its own two databases.
Permissions: what you can do
Every scope token has one of three permission levels:
| Level | Data access | Management |
|---|---|---|
| read | Read data from databases | List databases and scopes |
| write | Read and write data | List databases and scopes |
| admin | Read and write data | Create/delete databases and child scopes. Issue tokens. |
The most important rule: permissions only go down, never up. An admin can issue write tokens. A write token can issue read tokens. But a write token cannot issue admin tokens, and a read token cannot issue any tokens at all. Delegation never escalates privilege.
Tokens: who you are
Three token types serve different roles:
| Token | Format | Who holds it | What it does |
|---|---|---|---|
| API key | ck_live_... | Your backend, dashboard, CI | Full account access. Creates scopes, databases, and tokens. |
| Scope token | cinch_... | Agents, services, tenants | Access to one scope. Manages databases within that scope. |
| Database token | cinch_... | Redis/Bolt/HTTP connections | Access to one database. Auto-issued when you call db.url(). |
API keys and scope tokens are for managing databases (creating, listing, deleting) through the SDK or REST API. Database tokens are for using databases (reading and writing data) through Redis, Bolt, or HTTP clients. The SDK handles the exchange between them automatically: call db.url() and you get a database URL plus an auth token.
Putting it together
Here is all three primitives working together. A backend orchestrator creates a scope for an agent, provisions a database, issues a scoped token, and hands it off. The agent uses the token to access its databases. When the task is done, deleting the scope cleans up everything.
Orchestrator
from cinchdb import Cinch
# Backend holds an API key (full access)
client = Cinch(api_key="ck_live_...", org="acme")
# Create a scope for this agent task
scope = client.scope("agent-task-001", environment="production", project="api")
# Create a database inside the scope
db = scope.create_database(type="redis", name="scratch")
# Issue a write token scoped to this task
token_resp = scope.token(permission="write", expires_in_days=1)
# Hand the token to the agent
# The agent can read/write databases in this scope,
# but cannot create databases, access sibling scopes,
# or see anything outside this scope.
send_to_agent(token_resp["token"])Agent
import os
import redis
from cinchdb import Cinch
# Agent receives its scope token
agent = Cinch(scope_token=os.environ["CINCH_SCOPE_TOKEN"])
# See what databases are available
dbs = agent.scope_auth_databases()
# Connect to a database
db = agent.scope_auth_database("database-id")
r = redis.from_url(str(db.url()))
# Do work
r.hset("findings", "key-insight", "the answer is 42")
r.lpush("log", "analysis complete")Cleanup
# When the task is done, delete the scope
scope.delete()
# Everything inside is removed: databases, child scopes, tokens.
# Archived data in cold storage is cleaned up too.Credential safety
Connection URLs returned by the SDK are wrapped in a RedactedUrl object. When you pass it to a client library (like redis.from_url), it returns the full URL with the token. When you print or log it, the token is replaced with ***, so credentials never leak into logs or error reports.
Token expiry
expires_in_days when issuing scope tokens. Short-lived tokens limit the blast radius if a credential is compromised. For long-running services, use the SDK's automatic retry and refresh.See the Python SDK or TypeScript SDK docs for the full API.