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

# Salvar cartão a partir de um token

> Guarda um cartão no cliente sem passar pelo gateway — para ter a forma de pagamento antes da primeira compra.

`POST /customers/{customerId}/cards`

Faz parte do recurso [Cartões](/pt-BR/cards) — como um cartão nasce e como cobrá-lo depois estão lá.

Salva o cartão a partir de um token do [Tokenizer](/pt-BR/tokenizer) e devolve o `crd_` reutilizável.
O corpo tem um campo só, `token`, e **nada é cobrado**: a chamada não passa pelo gateway.

<Note>
  **Na maior parte das integrações você não precisa desta rota.** Criar uma transação de cartão com
  `customerId` e `token` já salva o `crd_` sozinho. Esta existe para o caso inverso — guardar a forma
  de pagamento **antes** de haver o que cobrar, como num cadastro de assinatura que só começa depois.
</Note>

<Warning>
  **O token é de uso único e morre aqui.** O `tok_` do Tokenizer vale 24 horas e é consumido nesta
  chamada — reenviá-lo responde `400 Token inválido ou expirado`, mesmo que ainda esteja dentro do
  prazo. Para salvar outro cartão, gere um token novo.
</Warning>

<Note>
  **Salvar o mesmo cartão duas vezes não cria dois.** A gravação deduplica pela impressão digital do
  cartão no escopo daquele cliente, então a segunda chamada devolve o **mesmo** `crd_` — com `201`,
  não com erro. Em clientes diferentes, os `crd_` são distintos.
</Note>

<Note>
  **Cliente inexistente responde `404` sem gastar o token.** A validação do cliente acontece antes de
  consumir o `tok_` — de propósito, para que um `customerId` errado não queime um token que ainda
  poderia ser usado.
</Note>

<Info>
  Endpoint idempotente. Envie o header `Idempotency-Key` para que um retry por timeout não repita a
  operação. Veja [Convenções](/pt-BR/convencoes).
</Info>


## OpenAPI

````yaml openapi/psp.json POST /customers/{customerId}/cards
openapi: 3.0.3
info:
  title: Z2Pay PSP API
  version: 1.0.0
  description: API pública do PSP — autenticação via API Key (Credential)
servers:
  - url: https://api.sandbox.z2pay.com/v1
    description: Sandbox
  - url: https://api.z2pay.com/v1
    description: Produção
security: []
tags:
  - name: Cards
    description: Cartões salvos de um cliente
  - name: Chargebacks
    description: Gerenciamento de chargebacks
  - name: Customers
    description: Gerenciamento de clientes (compradores)
  - name: Fees
    description: Tabela de taxas da conta (pix, boleto, cartão, saque, refund, chargeback)
  - name: Recipients
    description: Gerenciamento de recebedores (sellers/merchants que recebem repasses)
  - name: Refunds
    description: Gerenciamento de reembolsos e estornos
  - name: Splits
    description: Regras de divisão do valor de uma venda entre recebedores
  - name: Transactions
    description: Gerenciamento de transações e payments
  - name: Wallets
    description: Saldo, extrato e resumo da carteira de um recebedor, agrupados por moeda
  - name: Webhooks
    description: Configuração, gerenciamento e histórico de entregas de webhooks
  - name: Withdrawals
    description: Solicitação e acompanhamento de saques (payouts) por recipient
