{
  "openapi": "3.0.4",
  "info": {
    "title": "Tokenização",
    "version": "v2",
    "description": "Spec pública sanitizada pelo DevPortal a partir da spec do serviço (não gerada do código). Ver openapi/public.config.json."
  },
  "paths": {
    "/v2/tokenization": {
      "post": {
        "tags": [
          "Tokenization"
        ],
        "summary": "Cria um token representando as informações do cartão de pagamento fornecidas.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "description": "TOK-S09: chave opaca escolhida pelo cliente, escopada por tenant, até 255 caracteres. Opcional - sem ela, o comportamento é o de sempre.",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "requestBody": {
          "description": "Os detalhes do cartão e informações contextuais necessárias para tokenização. Não deve ser nulo.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenizeCardRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Sucesso. Se a resposta for o replay de uma Idempotency-Key já concluída, o cabeçalho Idempotent-Replayed vem \"true\" e o corpo é o mesmo token já tokenizado - nenhuma tokenização nova acontece.",
            "headers": {
              "Idempotent-Replayed": {
                "description": "Presente e \"true\" só quando a resposta é o replay de uma Idempotency-Key já concluída. Ausente em toda tokenização nova.",
                "schema": {
                  "type": "string",
                  "enum": [
                    "true"
                  ]
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ResponseDefaultTokenData"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "409": {
            "description": "TOK-S09: conflito de Idempotency-Key. O code em errors[] distingue IDEMPOTENCY_IN_PROGRESS (outra requisição com a mesma chave ainda em andamento; aguardar Retry-After e repetir) de IDEMPOTENCY_KEY_REUSED (mesma chave, corpo de requisição diferente; o cliente deve usar uma chave nova).",
            "headers": {
              "Retry-After": {
                "description": "Segundos até a lease da requisição em andamento vencer. Presente só em IDEMPOTENCY_IN_PROGRESS.",
                "schema": {
                  "type": "integer",
                  "format": "int32"
                }
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "422": {
            "description": "Erro de validação dos dados do cartão.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        }
      }
    },
    "/v2/tokenization/{tokenId}": {
      "delete": {
        "tags": [
          "Tokenization"
        ],
        "summary": "Expira um token identificado pelo token ID especificado para o tenant atual.",
        "description": "Esta operação é tipicamente usada para invalidar um token antes da expiração natural. O token deve pertencer ao contexto do tenant atual. Se o token não existir ou já estiver expirado, a resposta indicará o status apropriado.",
        "parameters": [
          {
            "name": "tokenId",
            "in": "path",
            "description": "O identificador único do token a ser expirado.",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "description": "O objeto de requisição contendo informações adicionais necessárias para expirar o token.",
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ExpireTokenRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Sucesso: o token foi expirado."
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ExpireTokenRequest": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": false
      },
      "ProblemDetails": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "nullable": true
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          },
          "detail": {
            "type": "string",
            "nullable": true
          },
          "instance": {
            "type": "string",
            "nullable": true
          }
        },
        "additionalProperties": {}
      },
      "ResponseDefaultTokenData": {
        "additionalProperties": false,
        "description": "Envelope com os dados mascarados de um token.",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/TokenDataResponse"
          },
          "errors": {
            "description": "Erros do resultado, com código, mensagem e campo.",
            "items": {
              "$ref": "#/components/schemas/Notification"
            },
            "nullable": true,
            "type": "array"
          },
          "message": {
            "description": "Mensagem legível do resultado.",
            "nullable": true,
            "type": "string"
          },
          "statusCode": {
            "description": "Código de status do resultado, igual ao status HTTP exceto onde a operação documenta o contrário.",
            "format": "int32",
            "type": "integer"
          },
          "success": {
            "description": "Indica se a operação foi concluída com sucesso.",
            "type": "boolean"
          }
        },
        "type": "object"
      },
      "Notification": {
        "additionalProperties": false,
        "properties": {
          "code": {
            "nullable": true,
            "type": "string"
          },
          "message": {
            "nullable": true,
            "type": "string"
          },
          "propertyName": {
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "TokenDataResponse": {
        "additionalProperties": false,
        "properties": {
          "bin": {
            "nullable": true,
            "type": "string"
          },
          "brand": {
            "nullable": true,
            "type": "string"
          },
          "cardHolderDocument": {
            "nullable": true,
            "type": "string"
          },
          "cardHolderName": {
            "nullable": true,
            "type": "string"
          },
          "expirationMonth": {
            "format": "int32",
            "type": "integer"
          },
          "expirationYear": {
            "format": "int32",
            "type": "integer"
          },
          "expiresAt": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "isActive": {
            "type": "boolean"
          },
          "last4": {
            "nullable": true,
            "type": "string"
          },
          "lastUsedAt": {
            "format": "date-time",
            "nullable": true,
            "type": "string"
          },
          "maskPan": {
            "nullable": true,
            "type": "string"
          },
          "token": {
            "nullable": true,
            "type": "string",
            "description": "Token opaco do cartão. Use este valor em card.cardToken para pagar com o cartão salvo; o número do cartão não volta mais."
          },
          "tokenId": {
            "nullable": true,
            "type": "string",
            "description": "Identificador do token (CardTokenId). É a chave de DELETE /v2/tokenization/{tokenId} e também é aceito como card.cardToken no pagamento."
          }
        },
        "type": "object"
      },
      "TokenizeCardRequest": {
        "type": "object",
        "properties": {
          "buyerId": {
            "type": "string",
            "format": "uuid"
          },
          "pan": {
            "type": "string",
            "nullable": true
          },
          "expirationMonth": {
            "type": "integer",
            "format": "int32"
          },
          "expirationYear": {
            "type": "integer",
            "format": "int32"
          },
          "cvv": {
            "type": "string",
            "nullable": true
          },
          "cardholderName": {
            "type": "string",
            "nullable": true
          },
          "cardholderDocument": {
            "type": "string",
            "nullable": true
          },
          "ttlHours": {
            "type": "integer",
            "format": "int32",
            "nullable": true
          }
        },
        "additionalProperties": false,
        "required": [
          "buyerId",
          "pan",
          "cvv",
          "expirationMonth",
          "expirationYear"
        ]
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "apiKey",
        "description": "Cabeçalho de autorização JWT usando o esquema Bearer. Exemplo: \"Authorization: Bearer {token}\"",
        "name": "Authorization",
        "in": "header"
      }
    }
  }
}