Blueprint Canton Chain API

The complete Canton Network transaction record over one REST API. Every Canton Coin transaction since genesis (June 2024) is indexed on Blueprint's own validator infrastructure and exposed with per-party resolution — the query surface the chain itself does not offer.

Canton's public Scan API serves a single global feed with no per-party filter, and a participant's Ledger API only sees parties it hosts. Blueprint's index closes that gap: any transaction, any party, any balance — cursor-paginated, filterable, and seconds behind the chain head.

What you can query

  • Global feed — hundreds of millions of transactions from genesis, filterable by type, mining round, or calendar day.
  • Any party's history — complete, in either direction, with the party's role in every transaction. No wallet, node, or hosting relationship required.
  • Live balances & holdings — point-in-time ACS snapshots: unlocked/locked coin, accrued holding fees, active holding contracts.
  • Rounds, names, network — mining-round activity, the ANS directory, DSO and super-validator metadata, current CC fee configuration.
  • Aggregates & market data — daily transaction and CC-volume series, plus CC price and market cap.

How it works

CANTONglobal feed VALIDATOR+ cc-indexer POSTGRES550M+ rows, per-party ccscan APIread-only REST YOUR APP ~seconds behind normalize GET · JSON SV SCAN API — live state balances · ANS · network
The global feed is ingested continuously (~seconds behind head), normalized per party into Postgres, and served read-only. Point-in-time state — balances, holdings, ANS, network config — is passed through live from the Super Validator Scan API.
Base URL: https://ccscan.xyz — all endpoints are read-only GETs returning JSON. Machine-readable spec at /openapi.json, interactive explorer at /api-docs/.

Getting Started

No SDK or signup needed to evaluate — the API speaks plain HTTPS + JSON:

# Chain head + the 12 newest transactions curl -s https://ccscan.xyz/api/overview # Page the global feed, newest first curl -s "https://ccscan.xyz/api/txs?limit=50" # One transaction, by seq or event id curl -s https://ccscan.xyz/api/tx/320000000 # Find a party, then pull its full history and live balance curl -s "https://ccscan.xyz/api/party/search?q=cumberland" P="Cumberland-1::12201aa8a23046d5740c9edd58f7e820c83e7f5c58f25551f955f3252d3a04240860" curl -s "https://ccscan.xyz/api/party/$P/txs?before_seq=0&limit=100" curl -s "https://ccscan.xyz/api/party/$P/balance"

Reconciliation loop in four lines: read next_after_seq from each page and persist it — the cursor is stable across restarts and retries.

after=0 while true; do page=$(curl -s "https://ccscan.xyz/api/party/$P/txs?after_seq=$after&limit=100") # process $page, then: after=$(echo "$page" | jq .next_after_seq) [ "$(echo "$page" | jq .count)" = 0 ] && sleep 30 done

Authentication & Plans

Browsing is open — the API answers unauthenticated requests at an anonymous, per-IP rate so the explorer and quick evaluation just work. For production and programmatic use, authenticate with an API key to unlock a higher plan.

Send your key on every request as either header:

curl -H "Authorization: Bearer cck_your_key_here" \ https://ccscan.xyz/api/overview # or curl -H "X-API-Key: cck_your_key_here" \ https://ccscan.xyz/api/overview

Plans

TierRate limitIncluded volumeFor
Anonymous300 req/min (per IP)Browsing & evaluation — no key
Free300 req/min10,000/day · 150,000/moPrototyping & low-volume apps
Pro3,000 req/minUncappedProduction integrations
Enterprise30,000 req/minUncappedHigh-volume / dedicated workloads

Create a key on the pricing page — passkey sign-in, no card needed for Free. Live tier details are always at GET /api/plans. Custom limits, SLAs, or dedicated capacity? Contact Blueprint.

Subscriptions & secure checkout

