Seaport Sandbox Validator Access
The Seaport Devnet validator is a hosted Canton 3.x participant on the Canton Devnet global synchronizer. Every idea in this archive ships with these endpoints baked in — no signup, no local participant, no synchronizer setup. Tokens are issued by an OIDC provider and last 8 hours; the validator accepts them as Bearer tokens on HTTP and as the daml.ws.auth / jwt.token.<token> subprotocols on websockets.
Endpoints
The runtime client_secret is provisioned for the workspace as the CANTON_DEVNET_OIDC_RUNTIME_CLIENT_SECRET environment variable. It is shared across the hackathon and only valid against this devnet — never use it in production.
1 · Exchange credentials for a Bearer token
curl -X POST 'https://auth.sandbox.fivenorth.io/application/o/token/' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'grant_type=client_credentials' \ -d 'client_id=validator-devnet-m2m' \ -d 'client_secret=$CANTON_DEVNET_OIDC_RUNTIME_CLIENT_SECRET' \ -d 'audience=validator-devnet-m2m' \ -d 'scope=daml_ledger_api'
Returns { access_token, expires_in: 28800, token_type: "Bearer" }. Cache in memory; refresh before expires_in elapses.
2 · Call the JSON Ledger API v2
curl 'https://ledger-api.validator.devnet.sandbox.fivenorth.io/v2/state/active-contracts?pageSize=25' \
-X POST \
-H 'Authorization: Bearer <ACCESS_TOKEN>' \
-H 'Content-Type: application/json' \
-d '{ "filter": { "filtersByParty": {} }, "verbose": false }'Common paths: /v2/dars (upload DAR), /v2/parties (allocate party), /v2/users (create user), /v2/users/{id}/rights (grant CanActAs), /v2/commands/submit-and-wait-for-transaction (exercise a Daml choice and get the updateId + events).
3 · Stream live updates over WebSocket
const ws = new WebSocket( "wss://ledger-api.validator.devnet.sandbox.fivenorth.io/v2/updates/flats", ["daml.ws.auth", "jwt.token." + accessToken] );
The validator authenticates websocket connections via subprotocols, not headers. Pass daml.ws.auth and a second subprotocol of the form jwt.token.<ACCESS_TOKEN>.
Four invariants
- Two token subjects, two purposes. A bootstrap client uploads DARs, allocates parties, and grants rights. A runtime client signs every command and ledger read.
- Bootstrap must be idempotent. Treat 409 / already-exists as success; persist the logical-name → fully-qualified party-id map.
userId === token.sub. On Devnet the validator enforces that theuserIdin every command equals the runtime token'ssubclaim. Decode the JWT to derive it.- DAR upgrade = rename, not bump. Bumping a package version on a breaking schema change fails with
KNOWN_PACKAGE_VERSION. For hackathon iteration, bump the package name instead.
Full Canton documentation: https://docs.canton.network/llms-full.txt ↗