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

# Listar Vouchers

> Vouchers do parceiro em ordem decrescente de `created_at`. Não desconta saldo. `after` e `before` são mutuamente exclusivos; combiná-los retorna `invalid_filter`.



## OpenAPI

````yaml GET /api/v1/partners/{partnerId}/vouchers
openapi: 3.1.0
info:
  title: Certificados ZapSign Partner API
  version: 4.2.0
  description: >-
    API REST para parceiros (revendedores) emitirem vouchers de certificado
    digital e-CPF e e-CNPJ. Cada criação desconta 1 certificado do saldo da
    carteira do parceiro. Autenticação por Bearer token com prefixo `czk_live_`
    gerado em
    [https://certificados.zapsign.com.br/reseller/api-keys](https://certificados.zapsign.com.br/reseller/api-keys).
  contact:
    name: Suporte Certificados ZapSign
    url: https://wa.me/5511952135263
servers:
  - url: https://certificados.zapsign.com.br
    description: Produção
security:
  - bearerAuth: []
tags:
  - name: Vouchers
    description: Criação e consulta de vouchers de certificado digital.
  - name: Carteira
    description: Saldo disponível do parceiro.
paths:
  /api/v1/partners/{partnerId}/vouchers:
    get:
      tags:
        - Vouchers
      summary: Lista vouchers do parceiro com paginação por cursor.
      description: >-
        Vouchers do parceiro em ordem decrescente de `created_at`. Não desconta
        saldo. `after` e `before` são mutuamente exclusivos; combiná-los retorna
        `invalid_filter`.
      operationId: listPartnerVouchers
      parameters:
        - $ref: '#/components/parameters/PartnerIdParam'
        - name: status
          in: query
          required: false
          description: Filtra por estado do voucher.
          schema:
            type: array
            items:
              $ref: '#/components/schemas/VoucherStatus'
          style: form
          explode: true
          example:
            - issued
        - name: created_after
          in: query
          required: false
          description: >-
            Limite inferior (inclusivo) de `created_at`. Formato ISO-8601 com
            timezone explícito (`Z` ou `±HH:MM`). Datas sem hora ou sem timezone
            são rejeitadas com `invalid_filter`.
          schema:
            type: string
            format: date-time
          example: '2026-05-01T00:00:00Z'
        - name: created_before
          in: query
          required: false
          description: >-
            Limite superior (inclusivo) de `created_at`. Mesma regra de formato
            de `created_after`.
          schema:
            type: string
            format: date-time
          example: '2026-05-31T23:59:59Z'
        - name: limit
          in: query
          required: false
          description: >-
            Quantos itens devolver por página. Mínimo 1, máximo 100. Quando
            omitido, o servidor usa 20.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 20
          example: 20
        - name: after
          in: query
          required: false
          description: >-
            Cursor exclusivo: `voucher_id` da última linha da página atual. A
            próxima página começa logo depois desse id (ele NÃO é repetido).
            Mutuamente exclusivo com `before`. Um id desconhecido devolve `data:
            []` sem erro.
          schema:
            type: string
            minLength: 1
          example: ZS_ECPF_A1_01HXYZABCDEFGHJKMNPQRSTV
        - name: before
          in: query
          required: false
          description: >-
            Cursor exclusivo no sentido inverso: `voucher_id` do primeiro item
            da página atual. A página anterior termina logo antes desse id (ele
            NÃO é repetido). Mutuamente exclusivo com `after`. Um id
            desconhecido devolve `data: []` sem erro.
          schema:
            type: string
            minLength: 1
          example: ZS_ECPF_A1_01HXYZABCDEFGHJKMNPQRST0
      responses:
        '200':
          $ref: '#/components/responses/VoucherListPage'
        '400':
          description: >-
            Query inválida: cobre 3 códigos `error` distintos. Veja o `error` no
            body para o motivo exato.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VoucherErrorEnvelope'
              examples:
                invalid_filter:
                  $ref: '#/components/examples/InvalidFilterExample'
                unknown_field:
                  $ref: '#/components/examples/UnknownFieldExample'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
      x-codeSamples:
        - lang: curl
          label: cURL
          source: >-
            # Página 1: sem cursor.

            curl -G
            'https://certificados.zapsign.com.br/api/v1/partners/PRT_ABC123/vouchers'
            \
              -H 'Authorization: Bearer czk_live_SUA_CHAVE' \
              --data-urlencode 'status=issued' \
              --data-urlencode 'created_after=2026-05-01T00:00:00Z' \
              --data-urlencode 'limit=20'

            # Página 2: usar o voucher_id do último item da página 1 em `after`.

            curl -G
            'https://certificados.zapsign.com.br/api/v1/partners/PRT_ABC123/vouchers'
            \
              -H 'Authorization: Bearer czk_live_SUA_CHAVE' \
              --data-urlencode 'status=issued' \
              --data-urlencode 'created_after=2026-05-01T00:00:00Z' \
              --data-urlencode 'limit=20' \
              --data-urlencode 'after=ZS_ECPF_A1_01HXYZABCDEFGHJKMNPQRSTV'
        - lang: javascript
          label: Node.js (fetch)
          source: |-
            async function listPage(after) {
              const params = new URLSearchParams();
              params.append('status', 'issued');
              params.append('created_after', '2026-05-01T00:00:00Z');
              params.append('limit', '20');
              if (after) params.append('after', after);

              const res = await fetch(
                `https://certificados.zapsign.com.br/api/v1/partners/PRT_ABC123/vouchers?${params}`,
                {
                  headers: { Authorization: 'Bearer czk_live_SUA_CHAVE' },
                },
              );
              return res.json();
            }

            // Iterar enquanto houver mais páginas.
            let cursor;
            do {
              const { object, has_more, data } = await listPage(cursor);
              // ... processar `data` aqui ...
              cursor = has_more ? data[data.length - 1].voucher_id : undefined;
            } while (cursor);
        - lang: python
          label: Python (requests)
          source: |-
            import requests

            def list_page(after=None):
                params = [
                    ('status', 'issued'),
                    ('created_after', '2026-05-01T00:00:00Z'),
                    ('limit', '20'),
                ]
                if after:
                    params.append(('after', after))
                res = requests.get(
                    'https://certificados.zapsign.com.br/api/v1/partners/PRT_ABC123/vouchers',
                    headers={'Authorization': 'Bearer czk_live_SUA_CHAVE'},
                    params=params,
                )
                return res.json()

            # Iterar enquanto houver mais páginas.
            cursor = None
            while True:
                body = list_page(cursor)
                # ... processar body['data'] aqui ...
                if not body['has_more']:
                    break
                cursor = body['data'][-1]['voucher_id']
components:
  parameters:
    PartnerIdParam:
      name: partnerId
      in: path
      required: true
      description: Identificador público do parceiro (Partner ID), exibido no portal.
      schema:
        type: string
        minLength: 1
        maxLength: 64
  schemas:
    VoucherStatus:
      type: string
      description: Estado atual do voucher no ciclo de vida.
      enum:
        - issued
        - redeemed
        - expired
        - declined
      x-enumDescriptions:
        issued: Voucher pronto pra ser usado pra emitir um certificado digital.
        redeemed: >-
          Titular já usou o voucher e recebeu o protocolo pra fazer a prova de
          vida e emitir o certificado.
        expired: Voucher venceu sem ser resgatado.
        declined: >-
          A emissão foi recusada, ou o próprio revendedor cancelou o voucher via
          `POST /vouchers/{voucher_id}/cancel`. Veja `decline_reason` pra o
          motivo (no self-cancel vale `reseller_self_cancel`).
    VoucherErrorEnvelope:
      type: object
      description: >-
        Envelope de erro dos endpoints de voucher: `error`, `message` e
        `details` (opcional).
      required:
        - error
        - message
      properties:
        error:
          type: string
          description: >-
            Código curto e estável do catálogo fechado. Use para fazer branching
            no seu cliente.
          example: validation_error
        message:
          type: string
          description: Mensagem em pt-BR, segura para mostrar a operadores internos.
        details:
          description: Estrutura adicional dependente do código. Veja a tabela de erros.
    VoucherListPage:
      type: object
      description: >-
        Página de vouchers do parceiro. Envelope `{ object: "list", has_more,
        data }`.
      required:
        - object
        - has_more
        - data
      properties:
        object:
          type: string
          const: list
          description: Discriminador do envelope. Sempre `"list"`.
          example: list
        has_more:
          type: boolean
          description: >-
            Indica se ainda existem páginas no sentido em que o cliente paginou.
            Quando `true`, use o `voucher_id` do último item de `data` em
            `?after=` para a próxima página.
          example: true
        data:
          type: array
          description: >-
            Vouchers da página atual, ordenados por `created_at` decrescente.
            Vazia quando não há resultados.
          items:
            $ref: '#/components/schemas/VoucherResponse'
    VoucherResponse:
      type: object
      description: >-
        Shape full retornado por `GET /vouchers/{voucher_id}` e por cada item de
        `GET /vouchers`.
      required:
        - voucher_id
        - certificate_type
        - status
        - issued_at
        - redeemed_at
        - decline_reason
        - reference_id
        - created_at
      properties:
        voucher_id:
          type: string
          description: Identificador único do voucher. Use no link de resgate e nas buscas.
          example: ZS_ECPF_A1_01HXYZABCDEFGHJKMNPQRSTV
        certificate_type:
          oneOf:
            - $ref: '#/components/schemas/CertificateType'
            - type: 'null'
          description: Tipo do certificado. `null` apenas em vouchers legados.
        status:
          $ref: '#/components/schemas/VoucherStatus'
        issued_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            Timestamp ISO 8601 de quando o status passou para `issued`. Costuma
            ser igual a `created_at`.
          example: '2026-05-07T14:32:11.000Z'
        redeemed_at:
          type:
            - string
            - 'null'
          format: date-time
          description: Timestamp ISO 8601 de quando o status passou para `redeemed`.
          example: null
        decline_reason:
          oneOf:
            - $ref: '#/components/schemas/VoucherDeclineReason'
            - type: string
              enum:
                - reseller_self_cancel
            - type: 'null'
          description: >-
            Motivo quando `status = declined`: um valor de
            `VoucherDeclineReason` ou o valor de sistema `reseller_self_cancel`
            (cancelamento pelo próprio revendedor). `null` nos demais estados.
        reference_id:
          type:
            - string
            - 'null'
          description: >-
            Alias enviado pelo parceiro na criação. Sempre presente: `null`
            quando o voucher foi criado sem alias.
          example: PEDIDO_12345
        created_at:
          type:
            - string
            - 'null'
          format: date-time
          description: Timestamp ISO 8601 de criação do voucher.
          example: '2026-05-07T14:32:11.000Z'
    CertificateType:
      type: string
      description: >-
        Slug do certificado digital a emitir. Combina o titular (`ecpf_*` pessoa
        física, `ecnpj_*` pessoa jurídica) com a mídia do certificado (`*_a1`
        arquivo `.pfx` no computador, `*_a3_nuvem` usa em qualquer dispositivo,
        autorizado por app de celular).
      enum:
        - ecpf_a1
        - ecpf_a3_nuvem
        - ecnpj_a1
        - ecnpj_a3_nuvem
      x-enumDescriptions:
        ecpf_a1: Pessoa física, arquivo .pfx no computador.
        ecpf_a3_nuvem: >-
          Pessoa física, qualquer dispositivo; cada uso autorizado no app de
          celular do titular.
        ecnpj_a1: Pessoa jurídica, arquivo .pfx no computador.
        ecnpj_a3_nuvem: >-
          Pessoa jurídica, qualquer dispositivo; cada uso autorizado no app de
          celular do responsável legal.
      example: ecpf_a1
    VoucherDeclineReason:
      type: string
      description: Motivo da recusa quando `status = declined`.
      enum:
        - missing_cnh_or_prior_certificate
        - voucher_expired
        - id_mismatch
        - documentation_invalid
        - facial_validation_failed
        - customer_gave_up
        - other
      x-enumDescriptions:
        missing_cnh_or_prior_certificate: Titular não apresentou CNH nem certificado prévio válido.
        voucher_expired: O voucher já estava vencido na hora da emissão.
        id_mismatch: Dados do titular não batem com o documento apresentado.
        documentation_invalid: Documentação entregue está inválida ou ilegível.
        facial_validation_failed: Validação facial (prova de vida) falhou durante a emissão.
        customer_gave_up: Titular desistiu da emissão antes de concluir o processo.
        other: Qualquer outro motivo não classificado.
  responses:
    VoucherListPage:
      description: Página de vouchers do parceiro, ordenada por `created_at` decrescente.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/VoucherListPage'
          examples:
            with_results:
              $ref: '#/components/examples/VoucherListSuccessExample'
            empty:
              $ref: '#/components/examples/VoucherListEmptyExample'
    Unauthorized:
      description: Não autenticado.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/VoucherErrorEnvelope'
          examples:
            missing_or_invalid_authorization:
              $ref: '#/components/examples/MissingOrInvalidAuthorizationExample'
            invalid_api_key:
              $ref: '#/components/examples/InvalidApiKeyExample'
            api_key_revoked:
              $ref: '#/components/examples/ApiKeyRevokedExample'
    Forbidden:
      description: Acesso negado.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/VoucherErrorEnvelope'
          examples:
            partner_not_approved:
              $ref: '#/components/examples/PartnerNotApprovedExample'
            tenant_mismatch:
              $ref: '#/components/examples/TenantMismatchExample'
    RateLimitExceeded:
      description: >-
        Limite de requisições excedido para a chave. Aguarde a janela e respeite
        os headers `RateLimit-*`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/VoucherErrorEnvelope'
          examples:
            rate_limit_exceeded:
              $ref: '#/components/examples/RateLimitExceededExample'
      headers:
        RateLimit-Limit:
          description: Limite máximo na janela atual.
          schema:
            type: integer
        RateLimit-Remaining:
          description: Quantas requisições ainda cabem na janela.
          schema:
            type: integer
            example: 0
        RateLimit-Reset:
          description: Segundos até a janela reabrir.
          schema:
            type: integer
            example: 42
    InternalError:
      description: >-
        Falha inesperada do servidor. Reenvie com backoff exponencial; o
        `reference_id` garante idempotência.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/VoucherErrorEnvelope'
          examples:
            internal_error:
              $ref: '#/components/examples/InternalErrorExample'
  examples:
    InvalidFilterExample:
      summary: Filtro de query com valor fora do enum ou data sem timezone
      x-resolution: >-
        Use enum em `status`, ISO-8601 com timezone (`Z` ou `±HH:MM`) nas datas,
        `limit` entre 1 e 100, e não combine `after` com `before`.
      value:
        error: invalid_filter
        message: >-
          Filtro de busca inválido. Verifique status, datas, limit (1-100) e
          cursor (after/before).
        details:
          field: created_after
          reason: must be ISO-8601 with explicit timezone
    UnknownFieldExample:
      summary: Body contém campo não previsto pelo schema do endpoint
      x-resolution: >-
        Remova o campo extra apontado em `details.field` ou troque por um
        aceito.
      value:
        error: unknown_field
        message: 'Campo desconhecido: variant_id'
        details:
          field: variant_id
          valid_values:
            - ecpf_a1
            - ecpf_a3_nuvem
            - ecnpj_a1
            - ecnpj_a3_nuvem
    VoucherListSuccessExample:
      summary: Página com 2 vouchers e mais resultados disponíveis
      value:
        object: list
        has_more: true
        data:
          - voucher_id: ZS_ECPF_A1_01HXYZABCDEFGHJKMNPQRSTV
            certificate_type: ecpf_a1
            status: issued
            issued_at: '2026-05-14T10:30:00.000Z'
            redeemed_at: null
            decline_reason: null
            reference_id: PEDIDO_12345
            created_at: '2026-05-14T10:30:00.000Z'
          - voucher_id: ZS_ECNPJ_A1_01HXYZABCDEFGHJKMNPQRST0
            certificate_type: ecnpj_a1
            status: redeemed
            issued_at: '2026-05-13T08:00:00.000Z'
            redeemed_at: '2026-05-13T09:15:00.000Z'
            decline_reason: null
            reference_id: null
            created_at: '2026-05-13T08:00:00.000Z'
    VoucherListEmptyExample:
      summary: Nenhum voucher casa com os filtros (página vazia, sem mais resultados)
      value:
        object: list
        has_more: false
        data: []
    MissingOrInvalidAuthorizationExample:
      summary: Header `Authorization` ausente ou fora do formato `Bearer <token>`
      x-resolution: Envie o header `Authorization` no formato `Bearer czk_live_...`.
      value:
        error: missing_or_invalid_authorization
        message: Header Authorization ausente ou malformado.
    InvalidApiKeyExample:
      summary: Token Bearer não bate com nenhuma chave válida
      x-resolution: >-
        Gere uma nova chave em
        https://certificados.zapsign.com.br/reseller/api-keys e atualize seus
        secrets.
      value:
        error: invalid_api_key
        message: API key inválida.
    ApiKeyRevokedExample:
      summary: Chave existe mas foi revogada no portal
      x-resolution: >-
        Gere uma nova chave em
        https://certificados.zapsign.com.br/reseller/api-keys e atualize seus
        secrets.
      value:
        error: api_key_revoked
        message: API key revogada.
    PartnerNotApprovedExample:
      summary: Parceiro existe mas o status não está em `approved`
      x-resolution: Aguarde a aprovação do cadastro. Você recebe email quando for liberado.
      value:
        error: partner_not_approved
        message: Parceiro não aprovado.
    TenantMismatchExample:
      summary: O `partnerId` da URL não bate com o dono da chave
      x-resolution: Use a chave do parceiro dono daquele `partnerId`.
      value:
        error: tenant_mismatch
        message: partnerId do path não corresponde ao dono da API key.
    RateLimitExceededExample:
      summary: Limite de requisições excedido para a chave.
      x-resolution: >-
        Reduza a frequência das chamadas e use backoff exponencial antes de
        tentar novamente.
      value:
        error: rate_limit_exceeded
        message: Limite de requisições excedido.
    InternalErrorExample:
      summary: Falha não esperada do servidor
      x-resolution: >-
        Reenvie com backoff exponencial. O mesmo `reference_id` garante
        idempotência.
      value:
        error: internal_error
        message: Erro interno do servidor.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: czk_live_*
      description: >-
        Token Bearer com prefixo `czk_live_`. Gere a chave no portal em
        [https://certificados.zapsign.com.br/reseller/api-keys](https://certificados.zapsign.com.br/reseller/api-keys).

````