Free keys issue instantly with just an email. Paid plans (Pro and Enterprise) are purchased through Stripe Checkout — the same PCI-DSS-compliant, embedded payment flow used across fintech. Card details are entered directly into Stripe and never touch ccscan's servers; we only ever store a Stripe customer and subscription identifier. Pay by card, Link, Cash App Pay, Klarna, or US bank (ACH).

The instant payment succeeds your account is upgraded and your API key is issued. For security only a hash of the key is stored, so the raw key is shown once at checkout — and you can create or copy keys anytime from your dashboard. Fulfillment is confirmed server-side by a signature-verified Stripe webhook, so your upgrade lands even if you close the tab.

Subscriptions are month-to-month with no lock-in. Manage your card, switch plans, download invoices, or cancel anytime from the billing portal on your dashboard — cancellation keeps your access through the end of the paid period, then reverts to Free.

Rate-limit headers

Every API response reports your current budget:

HeaderMeaning
RateLimit-LimitRequests allowed in the current window
RateLimit-RemainingRequests left in the window
RateLimit-ResetSeconds until the window resets
X-PlanThe plan applied to this request
X-Quota-Daily-Limit / -RemainingIncluded daily volume & what's left (quota-capped plans)
X-Quota-Monthly-Limit / -RemainingIncluded monthly volume & what's left (quota-capped plans)
Exceeding your per-minute limit returns 429 Too Many Requests with a Retry-After header (seconds); an exhausted daily or monthly quota also returns 429, naming the window that resets it. An invalid or revoked key returns 401. Quotas pool across all keys on one account — when Free volume gets tight, Pro removes the caps.

Cursors & Pagination

Every transaction carries a monotonic integer seq assigned at ingest — the universal cursor. List endpoints return up to limit rows (max 100) and a cursor for the next page:

