Tether
DocsGitHub

Core concepts

Tenants and scope

Every tool call, staged write, ledger row and stored memory is scoped by an identity. That identity is set once, from your API key, and nothing downstream can change it.

The rule

Scope comes from the credential. Never from the request body. Never from the model.

This is the entire multi-tenant boundary. A model can hallucinate an organization id into its tool arguments; a compromised client can put one in a request body. Neither reaches your endpoint, because Tether builds the outbound envelope from the authenticated key and ignores everything else.

// This is accepted. The organizationId is silently ignored.
{ "prompt": "show me open tickets", "organizationId": 999 }

The AiChatRequest type still carries organizationId and locationId fields. They are legacy, they are not read, and no value you put in them has any effect. Treat them as absent.

The three levels

LevelSourceMeaning
TenantThe API keyWhich of your customers is asking
ScopeX-Tether-Scope-IdA narrower boundary inside that customer — a site, ledger, region, workspace
UserX-Tether-User-IdThe individual acting, for attribution and confirmation

Only the tenant is mandatory. Scope and user are optional headers you set per request.

curl -X POST https://api.trytether.ge/v1/chat \
  -H "X-Api-Key: $TETHER_SECRET_KEY" \
  -H "X-Tether-Scope-Id: 9" \
  -H "X-Tether-User-Id: 431" \
  -H "X-Tether-User-Role: shift_lead" \
  -d '{ "prompt": "what is still open?" }'

What each level actually gates

Tenant decides the tool catalog, the tool endpoint and signing secret, the plan and its ceilings, the spend budget, the conversation history, and the knowledge corpus. Two tenants share nothing.

Scope is passed through to your endpoint as tenant.scope_id, and gates tools registered requires_scope: true. A tool that cannot answer without knowing which site should declare that, so the model asks rather than guessing across all of them.

User is passed through, attributed on staged writes, and used for durable preference memory. Preferences learned from one user are not injected into another's turns.

Naming

The wire format uses organization_id and scope_id. The names are older than the concepts they now carry: organization_id is the tenant, and scope_id is whatever subdivision of that tenant you decide it is.

What Tether stores against a tenant

Conversations, staged actions and their execution records, the spend ledger, request telemetry, extracted user preferences, and any documentation you ingest for retrieval.

Not your business records. Tether has no table for your orders, customers, or inventory, because it never receives them — only the tool results it passes to the model within a turn.