---
title: "Get Proof of Reserves signing keys"
method: GET
path: "/por/keys"
tags: ["Proof of Reserves"]
---

# Get Proof of Reserves signing keys

`GET /por/keys`

## Request

- Base URL: `https://api.cert.zerohash.com`
- URL: `https://api.cert.zerohash.com/por/keys`
- Auth: API key in header `X-SCX-API-KEY` and API key in header `X-SCX-PASSPHRASE`

List the `zh_por_pub` Ed25519 public keys used to sign Merkle Sum Tree root commitments, with the range of snapshot dates each one covers.

The list is a discovery convenience, not a trust anchor: it is served over your authenticated partner session but is **not itself signed**. Pin the key fingerprint you are given out-of-band at onboarding and compare against it.

Keys are region-global rather than platform-scoped, so this endpoint returns the same list for every partner in a region. Unlike the root and proof endpoints it is not gated on Proof of Reserves being enabled for your platform, though the same authentication and device checks still apply.

To verify a commitment, select the entry whose `keyId` equals the commitment's `signingKeyId` and check `signature` against that entry's `publicKey`.

The validity window is not checkable yet. The only date a root commitment carries is `snapshotTs`, which is currently emitted as the Unix epoch, so there is nothing meaningful to compare against `validFromSnapshotDate`..`validToSnapshotDate`. Do not gate verification on that comparison in this release, and do not substitute your own clock for the missing value.

## Headers

- `X-SCX-SIGNED` string, required
- `X-SCX-TIMESTAMP` string, required
- `X-Request-Id` string, uuid

## Response `200`

Current and previously rotated signing keys

- GetPorKeysResponse
  - `keys` PorKeyEntry[], required: Current and previously rotated keys. May be empty in an environment where no key has been provisioned yet.
    - `key_id` string, required: Identifier of the signing key. Matches `signing_key_id` on a root commitment, which is how a verifier selects the key to check a signature against.
    - `public_key` string, byte, required: Ed25519 public key, DER/SPKI-encoded then base64 (standard alphabet). This is not a raw 32-byte key — parse it as SubjectPublicKeyInfo.
    - `valid_from_snapshot_date` string, required: First snapshot date this key signs, inclusive, as `YYYY-MM-DD` (a calendar date, not a timestamp).
    - `valid_to_snapshot_date` string, required: Last snapshot date this key signs, inclusive, as `YYYY-MM-DD`. Empty string means the key is current and open-ended. During a rotation overlap both the outgoing and incoming keys are listed.

## Other responses

- `304`: Your `If-None-Match` matched the current weak `ETag`. No body is returned.
- `403`: Authorization failed — rejected API-key headers or signature (a plain string served as `text/html`, not JSON), or device verification could not resolve your platform.
- `500`: Internal Server Error
- `503`: Service Unavailable

## Changes

- **2026-11-03** `47cf70ae701c`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/zerohash/apis/zerohash-api/changes/por/keys/get.md)

---

[API](https://skmtc.dev/zerohash/apis/zerohash-api.md) - [All operations](https://skmtc.dev/zerohash/apis/zerohash-api/llms.txt) - [OpenAPI document](https://skmtc.dev/zerohash/apis/zerohash-api/revisions/47cf70ae701c?raw)
