> ## Documentation Index
> Fetch the complete documentation index at: https://docs-pos.solya.app/llms.txt
> Use this file to discover all available pages before exploring further.

# List the published fiscal verification keys

> Returns the Ed25519 PUBLIC keys the NF525 fiscal signature chain is sealed with, so an auditor can verify that chain OFFLINE with no secret: take a record's key id, fetch the matching `publicKeyPem` here, recompute the link's canonical body and check the signature. Unauthenticated on purpose — a public key is not a secret, and publishing it is what makes the signature meaningful.

This is a NARROW, auditor-facing read, not a fiscal reporting endpoint: it carries no sales, totals or journal entries. For the Z/X reports, the fiscal journal and the server-side chain verification, use the `pos.finance.view`-gated `/v1/fiscal/*` operations instead. Reach for this only when you are verifying signatures yourself and need the key material.

An EMPTY `keys` array is a normal, successful answer, not a fault: it means the deployment is signing with symmetric HMAC keys, which have no public half to publish. In that case offline verification is simply not available and there is nothing to retry. `keyId` is the join key — it matches the `#<keyId>` suffix stamped on every record the key sealed, and a rotated deployment lists several keys at once so an old record still resolves to the key that signed it. The response never contains private material.



## OpenAPI

````yaml /openapi.json get /v1/fiscal-keys
openapi: 3.0.3
info:
  title: Solya POS API
  version: 1.0.0
  description: >-
    The Solya POS backend HTTP surface. Every documented operation is
    agent-ready: it carries an `operationId`, an agent-facing `description`, the
    `pos.*` scopes it enforces (`x-required-permissions`) and an `x-agent-tier`.
    Success responses return the payload as raw JSON; failures return the
    `ErrorResponse` envelope (`{ error: { code, message, statusCode } }`).
servers:
  - url: /
    description: The backend, relative to its deployed origin.
security: []
paths:
  /v1/fiscal-keys:
    get:
      tags:
        - Fiscal
      summary: List the published fiscal verification keys
      description: >-
        Returns the Ed25519 PUBLIC keys the NF525 fiscal signature chain is
        sealed with, so an auditor can verify that chain OFFLINE with no secret:
        take a record's key id, fetch the matching `publicKeyPem` here,
        recompute the link's canonical body and check the signature.
        Unauthenticated on purpose — a public key is not a secret, and
        publishing it is what makes the signature meaningful.


        This is a NARROW, auditor-facing read, not a fiscal reporting endpoint:
        it carries no sales, totals or journal entries. For the Z/X reports, the
        fiscal journal and the server-side chain verification, use the
        `pos.finance.view`-gated `/v1/fiscal/*` operations instead. Reach for
        this only when you are verifying signatures yourself and need the key
        material.


        An EMPTY `keys` array is a normal, successful answer, not a fault: it
        means the deployment is signing with symmetric HMAC keys, which have no
        public half to publish. In that case offline verification is simply not
        available and there is nothing to retry. `keyId` is the join key — it
        matches the `#<keyId>` suffix stamped on every record the key sealed,
        and a rotated deployment lists several keys at once so an old record
        still resolves to the key that signed it. The response never contains
        private material.
      operationId: listFiscalPublicKeys
      responses:
        '200':
          description: >-
            The published verification keys; empty when only HMAC keys are
            configured.
          content:
            application/json:
              schema:
                type: object
                properties:
                  keys:
                    type: array
                    items:
                      type: object
                      properties:
                        keyId:
                          type: string
                          description: >-
                            Matches the `#<keyId>` suffix in the records this
                            key sealed.
                        algorithm:
                          type: string
                          description: The signature scheme label, e.g. `ed25519-v3`.
                        publicKeyPem:
                          type: string
                          description: The SPKI public-key PEM used to verify a signature.
                      required:
                        - keyId
                        - algorithm
                        - publicKeyPem
                      additionalProperties: false
                required:
                  - keys
                additionalProperties: false
                description: >-
                  The published verification keys; empty when only HMAC keys are
                  configured.
                example:
                  keys:
                    - keyId: ed-1
                      algorithm: ed25519-v3
                      publicKeyPem: |
                        -----BEGIN PUBLIC KEY-----
                        MCowBQYDK2VwAyEA…
                        -----END PUBLIC KEY-----
        '400':
          description: >-
            The request failed schema validation; `error.fieldErrors` lists the
            fields.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationErrorResponse'
        '500':
          description: An unexpected server error — safe to retry idempotent requests.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    ValidationErrorResponse:
      type: object
      required:
        - error
      additionalProperties: false
      description: >-
        A `VALIDATION_FAILED` envelope carrying the offending fields in
        `fieldErrors`.
      properties:
        error:
          type: object
          required:
            - code
            - message
            - statusCode
          additionalProperties: false
          properties:
            code:
              type: string
              enum:
                - VALIDATION_FAILED
            message:
              type: string
            statusCode:
              type: integer
            fieldErrors:
              type: array
              description: >-
                One entry per rejected field: the field path and why it was
                rejected.
              items:
                type: object
                required:
                  - field
                  - message
                additionalProperties: false
                properties:
                  field:
                    type: string
                    description: Dot-path of the offending field.
                  message:
                    type: string
                    description: Why the field was rejected.
    ErrorResponse:
      type: object
      required:
        - error
      additionalProperties: false
      description: The uniform failure envelope every non-2xx response returns.
      properties:
        error:
          type: object
          required:
            - code
            - message
            - statusCode
          additionalProperties: false
          properties:
            code:
              type: string
              enum:
                - VALIDATION_FAILED
                - UNAUTHORIZED
                - FORBIDDEN
                - NOT_FOUND
                - CONFLICT
                - BUSINESS_RULE_VIOLATION
                - INTERNAL_ERROR
              description: >-
                Machine-readable kernel `ResultCode` — branch on this, not on
                `message`.
            message:
              type: string
              description: >-
                Human-readable explanation. Safe to surface; never leaks server
                internals.
            statusCode:
              type: integer
              description: >-
                The HTTP status, mirrored into the body so a client need not
                read headers.

````