DirectionRequest paramResponse cursorSemantics
Newest firstbefore_seqnext_before_seqRows with seq < before_seq; 0 = start at the newest
Oldest first (party history)after_seqnext_after_seqRows with seq > after_seq; 0 = start at genesis
after_seq · oldest first (party history) GENESIS HEAD seq 0 seq N · live one page · ≤ 100 before_seq=0 · newest first
One monotonic cursor, two directions: before_seq walks backward from the head (start at 0), after_seq walks forward from genesis. Chain the returned next_*_seq to fetch the next page.
  • Cursors are deterministic: no gaps, no overlap, safe to chain across retries.
  • count: 0 means the range is exhausted (head reached, or the party's first transaction).
  • after_seq and before_seq are mutually exclusive — sending both returns 400.

Transactions

GET/api/txs

The global feed, newest first. Filters compose freely:

ParamTypeDescription
before_seqintCursor; 0/omitted = newest
typeenumtransfer · mint · tap · abort_transfer_instruction
roundintLimit to one mining round
daydateJump to a UTC day (YYYY-MM-DD) — resolved by binary search over the seq key, ~30 index probes
limitintDefault 25, max 100
GET/api/tx/{key}

One transaction by seq (digits) or full event id. Returns the list shape plus detail — the complete financial body: sender with input amount and fees, every receiver with amounts and receiver fees, balance changes with per-party deltas and holding-fee rates, transfer kind, and the ledger offset.

Parties

Parties are Canton identities of the form name::fingerprint. URL-encode the full id in paths. Over 420,000 parties have appeared on-chain; all are queryable.

GET/api/party/search?q=…

Case-insensitive substring search over every party ever seen (min 2 chars, up to 50 matches).

GET/api/parties/notable

A curated starting set for discovery: Blueprint's validator, every super validator, and featured-app providers — each with a display name and a tag (validator / super validator / featured app).

GET/api/party/{party}/summary

First/last activity with seqs, transaction count (exact to 100,000, then tx_count_capped: true), and the party's ANS entry when registered.

GET/api/party/{party}/txs

The party's complete history from genesis, forward (after_seq) or backward (before_seq), optionally filtered by type. Each row adds roles — how this party appears in that transaction (sender / receiver / balance_change).

GET/api/party/{party}/balance

Live balance at the most recent valid ACS snapshot: total_unlocked_coin, total_locked_coin, total_coin_holdings, accrued holding fees, and total_available_coin (holdings − fees). Amounts are decimal strings with 10 dp. summary: null = no CC held at the snapshot.

GET/api/party/{party}/holdings

The active Amulet holding contracts behind that balance (amounts, lock state), page size 200 with the Scan after token.

GET/api/party/{party}/validator

Whether the party is a validator, super-validator, and/or app-provider (from the reward types it collects), plus a sync indicator: active when ccscan’s index is within a few rounds of the network head round, inactive when the index has fallen further behind, or unknown when the party is not a validator or the network tip is unavailable (rounds_behind reports the gap). It also returns recent reward performance (a fast bounded scan of the latest transactions) and exact lifetime reward totals (a cached full-history scan; lifetime.complete=false only if the history is too large to total in real time). Canton issues no validator liveness rewards, so liveness is measured by round progress, not reward recency.

Balances vs. history: balances are point-in-time snapshots; the transaction index stores per-transaction balance changes. Together they give a full audit trail: reconcile any party's balance from genesis, then verify against the live snapshot.

Rounds

GET/api/round/{round}

One mining round (~10 minutes each): tx_count, first/last seq, start and end times, plus a newest-first page of the round's transactions (same cursor semantics). Some automation records carry round 0 — they are indexed but do not belong to a user-facing round.

Names (ANS)

GET/api/ans?prefix=…&page_size=…

Canton Name Service directory entries — name, the user party id it resolves to, url/description, and expiry. Prefix filter is lowercased server-side; page size up to 1000. Reverse lookup (party → name) is included in the party summary.

Network

GET/api/network

One call for network metadata: DSO state (party id, voting threshold, SV node states), the super-validator scan directory, Splice instance names, Scan version, and the current AmuletRules payload — the authoritative CC fee schedule and traffic limits.

GET/api/netstat

The compact economics snapshot behind the landing page: on-chain oracle CC price, the current open mining round with its open/close timing, issuance per year, the app/validator reward split, synchronizer traffic price, holding-fee rate, SV and featured-app counts, and protocol version — one cheap call instead of four.

GET/api/validators

The validator directory: every party that collected validator rewards in the trailing 7 days, ranked, with is_sv flags and a per-day reward series. Background-computed; pending: true until the first rollup lands.

Governance

The DSO governs Canton by on-chain vote requests. ccscan decodes them into readable proposals — action, category, requester, per-SV votes — and archives every decided proposal permanently, past the upstream scan's ~100-item window.

GET/api/governance?limit=

Open and recently-closed proposals with per-proposal tallies, category counts, and an all-time status tally. limit caps closed history (5–200, default 40).

GET/api/governance/{cid}

One proposal by tracking contract id: everything in the list row plus all_votes (every SV's accept/reject with reasons), the raw action payload, and sv_count — the current electorate size for the tally denominator.

GET/api/governance/participation

Per-SV voting participation across all archived decided proposals: votes cast, accept/reject split, and participation rate per super validator.

Stats & Market

GET/api/stats/daily

Per-day series from genesis: transaction counts by type and CC volume (transferred/minted/tapped), aggregated from the full index. While the one-time backfill is completing, complete: false and days appear oldest-first; progress = aggregated_to_seq / head_seq.

GET/api/stats/recent?days=14

Always-current per-day counts for the trailing 1–30 days, computed live against the index (10-minute cache). The final entry is the current partial day (partial: true).

GET/api/price

Canton Coin market data: USD and BTC price, market cap, 24h change (CoinGecko, 120s cache). Degrades to available: false rather than failing.

Live & Streaming

The same real-time layer that drives the explorer's pulse chart is part of the API. Both endpoints are served entirely from memory and are metering-exempt — they never consume your rate or quota budget. GET /api/status is metering-exempt too.

GET/api/live

Snapshot of the trailing ~3 minutes: ~2s head-seq samples (t0 + ts[] offsets, seqs[], rounds[]) plus instant / 1m / 5m throughput (tps_10s, tps_60s, tps_5m). A 2s poll is always safe.

GET/api/live/stream

Server-Sent Events: the live payload — plus each newly indexed transaction in txs[] — pushed the moment the chain head moves, sub-second after ingest. The first event arrives immediately with a ~30-transaction backfill. Streams recycle after ~120s and EventSource reconnects transparently; at connection capacity the endpoint returns 503 — fall back to polling /api/live.

# every new Canton transaction, as it lands curl -sN https://ccscan.xyz/api/live/stream

Want push without holding a connection? Webhooks deliver per-party transaction events to your endpoint, signed, on Free and up.

Data Model

Transaction row

{ "seq": 320000000, // monotonic cursor, assigned at ingest "event_id": "#1220ce…:0", // Canton event id, globally unique "round": 103286, // mining round (0/null on a few records) "tx_type": "transfer", // transfer | mint | tap | abort_transfer_instruction "tx_date": "2026-07-06 03:16:12.337540+00:00", "amount": 1.0, // headline CC per `nature`; null only for aborts "nature": "send", // send | reward | self | mint | tap | abort | other "rewards": null, // validator+SV+app rewards claimed, when nature=reward "parties": { "<party>": ["sender"], "<party>": ["receiver"] }, "kind": "preapproval_send" // transfer_kind, when the type is transfer }

Transaction types

TypeMeaning
transferCC moved on-ledger. The nature field refines it: send (to a distinct receiver), reward (a validator / super-validator / app-provider collecting rewards into its own balance — no separate recipient), or self (a self-transfer / coin merge). Every transfer moves value — amount is the headline for that nature. kind further distinguishes direct transfers, pre-approved sends, and transfer-instruction flows.
mintNew CC issued to a party — defined in the protocol; not observed on Canton MainNet to date.
tapFaucet-style issuance — defined for DevNet-originated economics; not observed on Canton MainNet (0 to date).
abort_transfer_instructionA pending transfer instruction was aborted.

Roles

A party appears in a transaction as sender, receiver, and/or balance_change (its holdings were touched — e.g. fees or change). Roles come from the indexed per-party join, so history queries are exact, not heuristic.

Amounts

The chain records amounts as 10-dp decimal strings; the API's amount headline field is a JSON number for convenience, while detail and balance endpoints preserve the original decimal strings for accounting-grade use.

Methodology

How the numbers on this site are derived — published so every figure is auditable.

  • Headline amounts are derived, never stored. For a send the amount is the sum of receiver amounts; for a reward collection it is the gross rewards claimed; for a self transfer it is the sender change; aborts have no amount. The full raw detail is always returned, so you can re-derive or re-define any headline.
  • The validator coupon is de-duplicated. Across protocol eras the same validator reward is reported in input_validator_reward_amount, input_validator_faucet_amount, or both. Every reward total on this site takes max(reward, faucet) — summing them double-counts.
  • Economics follow Canton's burn-mint model. Reward collections mint new CC (split into app / validator / super-validator components); every fee — sender, receiver, and holding fees — burns. Net issuance is minted minus burned, accumulated from genesis by the background aggregator.
  • Accounting-grade values are decimal strings. Balance and detail amounts are 10-decimal-place strings; the headline amount is a JSON number for convenience. Use the strings when exactness matters.
  • The liveness field is index freshness, not per-party activity. rounds_behind compares ccscan’s index head to the network head, so it is the same for every party queried; it is reported only for parties that actually collect validator or super-validator rewards, and unknown otherwise. Canton issues no validator liveness rewards, and a synced validator only collects every ~40–50 rounds, so neither reward recency nor collection round is a sound per-validator liveness signal. Treat this field as “is ccscan current?”, not “is this validator up?”.

Freshness & Sources

DataSourceFreshness
Transactions, parties, rounds, searchBlueprint's chain index (validator infrastructure)Continuously ingesting; typically seconds behind head — verify via ingest_cursor_at in /api/overview
Balances, holdings, ANS, networkSV Scan API pass-throughLive, short server-side cache (30s–1h by endpoint)
Daily aggregatesIndex post-processing/api/stats/recent always current; /api/stats/daily backfilling from genesis
Market dataCoinGecko120s cache

Errors

Errors are JSON with an error message and a conventional status:

StatusMeaning
400Invalid parameter (unknown type, both cursors at once)
401API key supplied but unknown, inactive, or revoked
404Transaction, party, round, or page not found
429Rate limit or daily/monthly quota exceeded — see the RateLimit-* and X-Quota-* response headers
502The Scan API upstream did not respond — retry shortly
503 + building: trueA supporting index is still building — retry in minutes

Unknown parties in search-style endpoints are not errors: they return count: 0.

Webhooks

Signed party-activity events, pushed the moment a party's transaction indexes — no polling. Create webhooks from your dashboard (plan limits: Free 1 · Pro 10 · Enterprise 50). Endpoints must be public HTTPS.

{ "event": "party.activity", "party": "party-name::1220…", "tx": { "seq": 322500123, "tx_type": "transfer", "amount": "12.5", "parties": { "…": ["sender"] } }, "sent_at": 1783900000.123 }

Every delivery carries X-CCScan-Signature: sha256=HMAC_SHA256(secret, raw_body) — verify it before trusting the payload. Ten consecutive failed deliveries disable a webhook (re-enable from the dashboard). Delivery is at-most-once: reconcile against /api/party/<id>/txs for completeness.

Stability & Versioning

The endpoints in openapi.json are the stable v1 contract: fields are additive-only, and any breaking change ships under a new path with at least 12 months of notice here and in the spec. Undocumented /api/* routes (they power the explorer UI) may change without notice — build against the spec, not the network tab. Live service health is published at /status.

Agents & Discovery

  • /openapi.json — OpenAPI 3.1, the authoritative machine-readable contract.
  • /api-docs/ — interactive explorer with runnable requests.
  • /llms.txt — compact orientation for LLM agents (llmstxt.org format).
  • /llms-full.txt — the complete inline agent reference: auth, pagination, every endpoint's shape, worked examples.
  • GET /api — a machine index of these discovery URLs.

Responses are flat, stable JSON with integer cursors — designed to be trivially consumed by agent frameworks and reconciliation pipelines alike.

FAQ

What is the ccscan Canton chain API?

A read-only REST API serving full-history Canton Network chain data — every Canton Coin transaction since genesis (June 2024), per-party history and balances, mining rounds, ANS names, governance, and network configuration.

Do I need an API key?

No. Browsing is anonymous at 300 requests/min per IP. A Free key matches that 300/min and adds per-key quotas (10,000/day, 150,000/month) plus usage analytics; Pro raises throughput to 3,000 requests/min and Enterprise to 30,000 — get one at /pricing.

How do I authenticate?

Send your key as Authorization: Bearer <key> or the X-API-Key header. Your remaining budget is returned in RateLimit-* response headers on every call.

How fresh is the data?

The index typically trails the chain head by seconds (ingest_cursor_at in /api/overview is the live signal); balances, holdings, names, and network state are relayed live from the SV Scan API. Current lag is published at /status.

Can AI agents use the API?

Yes — automated access within your rate limits is welcome. Start at /llms.txt or the machine index at GET /api.

Access & Commercial

The API is open for evaluation. For production workloads — commercial terms, rate guarantees, SLAs, dedicated read capacity, or custom endpoints (webhooks, bulk export, bespoke aggregates) — talk to Blueprint:

  • theblueprint.xyz — company, platform, and contact.
  • The same infrastructure powers Blueprint's institutional reconciliation pipelines — the endpoints documented here are the ones we run in production ourselves.
Blueprint