Proof of Reserves

Get a signed root commitment

Changed on

Return the signed Merkle Sum Tree root commitment for one asset in your platform's tree.

The tree is always your own: the platform is taken from your authenticated identity and cannot be supplied in the request, so another platform's roots are not addressable through this endpoint.

Verify the response by checking signature over the raw bytes of commitment_cbor using the key whose key_id matches signing_key_id in GET /por/keys, then decoding commitment_cbor and reading the committed values from it. The sibling JSON fields are an unsigned convenience view, and they are not a complete rendering of the signed payload.

This API does not cache these responses and sets no Cache-Control, but responses do carry a weak ETag, so a request sending If-None-Match can receive 304 Not Modified with no body. Nothing here suppresses caching by an intermediary, so treat latest as a moving target.

No rate limit is applied on these routes by this API. Edge limits may still apply, so handle 429 and honour Retry-After rather than assuming an unlimited budget.

get/por/roots/{asset}/{snapshot}

Request

  • Base URL
    https://api.cert.zerohash.com
  • URL
    https://api.cert.zerohash.com/por/roots/{asset}/{snapshot}
  • Auth
    API key in header X-SCX-API-KEY and API key in header X-SCX-PASSPHRASE

Path parameters

assetstring required
Example:ETH

Chain-qualified asset identifier. A bare symbol denotes the asset on its home chain; a dotted form denotes the bridged asset on that chain.

snapshotstring required
Example:latest

Which root to return. Either the literal latest or a db_snapshot_id hex string to pin a specific historical snapshot.

latest resolves to the commitment with the highest publication_seq for this tree. To pin: take db_snapshot_id from a prior response and pass it here — the service looks up that exact snapshot.

Headers

X-SCX-SIGNEDstring required

HMAC-SHA256 signature of the request, base64-encoded. See the Authentication guide for the exact signing formula.

X-SCX-TIMESTAMPstring required
Example:1678901234

Current Unix timestamp in seconds. Must be within 60 seconds of server time or the request is rejected.

X-Request-Idstring uuid

Optional client-supplied request ID used for tracing and idempotency. Must be a UUID v4. When omitted, zerohash generates one and returns it in the response X-Request-Id header.

Response

Signed root commitment

platform_codestring required

Platform the tree belongs to. Always your own platform — it is taken from your authenticated identity, never from the request.

assetstring required

Chain-qualified asset identifier, used in every leaf exactly as returned here — apply no normalization of your own.

spec_versionstring required

Version of the Proof of Reserves commitment schema. A change here can change the leaf preimage or the signed payload layout.

publication_seqstring required

Publication counter for this (platform, asset) series, rendered as a decimal string (not a JSON number) because it is a 64-bit integer. Monotonically increasing — a higher value supersedes a lower one for the same tree. Use it to detect a replayed or withheld root.

db_snapshot_idstring required

Content identifier of the whole normalized balance snapshot this root was built from, as lowercase hex. It is computed across every platform and asset in that snapshot, of which this tree is one subset — so trees built in the same run share one value, and it does not by itself identify this tree. See the snapshot path parameter for how to address a specific root.

snapshot_tsstring date-time required

Time the balance snapshot was taken, RFC 3339 UTC. Currently emitted as the Unix epoch (1970-01-01T00:00:00Z) — treat it as unset and do not use it for freshness checks until it carries a real value.

root_hashstring required

Merkle root, 32 bytes as lowercase hex.

root_sumstring required

Sum of every leaf balance in the tree, as a 16-byte big-endian u128 in lowercase hex — the same bytes that are hashed into the tree. Note this differs from balance and sibling_sum, which are decimal. Phase 1 sums available balances only.

commitment_cborstring byte required

The exact bytes that were signed, canonical CBOR (RFC 8949 §4.2.1), base64-encoded for transport. Verify signature over the decoded bytes — never over a re-encoding of the JSON fields above.

Decode it as a whole map rather than reading fixed offsets: it commits to more entries than are mirrored in this response, and the entry set is tied to spec_version. The authoritative field list for a given spec_version is in the Proof of Reserves verification spec issued with the reference verifier at onboarding.

In the example below three signed entries are still placeholders and must not be relied on: asset_precision is 0, evidence_pkg_sha256 is 32 zero bytes, and asset_config_version is the empty string.

Note: the example value below must be regenerated after the BG-5368 proto rename (platform_id → platform_code in the signed CBOR) is deployed. The current bytes encode the old key name and will not match the live service once that spec bump lands.

signaturestring byte required

Detached Ed25519 signature over the decoded commitment_cbor bytes, base64-encoded.

signing_key_idstring required

The key that produced signature. Look it up by key_id in GET /por/keys and verify against that entry's public_key. Do not gate on the key validity window in this release — see GET /por/keys for why it is not yet checkable.

Example response

{
  "platform_code": "FP2F20",
  "asset": "ETH",
  "spec_version": "1.0.0",
  "publication_seq": "1",
  "db_snapshot_id": "10edfd6c58bcae73b5c6bf9f9e88b69cb47173271cb5fc1362121b1544d04f3c",
  "snapshot_ts": "1970-01-01T00:00:00Z",
  "root_hash": "b72605925891e8d8f9c1a9b28f662f34b66f7f9ee9ece8c187cc206c06ac49c4",
  "root_sum": "000000000005a9d6eb0ecc04a85ed3a0",
  "commitment_cbor": "rGhhc3NldF9pZGNFVEhocm9vdF9zdW1QAAAAAAAFqdbrDswEqF7ToGlyb290X2hhc2hYILcmBZJYkejY+cGpso9mLzS2b3+e6ezowYfMIGwGrEnEa3BsYXRmb3JtX2lkZkZQMkYyMGtzbmFwc2hvdF90cwBsYWNjb3VudF90eXBlaWF2YWlsYWJsZWxzcGVjX3ZlcnNpb25lMS4wLjBuZGJfc25hcHNob3RfaWRYQDEwZWRmZDZjNThiY2FlNzNiNWM2YmY5ZjllODhiNjljYjQ3MTczMjcxY2I1ZmMxMzYyMTIxYjE1NDRkMDRmM2NvYXNzZXRfcHJlY2lzaW9uAG9wdWJsaWNhdGlvbl9zZXEAc2V2aWRlbmNlX3BrZ19zaGEyNTZYIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdGFzc2V0X2NvbmZpZ192ZXJzaW9uYA==",
  "signature": "vcJ7xd0OSR75rkBKW/yc5pO0n3FYdjjExFz+8CqgHvIPtZlQ9vf37wkntHgVCTDFNBttRJCfnNct9sI7W4DxDQ==",
  "signing_key_id": "Wallet:3b779fac-a9c2-4bef-a7b2-05ee8807af96"
}

Changes