Canton
Reach Canton networks through a Tenzro node: party-bound API keys, per-tenant isolation, mandate-bound agent writes and operator controls.
Canton is the privacy-preserving network that runs DAML contracts. On Tenzro Network 1, Canton is an operator-provided integration: a node operator connects the node to one or more Canton participants (Canton 3.5 and later, JSON Ledger API v2) and offers access to developers and agents through scoped API keys. The node handles party resolution, per-tenant isolation and TNZO settlement, so an application or agent talks to Canton with the same client it uses for the rest of Tenzro.
What you can do
| Task | CLI | JSON-RPC |
|---|---|---|
| Check the connection | tenzro canton health, tenzro canton version | tenzro_canton_health, tenzro_canton_version |
| See your user and party | tenzro canton my-user | tenzro_canton_getMyUser |
| List synchronizers and parties | tenzro canton domains, tenzro canton connected-synchronizers, tenzro canton parties | tenzro_listCantonDomains, tenzro_canton_connectedSynchronizers, tenzro_canton_listParties |
| List active contracts | tenzro canton contracts | tenzro_listDamlContracts |
| Watch one party's contracts | tenzro canton watch-party | tenzro_canton_watchParty |
| Submit a create or exercise | tenzro canton submit | tenzro_submitDamlCommand |
| Agent write under a mandate | tenzro canton submit-with-mandate | tenzro_canton_submitWithMandate |
| Upload a DAR, list packages | tenzro canton upload-dar, tenzro canton packages | tenzro_canton_uploadDar, tenzro_canton_listPackages |
| Canton Coin balance and fee schedule | tenzro canton coin-balance, tenzro canton fee-schedule | tenzro_canton_coinBalance, tenzro_canton_feeSchedule |
| Look up a transaction | tenzro canton get-transaction | tenzro_canton_getTransaction |
| Your own usage counters | tenzro canton my-analytics | tenzro_canton_getMyAnalytics |
Access
Every Canton call carries an API key with the canton scope, issued by the operator of the node you connect to. Send it as the X-Tenzro-Api-Key header, the api_key JSON-RPC parameter, or --api-key (or TENZRO_API_KEY) on the CLI.
A key gates Canton because the Canton ledger sits outside Tenzro and the node reaches it with credentials the operator supplies. Keys do not gate the rest of the network: publishing an agent, skill, workflow or MCP server stays permissionless. See API keys and RPC access.
Network selection. A node can serve several Canton networks, and a key is authorised for some of them. Name the target with the canton_network parameter, the X-Canton-Network header or --canton-network. If you name none, the node uses your key's only network, or else its own default. A key authorised for several networks that names none gets error -32004 listing the networks it may use.
Rate tiers. Each key has a tier that bounds requests over a sliding 60-second window: free (read-only), standard and priority. Over budget returns -32005 with retry_after_ms, requests_per_minute and tier. Agent writes under a mandate need standard or above.
Tenancy and parties
Each developer team or agent is isolated behind its own key, and each key is bound to its own Canton user and party.
- When an operator issues a key with a Canton binding, the node allocates a party for the tenant, registers a Canton user with that party as its primary party, and grants it the right to act as that party, in one step. Re-issuing for an existing user reuses its party.
- On every call, the node uses the key's primary party as
actAsand as the requesting party for reads. A key without a Canton binding cannot submit; the operator's own party is never used on a tenant's behalf. - To act as another party, pass
act_as(or--act-as). The node allows it only if the party is on the key'scan_act_as_partieslist. Reads of another party need it oncan_read_as_parties. Anything else returns-32004. - Canton enforces the same rights again on its side, so a misconfigured client cannot exceed them.
Operators who need a dedicated OAuth client per tenant can enable per-tenant identity providers. The node then creates an upstream OAuth client for each new key, mints and caches the tenant's Canton token on the server side, and forwards it on the tenant's calls. The tenant's only credential is its Tenzro API key; revoking the key removes the upstream client and the Canton rights together. Tenants with their own identity provider can instead send a token in the X-Canton-Auth: Bearer <jwt> header.
Agents on Canton
Autonomous agents can write to Canton under a spending mandate, so a principal stays in control of what the agent commits to. An agent presents two things on each write:
- A key whose
can_act_as_partiesincludes the party the agent acts for. - An AP2 mandate pair: a checkout credential signed by the principal and a payment credential signed by the agent.
The node validates the mandate pair, the agent's delegation scope and the runtime spending policy, and optionally an on-chain escrow, before it forwards the command. Any failed check stops the write. The response carries both the mandate receipt and the Canton transaction.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tenzro_canton_submitWithMandate",
"params": {
"mandate": {
"checkout": { "...": "AP2 checkout credential" },
"payment": { "...": "AP2 payment credential" }
},
"command_type": "create",
"template_id": "ComputeJob:Job",
"create_arguments": {
"buyer": "Buyer::1220ab...",
"provider": "Provider::1220cd...",
"gpuHours": "12.0"
}
}
}From the CLI, pass the two credentials as files:
tenzro canton submit-with-mandate \
--checkout-vdc ./checkout.json --payment-vdc ./payment.json \
--command-type create --template ComputeJob:Job \
--create-arguments '{"buyer":"Buyer::1220ab...","provider":"Provider::1220cd...","gpuHours":"12.0"}' \
--api-key "$TENZRO_API_KEY" --rpc https://rpc.tenzro.xyzFor reads, an agent uses tenzro_canton_watchParty with a party and optional template filter; the key must be allowed to read as that party. See Agent commerce for mandates and spending policies.
SDKs
The TypeScript and Rust tenzro-sdk packages expose a Canton client with the same methods and the same act_as override:
import { TenzroClient } from "tenzro-sdk";
const client = new TenzroClient({ endpoint: "https://rpc.tenzro.xyz" });
const receipt = await client.canton.submitWithMandate(mandate, {
command_type: "create",
template_id: "ComputeJob:Job",
create_arguments: args,
});Operator controls
Operators manage Canton through admin methods, which need the node's admin credential and are never reachable with a tenant key:
- Party and rights management:
tenzro canton allocate-party,tenzro canton grant-rights,tenzro canton list-rights. - Identity providers:
tenzro_canton_createIdp,tenzro_canton_listIdps,tenzro_canton_deleteIdp. - Workflow anchoring:
tenzro_mirrorWorkflowToCantonandtenzro_mirrorObligationToCantonrecord Tenzro workflows and their obligations as contracts on a Canton synchronizer. - Usage across tenants:
tenzro_canton_listApiKeyAnalyticsandtenzro_canton_aggregateAnalyticsreturn per-key call and error counts. Tenants read only their own withtenzro_canton_getMyAnalytics. - Reconnecting a synchronizer after an outage or planned disconnection.
Running Canton access is one way an operator can earn from a node; see Operators and roles.