paths:
  /customers/{customerId}/cards:
    post:
      tags:
        - Cards
      summary: Salvar cartão a partir de um token
      description: >-
        Salva um cartão (card-on-file) para o cliente a partir de um token
        one-shot do tokenizer (tok_*), sem realizar cobrança. O token é
        consumido no processo — use o header Idempotency-Key para retries
        seguros
      operationId: CardController_create
      parameters:
        - name: customerId
          in: path
          required: true
          description: ID do cliente
          schema:
            type: string
        - name: Idempotency-Key
          in: header
          required: false
          description: Chave única para garantir idempotência da requisição
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                token:
                  type: string
                  description: >-
                    Token one-shot do Tokenizer (tok_*) usado para salvar o
                    cartão sem cobrança.
              required:
                - token
      responses:
        '201':
          description: Cartão criado
          content:
            application/json:
              example:
                id: crd_hqx4mkpi8dcxbrb2nzynxnjky
                customerId: cust_j43n74fbt2geb8c1y86ssf6iw
                brand: visa
                firstDigits: '411111'
                lastDigits: '1111'
                holderName: JOAO DA SILVA
                expirationMonth: '12'
                expirationYear: '2030'
                status: active
                createdAt: '2026-07-02T19:26:17.000Z'
                updatedAt: '2026-07-02T19:26:17.000Z'
              schema:
                type: object
                properties:
                  id:
                    type: string
                    description: ID do cartão (`crd_`).
                  customerId:
                    type: string
                    description: Cliente dono do cartão (`cust_`).
                  brand:
                    type: string
                    description: 'Bandeira (ex.: `visa`, `mastercard`).'
                  firstDigits:
                    type: string
                    description: Seis primeiros dígitos.
                  lastDigits:
                    type: string
                    description: Quatro últimos dígitos.
                  holderName:
                    type: string
                    description: Nome impresso no cartão.
                  expirationMonth:
                    type: string
                    description: Mês de validade (`MM`).
                  expirationYear:
                    type: string
                    description: Ano de validade (`YYYY`).
                  status:
                    type: string
                    description: Situação do cartão.
                  createdAt:
                    type: string
                    description: Criação, ISO 8601.
                  updatedAt:
                    type: string
                    description: Última alteração, ISO 8601.
        '400':
          description: Token inválido ou expirado
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
                      issues:
                        type: array
                        description: >-
                          Um item por campo rejeitado. Nunca vem vazio: se há
                          400 de validação, há pelo menos um.
                        items:
                          type: object
                          properties:
                            path:
                              type: string
                              description: >-
                                Campo que falhou. Vem vazio quando o erro é do
                                corpo como um todo.
                            message:
                              type: string
                              description: O que há de errado com esse campo.
              example:
                error:
                  code: VALIDATION_ERROR
                  message: Validation failed
                  issues:
                    - path: status
                      message: >-
                        Status inválido. Valores aceitos: pending,
                        waiting_payment, paid, refused, canceled, refunded
                    - path: startDate
                      message: >-
                        Data deve ser ISO 8601 com timezone (ex.:
                        2026-06-24T00:00:00Z)
        '401':
          description: Chave de API ausente, malformada ou inválida
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: UNAUTHORIZED
                  message: Invalid API key
        '404':
          description: Cliente não encontrado
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: object
                    properties:
                      code:
                        type: string
                        description: >-
                          Identificador estável do erro. É por ele que você deve
                          ramificar, não pela mensagem.
                      message:
                        type: string
                        description: >-
                          Descrição legível. Pode mudar sem aviso e não deve ser
                          usada em condicional.
              example:
                error:
                  code: NOT_FOUND
                  message: Card not found
        '409':
          description: >-
            Já existe uma requisição em andamento com esta Idempotency-Key. A
            API aguarda a primeira concluir por até 5 segundos antes de
            responder assim
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: >-
                      Mensagem do conflito de idempotência. Aqui `error` é
                      texto, não objeto — ramifique pelo status HTTP.
              example:
                error: A request with this idempotency key is already being processed
        '422':
          description: >-
            Idempotency-Key já usada com um corpo diferente. Use uma chave nova
            para uma operação diferente
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    description: >-
                      Mensagem do conflito de idempotência. Aqui `error` é
                      texto, não objeto — ramifique pelo status HTTP.
              example:
                error: Idempotency key already used with a different request body
      security:
        - apiKey: []
components:
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: x-api-key
      description: API Key da Credential (gerada no Backoffice)

````