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

# Get an indirect participant's JWK Set

> Returns the JWK Set JDPI signs THIS indirect's dynamic-QR JWS with, as an application/jwk-set+json document, so the indirect can publish it on its own host for payer PSPs to validate signatures against. The indirect cannot produce this itself — JDPI holds the certificate and does the signing — which is why the convenience lives on the direct participant's API.

Call it once when onboarding an indirect onto its own QR certificate (after qrCertificate.ownCertificate is set), and again whenever that certificate is rotated; then serve the bytes verbatim at the JWKS location under the indirect's own base URL. It is read-only and changes nothing here. It is ONLY for an indirect that hosts its own certificate: one that falls back to the direct participant has no key set of its own and is refused 422 PIX-0114, which names the direct participant's own JWKS route to publish instead. Lifecycle status is deliberately NOT a condition — a SUSPENDED or CLOSED indirect still has live QR codes in the wild, and withholding the key would break their validation.

Every answer carries X-JWK-Set-Freshness: 'fresh' when the key set came from inside the cache TTL, or 'stale' when the TTL had expired, JDPI could not be reached, and a cached key set was served instead — a 200 alone does not assert freshness, since a cached document and a fresh one are the same bytes. Refusals: 422 PIX-0111 when this tenant's indirect-participants feature is not enabled (no QR is signed with any indirect certificate while it is off, so the key set would validate nothing); 404 PIX-0095 for an unknown id; 422 PIX-0114 for the fallback case above; 422 PIX-0098 when the indirect carries no ispb, which is the key §8.3.11 is looked up by; 503 PIX-1050 when JDPI is unreachable and nothing is cached — attributed to JDPI, never presented as a configuration error.



## OpenAPI

````yaml /en/openapi/v3-current/pix.yaml get /v1/indirects/{indirectId}/jwks
openapi: 3.1.0
info:
  description: Brazilian PIX Direct (DICT + SPI) plugin API.
  title: plugin-br-pix-jd
  version: 1.0.0
servers: []
security:
  - BearerAuth: []
paths:
  /v1/indirects/{indirectId}/jwks:
    get:
      tags:
        - Indirects
      summary: Get an indirect participant's JWK Set
      description: >-
        Returns the JWK Set JDPI signs THIS indirect's dynamic-QR JWS with, as
        an application/jwk-set+json document, so the indirect can publish it on
        its own host for payer PSPs to validate signatures against. The indirect
        cannot produce this itself — JDPI holds the certificate and does the
        signing — which is why the convenience lives on the direct participant's
        API.


        Call it once when onboarding an indirect onto its own QR certificate
        (after qrCertificate.ownCertificate is set), and again whenever that
        certificate is rotated; then serve the bytes verbatim at the JWKS
        location under the indirect's own base URL. It is read-only and changes
        nothing here. It is ONLY for an indirect that hosts its own certificate:
        one that falls back to the direct participant has no key set of its own
        and is refused 422 PIX-0114, which names the direct participant's own
        JWKS route to publish instead. Lifecycle status is deliberately NOT a
        condition — a SUSPENDED or CLOSED indirect still has live QR codes in
        the wild, and withholding the key would break their validation.


        Every answer carries X-JWK-Set-Freshness: 'fresh' when the key set came
        from inside the cache TTL, or 'stale' when the TTL had expired, JDPI
        could not be reached, and a cached key set was served instead — a 200
        alone does not assert freshness, since a cached document and a fresh one
        are the same bytes. Refusals: 422 PIX-0111 when this tenant's
        indirect-participants feature is not enabled (no QR is signed with any
        indirect certificate while it is off, so the key set would validate
        nothing); 404 PIX-0095 for an unknown id; 422 PIX-0114 for the fallback
        case above; 422 PIX-0098 when the indirect carries no ispb, which is the
        key §8.3.11 is looked up by; 503 PIX-1050 when JDPI is unreachable and
        nothing is cached — attributed to JDPI, never presented as a
        configuration error.
      operationId: getIndirectJWKS
      parameters:
        - description: The indirect participant id.
          in: path
          name: indirectId
          required: true
          schema:
            description: The indirect participant id.
            examples:
              - 018f2b7c-0000-7000-8000-000000000000
            type: string
      responses:
        '200':
          content:
            application/jwk-set+json:
              schema:
                $ref: '#/components/schemas/JWKSet'
          description: OK
          headers:
            X-JWK-Set-Freshness:
              schema:
                description: >-
                  'fresh' when the key set is within its cache freshness window
                  — fetched from JDPI for this request, or cached less than the
                  TTL ago; 'stale' when that window had expired AND JDPI could
                  not be reached, so a cached key set was served instead.
                examples:
                  - fresh
                type: string
        default:
          content:
            application/problem+json:
              schema:
                $ref: '#/components/schemas/Detail'
          description: Error
components:
  schemas:
    JWKSet:
      additionalProperties: false
      properties:
        keys:
          description: >-
            The JSON Web Keys, exactly as JDPI extracted them from the
            indirect's CERTQRC certificate.
          items:
            additionalProperties: {}
            type: object
          type:
            - array
            - 'null'
      required:
        - keys
      type: object
    Detail:
      additionalProperties: false
      properties:
        code:
          description: >-
            Stable, machine-readable domain error code scoped to the emitting
            service (format: <SERVICE>-NNNN).
          examples:
            - ERR-0001
          type: string
        detail:
          description: >-
            A human-readable explanation specific to this occurrence of the
            problem.
          examples:
            - Property foo is required but is missing.
          type: string
        errors:
          description: Optional list of individual error details
          items:
            $ref: '#/components/schemas/ErrorDetail'
          type:
            - array
            - 'null'
        instance:
          description: >-
            A URI reference that identifies the specific occurrence of the
            problem.
          examples:
            - https://example.com/error-log/abc123
          format: uri
          type: string
        status:
          description: HTTP status code
          examples:
            - 400
          format: int64
          type: integer
        title:
          description: >-
            A short, human-readable summary of the problem type. This value
            should not change between occurrences of the error.
          examples:
            - Bad Request
          type: string
        type:
          default: about:blank
          description: A URI reference to human-readable documentation for the error.
          examples:
            - https://example.com/errors/example
          format: uri
          type: string
        upstream:
          $ref: '#/components/schemas/Upstream'
          description: >-
            RFC 9457 extension member: the error a proxied third-party provider
            reported. Absent unless the emitting service explicitly surfaced
            one.
      type: object
    ErrorDetail:
      additionalProperties: false
      properties:
        location:
          description: >-
            Where the error occurred, e.g. 'body.items[3].tags' or
            'path.thing-id'
          type: string
        message:
          description: Error message text
          type: string
        value:
          description: The value at the given location
      type: object
    Upstream:
      additionalProperties: false
      properties:
        code:
          description: The upstream provider's own error code, verbatim.
          examples:
            - E4001
          type: string
        message:
          description: >-
            The upstream provider's own error message, verbatim (bounded, never
            its raw response body).
          examples:
            - account not found at provider
          type: string
      type: object
  securitySchemes:
    BearerAuth:
      bearerFormat: JWT
      description: JWT bearer token issued by the identity provider.
      scheme: bearer
      type: http

````