Skip to content
Tenzro
Documentation menu
Build and operate

API keys

Operator-issued API keys sent as X-Tenzro-Api-Key: scopes, key classes, tiers, issuance, self-service revocation and error codes.

An API key is a credential that one node operator issues to a tenant: a developer, a team, an agent or a machine they have an agreement with. It is sent as the X-Tenzro-Api-Key header and grants access to a set of scopes on that operator's node, within a rate budget.

API keys are per operator. Each operator issues, stores and revokes keys on their own node with their own admin token; there is no network-wide key authority. A key from one RPC provider means nothing to another.

You do not need an API key to use Tenzro. Reads are open, owner actions are authorised by your own signature, and paid routes accept per-request payment over HTTP 402. A key is for when you and a provider have agreed terms in advance: a subscription, a private model, tenant storage or a database. See RPC access.

Format

Keys look like tnz_<base64url>. The plaintext is returned once, at creation. The node stores only a SHA-256 digest, compares it in constant time and never logs it.

bash
curl -s https://rpc.tenzro.xyz/v1/chat/completions \
  -H 'content-type: application/json' \
  -H "X-Tenzro-Api-Key: $TENZRO_API_KEY" \
  -d '{"model":"<model id>","messages":[{"role":"user","content":"Hello"}]}'

The SDKs and the CLI read the key from TENZRO_API_KEY.

Scopes

A key carries one or more scopes. A key with no scopes is invalid.

ScopeGrants
inferenceChat, embeddings and the other model endpoints, when the operator gates inference
storageTenant object storage: /v1/files and the file methods. The key's subject owns every file it uploads.
databaseManaged databases: /v1/databases and the database methods, inside the tenant's own isolation boundary
evm, svmContract calls and program execution, when the operator gates them
teeAttestation and proof verification, when the operator gates them
bridgeCross-chain dispatch through the operator's relays
cantonDAML ledger access through a Canton participant the operator runs. See Canton.
chainlinkBridge-fee quotes backed by the operator's price feeds
issuerOperating a stable unit registered on the node

storage and database are always enforced, because the key's subject is what makes a tenant the owner of their data. The other scopes are gates an operator can choose to switch on for services they monetise or rate limit.

Publishing to the marketplaces (agents, skills, tools, workflows) needs no key and no approval from any operator.

Classes

The class decides who may revoke a key.

ClassRevoked byUse for
subject (default)The operator, or the key holder themselvesKeys issued to developers and customers
operator_internalThe operator onlyThe operator's own automation and monitoring
operator_protectedNobody over RPC; rotated by changing the operator's secret and restartingKeys the node itself depends on. Needs confirm_operator_protected.

Tiers

The tier decides how much of a reachable surface a key gets over a sliding 60-second window.

TierBudgetWrites
freeLowestRefused: read-only evaluation access
standardHigherAllowed
priorityHighestAllowed

A key over budget gets -32005 with retry_after_ms, requests_per_minute and tier in the error data.

Issue a key (operator)

Issuing, listing and revoking keys are admin methods: they need your node's X-Tenzro-Admin-Token.

bash
tenzro admin api-key create \
  --label acme-prod \
  --subject did:tenzro:human:... \
  --scope inference --scope storage \
  --tier standard \
  --rpc http://127.0.0.1:8545

tenzro admin api-key list
tenzro admin api-key revoke --key-id <key-id>

Over JSON-RPC:

bash
curl -s http://127.0.0.1:8545 \
  -H 'content-type: application/json' \
  -H "X-Tenzro-Admin-Token: $TENZRO_ADMIN_TOKEN" \
  -d '{
    "jsonrpc": "2.0", "id": 1,
    "method": "tenzro_createApiKey",
    "params": {
      "label": "acme-prod",
      "subject": "did:tenzro:human:...",
      "scopes": ["inference", "storage"],
      "class": "subject",
      "tier": "standard"
    }
  }'

The response contains the plaintext key (shown once) and a key_id. With the TypeScript SDK:

ts
const created = await client.apiKey.create({
  label: "acme-prod",
  subject: "did:tenzro:human:...",
  scopes: ["inference", "storage"],
  tier: "standard",
});

Self-service (key holder)

A holder of a subject key can see and revoke their own keys without asking the operator. Both calls are authorised by the key itself and return only keys with the same subject.

bash
tenzro key list-mine
tenzro key revoke-mine --key-id <key-id>
bash
curl -s https://rpc.tenzro.xyz \
  -H 'content-type: application/json' \
  -H "X-Tenzro-Api-Key: $TENZRO_API_KEY" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tenzro_listMyApiKeys","params":{}}'

Each row describes everything the node will enforce for that key: scopes, class, tier, requests_per_minute, allows_write and active. A tenant can answer "what may I do here" without asking.

What keys do not do

  • They do not replace signatures. An owner action, such as a transfer, still needs a signature from the paying account; a key only admits the caller to the operator's services.
  • They are not network credentials. Validator set, fees and protocol parameters change only through governance, whatever key is presented.
  • They are not the admin token, and they are not service keys. A service key (X-Tenzro-Service-Key) decides whether a caller may reach a private node at all; an API key decides what an admitted caller may do.

Methods

MethodAccess
tenzro_createApiKey, tenzro_listApiKeys, tenzro_revokeApiKeyAdmin
tenzro_listMyApiKeys, tenzro_revokeMyApiKeyThe key holder

Errors

CodeMeaning
-32001Admin token missing or wrong
-32004Key missing, unknown or revoked; key lacks the scope; tier is read-only and the method writes; or the key is not yours
-32005Over the tier's rate budget
-32602Invalid parameters, such as an unknown tier, or operator_protected without confirmation

Running a node that issues keys to customers? See Run an RPC provider.