---
updatedAt: 2026-08-12T17:35:34.000Z
agentTools:
  projectIndex: https://docs.zerohash.com/llms.txt
---

# Get Proof of Reserves signing keys

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.

# OpenAPI definition

```json
{
  "openapi": "3.1.0",
  "info": {
    "title": "zerohash API",
    "description": "\n### Authentication\n\nzerohash Uses HMAC SHA-256 verification to ensure the authenticity of API requests, follow instructions by link [https://docs.zerohash.com/reference/api-authentication](https://docs.zerohash.com/reference/api-authentication)\n\n<a href=\"/zh-swagger.json\">Download zerohash OpenAPI Schema as JSON</a>\n",
    "version": "1.7.0"
  },
  "servers": [
    {
      "url": "https://api.cert.zerohash.com",
      "description": "Certification API server"
    }
  ],
  "x-readme": {
    "proxy-enabled": false
  },
  "tags": [
    {
      "name": "Proof of Reserves",
      "description": "Signed Merkle Sum Tree root commitments and participant inclusion proofs. Each root commits to per-participant balances as recorded in the zerohash liability ledger, so a verified proof shows that a balance was included in the published total — it is not by itself evidence of the assets held against those liabilities."
    }
  ],
  "paths": {
    "/por/keys": {
      "get": {
        "tags": [
          "Proof of Reserves"
        ],
        "summary": "Get Proof of Reserves signing keys",
        "description": "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.\n\nThe 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.\n\nKeys 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.\n\nTo verify a commitment, select the entry whose `keyId` equals the commitment's `signingKeyId` and check `signature` against that entry's `publicKey`.\n\nThe 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.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Signature"
          },
          {
            "$ref": "#/components/parameters/Timestamp"
          },
          {
            "$ref": "#/components/parameters/RequestId"
          }
        ],
        "responses": {
          "200": {
            "description": "Current and previously rotated signing keys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetPorKeysResponse"
                }
              }
            }
          },
          "304": {
            "description": "Your `If-None-Match` matched the current weak `ETag`. No body is returned."
          },
          "403": {
            "description": "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.",
            "content": {
              "text/html": {
                "schema": {
                  "type": "string",
                  "example": "Missing API Key header"
                }
              },
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PorAuthError"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Code500"
                }
              }
            }
          },
          "503": {
            "description": "Service Unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Code503"
                }
              }
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKey": [],
      "apiPassphrase": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "description": "Your API public key. See the [Authentication guide](https://docs.zerohash.com/reference/api-authentication) for how to obtain keys.",
        "in": "header",
        "name": "X-SCX-API-KEY"
      },
      "apiPassphrase": {
        "type": "apiKey",
        "description": "The passphrase associated with your API key, set when the key was created.",
        "in": "header",
        "name": "X-SCX-PASSPHRASE"
      }
    },
    "parameters": {
      "Signature": {
        "name": "X-SCX-SIGNED",
        "in": "header",
        "description": "HMAC-SHA256 signature of the request, base64-encoded. See the [Authentication guide](https://docs.zerohash.com/reference/api-authentication) for the exact signing formula.",
        "required": true,
        "schema": {
          "type": "string"
        }
      },
      "Timestamp": {
        "name": "X-SCX-TIMESTAMP",
        "in": "header",
        "description": "Current Unix timestamp in seconds. Must be within 60 seconds of server time or the request is rejected.",
        "required": true,
        "schema": {
          "type": "string",
          "example": "1678901234"
        }
      },
      "RequestId": {
        "name": "X-Request-Id",
        "in": "header",
        "description": "Optional client-supplied request ID used for tracing and idempotency. Must be a [UUID v4](https://www.uuidtools.com/uuid-versions-explained#version-4). When omitted, zerohash generates one and returns it in the response `X-Request-Id` header.",
        "required": false,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "schemas": {
      "Code500": {
        "type": "object",
        "description": "An unexpected error occurred on the server. The request can be retried after a short delay, but the same inputs may reproduce the error.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "example": "Internal Server Error"
          }
        }
      },
      "Code503": {
        "type": "object",
        "description": "A downstream dependency was unavailable, timed out, or returned a retryable error. Safe to retry; the response carries a `zh-allow-retry: true` header.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "example": "Service Unavailable"
          }
        }
      },
      "PorKeyEntry": {
        "type": "object",
        "description": "One `zh_por_pub` public key and the range of snapshot dates it signs.",
        "required": [
          "key_id",
          "public_key",
          "valid_from_snapshot_date",
          "valid_to_snapshot_date"
        ],
        "properties": {
          "key_id": {
            "type": "string",
            "description": "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.",
            "example": "Wallet:3b779fac-a9c2-4bef-a7b2-05ee8807af96"
          },
          "public_key": {
            "type": "string",
            "format": "byte",
            "description": "Ed25519 public key, DER/SPKI-encoded then base64 (standard alphabet). This is not a raw 32-byte key — parse it as SubjectPublicKeyInfo.",
            "example": "MCowBQYDK2VwAyEAsjfXVOjTHH+pv3CTmavkvpfnHrRcGz13s6JDtvNLyRo="
          },
          "valid_from_snapshot_date": {
            "type": "string",
            "description": "First snapshot date this key signs, inclusive, as `YYYY-MM-DD` (a calendar date, not a timestamp).",
            "example": "2026-07-20"
          },
          "valid_to_snapshot_date": {
            "type": "string",
            "description": "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.",
            "example": ""
          }
        }
      },
      "GetPorKeysResponse": {
        "type": "object",
        "required": [
          "keys"
        ],
        "properties": {
          "keys": {
            "type": "array",
            "description": "Current and previously rotated keys. May be empty in an environment where no key has been provisioned yet.",
            "items": {
              "$ref": "#/components/schemas/PorKeyEntry"
            }
          }
        }
      },
      "PorAuthError": {
        "type": "object",
        "description": "Authorization failure raised by the Proof of Reserves routes themselves.",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "example": "You are not allowed to access proof-of-reserves data for that platform."
          }
        }
      }
    }
  }
}
```