Explore todos os endpoints, parâmetros, corpos e respostas do contrato atual. Use a busca para encontrar uma operação.
Expanda uma operação para ver seu contrato e as estruturas de dados associadas. Os nomes dos campos estão em inglês, como na API. Campos required são obrigatórios; enum lista os valores aceitos.
Os caminhos incluem /api/v1. Endpoints de operador e provedor não são recursos de integração livre para vendedores.
Esta é uma referência de consulta: não executa requisições nem solicita suas credenciais. Siga os guias para fazer as primeiras chamadas.
/healthDisponibilidade do serviço e do bancoAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"health"
],
"summary": "Disponibilidade do serviço e do banco",
"security": [],
"responses": {
"200": {
"description": "Serviço no ar.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Health"
},
"example": {
"status": "ok",
"mode": "local",
"payments_enabled": false,
"provider": "simulation",
"origin": "http://localhost:3000"
}
}
}
}
},
"operationId": "healthCheck"
}{
"type": "object",
"required": [
"status",
"mode",
"payments_enabled",
"provider",
"origin"
],
"properties": {
"status": {
"type": "string",
"enum": [
"ok"
]
},
"mode": {
"type": "string",
"enum": [
"local",
"test"
]
},
"payments_enabled": {
"type": "boolean",
"enum": [
false
]
},
"provider": {
"type": "string",
"description": "Adaptador de provedor em uso. Hoje sempre \"simulation\"."
},
"origin": {
"type": "string",
"format": "uri",
"description": "Origem que esta instância aceita em requisições de alteração. Publicada para ferramentas de linha de comando não discordarem da API no ar."
}
}
}/api/v1/auth/registerCriar contaResponde sempre a mesma mensagem, exista ou não a conta, para não revelar cadastros. Quando o e-mail é novo, enfileira o link de confirmação na caixa local.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Criar conta",
"description": "Responde sempre a mesma mensagem, exista ou não a conta, para não revelar cadastros. Quando o e-mail é novo, enfileira o link de confirmação na caixa local.",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterInput"
}
}
}
},
"responses": {
"202": {
"$ref": "#/components/responses/Accepted"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"413": {
"$ref": "#/components/responses/TooLarge"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "registerAccount"
}{
"type": "object",
"additionalProperties": false,
"required": [
"email",
"password",
"name"
],
"properties": {
"email": {
"$ref": "#/components/schemas/Email"
},
"password": {
"$ref": "#/components/schemas/Password"
},
"name": {
"type": "string",
"minLength": 2,
"maxLength": 120
}
}
}{
"type": "string",
"format": "email",
"maxLength": 254,
"description": "Normalizado para minúsculas e sem espaços nas pontas."
}{
"type": "string",
"minLength": 12,
"maxLength": 128,
"description": "Guardada com scrypt e sal aleatório."
}/api/v1/auth/loginEntrarCria sessão opaca no servidor e devolve o cookie movvi_session (HttpOnly, SameSite=Lax, Secure quando a origem é HTTPS). O csrf_token da resposta deve acompanhar as alterações autenticadas no cabeçalho X-CSRF-Token. Quando a conta tem segundo fator confirmado, responde 200 com second_factor_required e um desafio, sem criar sessao; a entrada termina em POST /auth/second-factor.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Entrar",
"description": "Cria sessão opaca no servidor e devolve o cookie movvi_session (HttpOnly, SameSite=Lax, Secure quando a origem é HTTPS). O csrf_token da resposta deve acompanhar as alterações autenticadas no cabeçalho X-CSRF-Token. Quando a conta tem segundo fator confirmado, responde 200 com second_factor_required e um desafio, sem criar sessao; a entrada termina em POST /auth/second-factor.",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginInput"
}
}
}
},
"responses": {
"200": {
"description": "Sessão criada.",
"headers": {
"Set-Cookie": {
"description": "movvi_session=<64 hex>; Path=/; HttpOnly; SameSite=Lax; Max-Age=43200",
"schema": {
"type": "string"
}
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionUser"
}
}
}
},
"401": {
"description": "Credenciais inválidas ou conta desativada. A mesma resposta é usada nos três casos.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "login"
}{
"type": "object",
"additionalProperties": false,
"required": [
"email",
"password"
],
"properties": {
"email": {
"$ref": "#/components/schemas/Email"
},
"password": {
"type": "string",
"minLength": 1,
"maxLength": 128
}
}
}{
"type": "string",
"format": "email",
"maxLength": 254,
"description": "Normalizado para minúsculas e sem espaços nas pontas."
}{
"type": "object",
"required": [
"user_id",
"name",
"email",
"email_verified",
"csrf_token"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"email_verified": {
"type": "boolean"
},
"csrf_token": {
"type": "string"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/auth/logoutSairRevoga a sessão atual e limpa o cookie. Não tem corpo, mas ainda assim exige Content-Type: application/json.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Sair",
"description": "Revoga a sessão atual e limpa o cookie. Não tem corpo, mas ainda assim exige Content-Type: application/json.",
"parameters": [
{
"$ref": "#/components/parameters/ContentType"
},
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"responses": {
"204": {
"description": "Sessão revogada. Sem corpo."
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenMutation"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "logout"
}/api/v1/auth/sessionSessão atual e vínculosRenova o carimbo de atividade da sessão. A sessão expira em 12 horas de duração máxima ou 30 minutos sem atividade.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Sessão atual e vínculos",
"description": "Renova o carimbo de atividade da sessão. A sessão expira em 12 horas de duração máxima ou 30 minutos sem atividade.",
"responses": {
"200": {
"description": "Sessão válida.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SessionState"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "getSession"
}{
"allOf": [
{
"$ref": "#/components/schemas/SessionUser"
},
{
"type": "object",
"required": [
"memberships"
],
"properties": {
"memberships": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Membership"
}
}
}
}
]
}{
"type": "object",
"required": [
"user_id",
"name",
"email",
"email_verified",
"csrf_token"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"email_verified": {
"type": "boolean"
},
"csrf_token": {
"type": "string"
}
}
}{
"type": "object",
"required": [
"seller_id",
"role"
],
"properties": {
"seller_id": {
"type": "string",
"format": "uuid"
},
"role": {
"type": "string",
"enum": [
"owner"
],
"description": "Somente owner é criado nesta etapa."
}
}
}/api/v1/auth/verify-emailConfirmar e-mailConsome o token do link de confirmação. Tokens são de uso único e expiram em 24 horas. O código demonstrativo 123456 não é aceito.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Confirmar e-mail",
"description": "Consome o token do link de confirmação. Tokens são de uso único e expiram em 24 horas. O código demonstrativo 123456 não é aceito.",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenInput"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/Message"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"422": {
"description": "Token inválido, já usado ou expirado (TOKEN_INVALID), ou campos fora do formato (VALIDATION_ERROR).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "verifyEmail"
}{
"type": "object",
"additionalProperties": false,
"required": [
"token"
],
"properties": {
"token": {
"$ref": "#/components/schemas/Token"
}
}
}{
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "Token do link enviado à caixa local. Uso único."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/auth/resend-verificationReenviar confirmação de e-mailExige sessão. Não faz nada quando o e-mail já está confirmado, mas responde igual. Não tem corpo, mas ainda assim exige Content-Type: application/json.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Reenviar confirmação de e-mail",
"description": "Exige sessão. Não faz nada quando o e-mail já está confirmado, mas responde igual. Não tem corpo, mas ainda assim exige Content-Type: application/json.",
"parameters": [
{
"$ref": "#/components/parameters/ContentType"
},
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"responses": {
"202": {
"$ref": "#/components/responses/Accepted"
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenMutation"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "resendVerification"
}/api/v1/auth/password-recoveryPedir link de recuperaçãoResponde sempre a mesma mensagem, exista ou não a conta. O token de redefinição expira em 30 minutos.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Pedir link de recuperação",
"description": "Responde sempre a mesma mensagem, exista ou não a conta. O token de redefinição expira em 30 minutos.",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"email"
],
"properties": {
"email": {
"$ref": "#/components/schemas/Email"
}
}
}
}
}
},
"responses": {
"202": {
"$ref": "#/components/responses/Accepted"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "requestPasswordRecovery"
}{
"type": "string",
"format": "email",
"maxLength": 254,
"description": "Normalizado para minúsculas e sem espaços nas pontas."
}/api/v1/auth/password-resetRedefinir senhaConsome o token de recuperação e revoga todas as sessões do usuário.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"auth"
],
"summary": "Redefinir senha",
"description": "Consome o token de recuperação e revoga todas as sessões do usuário.",
"security": [],
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasswordResetInput"
}
}
}
},
"responses": {
"200": {
"$ref": "#/components/responses/Message"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"422": {
"description": "Token inválido, já usado ou expirado (TOKEN_INVALID), ou campos fora do formato (VALIDATION_ERROR).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "resetPassword"
}{
"type": "object",
"additionalProperties": false,
"required": [
"token",
"password"
],
"properties": {
"token": {
"$ref": "#/components/schemas/Token"
},
"password": {
"$ref": "#/components/schemas/Password"
}
}
}{
"type": "string",
"pattern": "^[a-f0-9]{64}$",
"description": "Token do link enviado à caixa local. Uso único."
}{
"type": "string",
"minLength": 12,
"maxLength": 128,
"description": "Guardada com scrypt e sal aleatório."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellersListar os negócios do usuárioRetorna apenas os vendedores em que o usuário tem vínculo. Exige e-mail confirmado.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"sellers"
],
"summary": "Listar os negócios do usuário",
"description": "Retorna apenas os vendedores em que o usuário tem vínculo. Exige e-mail confirmado.",
"responses": {
"200": {
"description": "Lista de vínculos.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/SellerListItem"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "listSellers"
}{
"type": "object",
"required": [
"id",
"legal_name",
"trade_name",
"status",
"version",
"role"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"legal_name": {
"type": "string"
},
"trade_name": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/SellerStatus"
},
"version": {
"type": "integer"
},
"role": {
"type": "string"
}
}
}{
"type": "string",
"enum": [
"draft",
"verification_pending",
"needs_changes",
"approved",
"rejected"
],
"description": "approved é a aprovação da plataforma, não do provedor; nenhuma rota depende dele para liberar pagamento."
}/api/v1/sellersCadastrar negócioCria o vendedor e o vínculo owner do usuário autenticado. O documento é guardado cifrado; a unicidade usa impressão HMAC, então documentos repetidos respondem 409 sem revelar de quem é o cadastro existente.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"sellers"
],
"summary": "Cadastrar negócio",
"description": "Cria o vendedor e o vínculo owner do usuário autenticado. O documento é guardado cifrado; a unicidade usa impressão HMAC, então documentos repetidos respondem 409 sem revelar de quem é o cadastro existente.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerInput"
}
}
}
},
"responses": {
"201": {
"description": "Negócio cadastrado.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerCreated"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"409": {
"description": "Documento já cadastrado (SELLER_CONFLICT).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "createSeller"
}{
"type": "object",
"additionalProperties": false,
"required": [
"legal_name",
"trade_name",
"tax_id",
"terms_version"
],
"properties": {
"legal_name": {
"type": "string",
"minLength": 2,
"maxLength": 160
},
"trade_name": {
"type": "string",
"minLength": 2,
"maxLength": 120
},
"tax_id": {
"type": "string",
"pattern": "^\\d{11}$|^\\d{14}$",
"description": "CPF ou CNPJ apenas com dígitos. Os dígitos verificadores são conferidos. Guardado cifrado com AES-GCM; nunca é devolvido nas respostas."
},
"terms_version": {
"type": "string",
"enum": [
"local-v1"
],
"description": "Aviso de teste do ambiente local. Não substitui os termos de produção."
}
}
}{
"type": "object",
"required": [
"id",
"status",
"version"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"enum": [
"draft"
]
},
"version": {
"type": "integer",
"enum": [
1
]
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}Detalhe do negócioResponde 404, e não 403, quando não há vínculo, para não revelar a existência do registro.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"sellers"
],
"summary": "Detalhe do negócio",
"description": "Responde 404, e não 403, quando não há vínculo, para não revelar a existência do registro.",
"responses": {
"200": {
"description": "Dados do vendedor.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Seller"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "getSeller"
}{
"type": "object",
"required": [
"id",
"legal_name",
"trade_name",
"status",
"version",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"legal_name": {
"type": "string"
},
"trade_name": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/SellerStatus"
},
"version": {
"type": "integer"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "string",
"enum": [
"draft",
"verification_pending",
"needs_changes",
"approved",
"rejected"
],
"description": "approved é a aprovação da plataforma, não do provedor; nenhuma rota depende dele para liberar pagamento."
}/api/v1/sellers/{seller_id}Alterar o nome da lojaÚnico campo alterável nesta etapa. Exige vínculo owner e expected_version igual à versão atual; divergência responde 409.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"sellers"
],
"summary": "Alterar o nome da loja",
"description": "Único campo alterável nesta etapa. Exige vínculo owner e expected_version igual à versão atual; divergência responde 409.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerPatchInput"
}
}
}
},
"responses": {
"200": {
"description": "Alteração aplicada.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerPatched"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"$ref": "#/components/responses/VersionConflict"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "updateSeller"
}{
"type": "object",
"additionalProperties": false,
"required": [
"trade_name",
"expected_version"
],
"properties": {
"trade_name": {
"type": "string",
"minLength": 2,
"maxLength": 120
},
"expected_version": {
"type": "integer",
"minimum": 1
}
}
}{
"type": "object",
"required": [
"id",
"trade_name",
"version"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"trade_name": {
"type": "string"
},
"version": {
"type": "integer"
}
}
}/api/v1/sellers/{seller_id}/verificationHistórico de envios de verificaçãoAté 20 registros, da versão mais recente para a mais antiga. Exige vínculo owner. provider_connected é sempre false nesta etapa: não existe análise externa.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"verification"
],
"summary": "Histórico de envios de verificação",
"description": "Até 20 registros, da versão mais recente para a mais antiga. Exige vínculo owner. provider_connected é sempre false nesta etapa: não existe análise externa.",
"responses": {
"200": {
"description": "Envios registrados.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"provider_connected"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/VerificationCase"
}
},
"provider_connected": {
"type": "boolean",
"enum": [
false
]
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "listVerificationCases"
}{
"type": "object",
"required": [
"id",
"version",
"status",
"business_url",
"segment",
"description",
"consent_version",
"submitted_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"version": {
"type": "integer"
},
"status": {
"type": "string",
"enum": [
"submitted",
"needs_changes",
"approved",
"rejected"
]
},
"business_url": {
"type": "string",
"format": "uri"
},
"segment": {
"$ref": "#/components/schemas/Segment"
},
"description": {
"type": "string"
},
"consent_version": {
"type": "string"
},
"submitted_at": {
"type": "string",
"format": "date-time"
},
"decision_reason": {
"type": "string",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"game_items",
"digital_products",
"other"
]
}/api/v1/sellers/{seller_id}/verification-submissionsEnviar dados para verificaçãoAceito somente quando o vendedor está em draft ou needs_changes. Muda a situação para verification_pending e incrementa a versão. NÃO representa aprovação financeira: nenhum arquivo é transmitido e não há análise externa.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"verification"
],
"summary": "Enviar dados para verificação",
"description": "Aceito somente quando o vendedor está em draft ou needs_changes. Muda a situação para verification_pending e incrementa a versão. NÃO representa aprovação financeira: nenhum arquivo é transmitido e não há análise externa.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VerificationSubmissionInput"
}
}
}
},
"responses": {
"202": {
"description": "Envio registrado localmente.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/VerificationSubmitted"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Versão divergente (VERSION_CONFLICT) ou situação que não permite novo envio (INVALID_STATE).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "submitVerification"
}{
"type": "object",
"additionalProperties": false,
"required": [
"expected_version",
"business_url",
"segment",
"description",
"consent_version"
],
"properties": {
"expected_version": {
"type": "integer",
"minimum": 1
},
"business_url": {
"type": "string",
"format": "uri",
"maxLength": 500,
"description": "Somente http ou https."
},
"segment": {
"$ref": "#/components/schemas/Segment"
},
"description": {
"type": "string",
"minLength": 10,
"maxLength": 2000
},
"consent_version": {
"type": "string",
"enum": [
"local-v1"
],
"description": "Aviso de teste do ambiente local."
}
}
}{
"type": "string",
"enum": [
"game_items",
"digital_products",
"other"
]
}{
"type": "object",
"required": [
"id",
"status",
"provider_connected",
"message"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"status": {
"type": "string",
"enum": [
"submitted"
]
},
"provider_connected": {
"type": "boolean",
"enum": [
false
]
},
"message": {
"type": "string"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/audit-eventsEventos de auditoria do vendedor50 registros por página, do mais recente para o mais antigo. Exige vínculo owner. A tabela bloqueia UPDATE, DELETE e TRUNCATE por gatilhos. A paginação por offset é do protótipo local; trocar por cursor antes de expor a API externamente.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"tags": [
"audit"
],
"summary": "Eventos de auditoria do vendedor",
"description": "50 registros por página, do mais recente para o mais antigo. Exige vínculo owner. A tabela bloqueia UPDATE, DELETE e TRUNCATE por gatilhos. A paginação por offset é do protótipo local; trocar por cursor antes de expor a API externamente.",
"parameters": [
{
"$ref": "#/components/parameters/Offset"
}
],
"responses": {
"200": {
"description": "Página de eventos.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AuditEvent"
}
},
"next_offset": {
"type": "integer",
"nullable": true,
"description": "Próximo offset, ou null quando a página não encheu."
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"operationId": "listAuditEvents"
}{
"type": "object",
"required": [
"id",
"action",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"action": {
"type": "string",
"description": "Nome do evento, como charge.paid, verification.approved ou fees.published. A lista cresce com o produto."
},
"target_id": {
"type": "string",
"nullable": true
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/chargesListar cobranças do vendedor50 por página, da mais recente para a mais antiga.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listCharges",
"tags": [
"charges"
],
"summary": "Listar cobranças do vendedor",
"description": "50 por página, da mais recente para a mais antiga.",
"parameters": [
{
"$ref": "#/components/parameters/ChargeStatusFilter"
},
{
"$ref": "#/components/parameters/Offset"
}
],
"responses": {
"200": {
"description": "Página de cobranças.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Charge"
}
},
"next_offset": {
"type": "integer",
"nullable": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"customer_name",
"product",
"status",
"expired_by_time",
"checkout_token",
"provider",
"provider_charge_id",
"simulated",
"expires_at",
"paid_at",
"created_at",
"updated_at",
"fee_version",
"refunded_cents"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa copiada da versão vigente na criação. Mudar a tarifa não altera cobranças já criadas."
},
"customer_name": {
"type": "string"
},
"product": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/ChargeStatus"
},
"expired_by_time": {
"type": "boolean",
"description": "Verdadeiro quando ainda está \"pending\" e já passou de expires_at. Serve para a interface, não muda o estado gravado."
},
"checkout_token": {
"type": "string",
"pattern": "^[a-f0-9]{32}$"
},
"provider": {
"type": "string"
},
"provider_charge_id": {
"type": "string"
},
"simulated": {
"type": "boolean",
"description": "Verdadeiro enquanto o adaptador não move dinheiro real."
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"paid_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"fee_version": {
"type": "integer",
"description": "Versão de tarifa que valia quando a cobrança foi criada. Publicar uma versão nova não altera cobranças existentes."
},
"refunded_cents": {
"type": "integer",
"description": "Soma das devoluções concluídas. O restante devolvível é amount_cents menos este valor."
}
}
}{
"type": "string",
"enum": [
"pending",
"paid",
"expired",
"canceled"
],
"description": "Situação gravada. Uma cobrança vencida continua \"pending\" até o provedor avisar: quem decide se um pagamento atrasado foi aceito é ele, não o relógio do servidor."
}/api/v1/sellers/{seller_id}/chargesCriar cobrançaCopia a tarifa vigente para a cobrança, pede o código ao adaptador de provedor e devolve a URL do checkout. Enquanto o adaptador for o de simulação, nada é pagável.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "createCharge",
"tags": [
"charges"
],
"summary": "Criar cobrança",
"description": "Copia a tarifa vigente para a cobrança, pede o código ao adaptador de provedor e devolve a URL do checkout. Enquanto o adaptador for o de simulação, nada é pagável.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
},
{
"$ref": "#/components/parameters/IdempotencyKey"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChargeInput"
}
}
}
},
"responses": {
"201": {
"description": "Cobrança criada, ou a primeira resposta repetida pela chave de idempotência.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ChargeCreated"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Chave de idempotência reutilizada com outros dados (IDEMPOTENCY_MISMATCH).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR), valor que não cobre a tarifa (AMOUNT_BELOW_FEE) ou chave de idempotência mal formada (IDEMPOTENCY_KEY_INVALID).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"customer_name",
"product",
"amount_cents"
],
"properties": {
"customer_name": {
"type": "string",
"minLength": 1,
"maxLength": 120
},
"product": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"amount_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000,
"description": "Em centavos. Precisa ser maior que a tarifa vigente, senão 422 AMOUNT_BELOW_FEE."
}
}
}{
"allOf": [
{
"$ref": "#/components/schemas/Charge"
},
{
"type": "object",
"required": [
"payload",
"checkout_url"
],
"properties": {
"payload": {
"type": "string",
"description": "O que o comprador copiaria no aplicativo do banco. Com o adaptador de simulação vem prefixado por MOVVI-SIMULACAO-NAO-PAGAVEL e não é pagável."
},
"checkout_url": {
"type": "string",
"format": "uri"
}
}
}
]
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"customer_name",
"product",
"status",
"expired_by_time",
"checkout_token",
"provider",
"provider_charge_id",
"simulated",
"expires_at",
"paid_at",
"created_at",
"updated_at",
"fee_version",
"refunded_cents"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa copiada da versão vigente na criação. Mudar a tarifa não altera cobranças já criadas."
},
"customer_name": {
"type": "string"
},
"product": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/ChargeStatus"
},
"expired_by_time": {
"type": "boolean",
"description": "Verdadeiro quando ainda está \"pending\" e já passou de expires_at. Serve para a interface, não muda o estado gravado."
},
"checkout_token": {
"type": "string",
"pattern": "^[a-f0-9]{32}$"
},
"provider": {
"type": "string"
},
"provider_charge_id": {
"type": "string"
},
"simulated": {
"type": "boolean",
"description": "Verdadeiro enquanto o adaptador não move dinheiro real."
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"paid_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"fee_version": {
"type": "integer",
"description": "Versão de tarifa que valia quando a cobrança foi criada. Publicar uma versão nova não altera cobranças existentes."
},
"refunded_cents": {
"type": "integer",
"description": "Soma das devoluções concluídas. O restante devolvível é amount_cents menos este valor."
}
}
}{
"type": "string",
"enum": [
"pending",
"paid",
"expired",
"canceled"
],
"description": "Situação gravada. Uma cobrança vencida continua \"pending\" até o provedor avisar: quem decide se um pagamento atrasado foi aceito é ele, não o relógio do servidor."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/charges/{charge_id}Detalhe da cobrançaResponde 404 quando a cobrança é de outro vendedor, sem revelar que ela existe.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getCharge",
"tags": [
"charges"
],
"summary": "Detalhe da cobrança",
"description": "Responde 404 quando a cobrança é de outro vendedor, sem revelar que ela existe.",
"responses": {
"200": {
"description": "Cobrança.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Charge"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"customer_name",
"product",
"status",
"expired_by_time",
"checkout_token",
"provider",
"provider_charge_id",
"simulated",
"expires_at",
"paid_at",
"created_at",
"updated_at",
"fee_version",
"refunded_cents"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa copiada da versão vigente na criação. Mudar a tarifa não altera cobranças já criadas."
},
"customer_name": {
"type": "string"
},
"product": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/ChargeStatus"
},
"expired_by_time": {
"type": "boolean",
"description": "Verdadeiro quando ainda está \"pending\" e já passou de expires_at. Serve para a interface, não muda o estado gravado."
},
"checkout_token": {
"type": "string",
"pattern": "^[a-f0-9]{32}$"
},
"provider": {
"type": "string"
},
"provider_charge_id": {
"type": "string"
},
"simulated": {
"type": "boolean",
"description": "Verdadeiro enquanto o adaptador não move dinheiro real."
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"paid_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"fee_version": {
"type": "integer",
"description": "Versão de tarifa que valia quando a cobrança foi criada. Publicar uma versão nova não altera cobranças existentes."
},
"refunded_cents": {
"type": "integer",
"description": "Soma das devoluções concluídas. O restante devolvível é amount_cents menos este valor."
}
}
}{
"type": "string",
"enum": [
"pending",
"paid",
"expired",
"canceled"
],
"description": "Situação gravada. Uma cobrança vencida continua \"pending\" até o provedor avisar: quem decide se um pagamento atrasado foi aceito é ele, não o relógio do servidor."
}/api/v1/public/checkouts/{token}Dados públicos do checkoutSem sessão: é a tela que o comprador abre. Entrega o código apenas enquanto a cobrança está pendente e dentro do prazo.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getPublicCheckout",
"tags": [
"checkout"
],
"summary": "Dados públicos do checkout",
"description": "Sem sessão: é a tela que o comprador abre. Entrega o código apenas enquanto a cobrança está pendente e dentro do prazo.",
"security": [],
"responses": {
"200": {
"description": "Dados suficientes para pagar.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PublicCheckout"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"status",
"amount_cents",
"product",
"seller_name",
"expires_at",
"payload",
"payable",
"simulated"
],
"properties": {
"status": {
"$ref": "#/components/schemas/ChargeStatus"
},
"amount_cents": {
"type": "integer"
},
"product": {
"type": "string"
},
"seller_name": {
"type": "string"
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"payload": {
"type": "string",
"nullable": true,
"description": "Null quando a cobrança já não pode ser paga."
},
"payable": {
"type": "boolean",
"enum": [
false
]
},
"simulated": {
"type": "boolean"
}
},
"description": "Só campos necessários para pagar. Não traz nome do comprador, tarifa, identificador do vendedor nem do provedor."
}{
"type": "string",
"enum": [
"pending",
"paid",
"expired",
"canceled"
],
"description": "Situação gravada. Uma cobrança vencida continua \"pending\" até o provedor avisar: quem decide se um pagamento atrasado foi aceito é ele, não o relógio do servidor."
}/api/v1/providers/{provider}/eventsReceber aviso do provedorConfere a assinatura antes de olhar o conteúdo e grava o aviso num livro somente-adição. A chave (provedor, event_id) é o que impede aplicar duas vezes quando o mesmo aviso é reenviado. Cobrança só sai de "pending", saque só sai de "processing" e devolução só sai de "requested": aviso fora de ordem não reabre nem re-liquida. `payout.unknown` NÃO devolve o dinheiro reservado — liberar seria arriscar pagar duas vezes; o valor fica reservado e a conciliação passa a apontar.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "receiveProviderEvent",
"tags": [
"providers"
],
"summary": "Receber aviso do provedor",
"description": "Confere a assinatura antes de olhar o conteúdo e grava o aviso num livro somente-adição. A chave (provedor, event_id) é o que impede aplicar duas vezes quando o mesmo aviso é reenviado. Cobrança só sai de \"pending\", saque só sai de \"processing\" e devolução só sai de \"requested\": aviso fora de ordem não reabre nem re-liquida. `payout.unknown` NÃO devolve o dinheiro reservado — liberar seria arriscar pagar duas vezes; o valor fica reservado e a conciliação passa a apontar.",
"security": [],
"x-authentication": "provider-signature",
"parameters": [
{
"$ref": "#/components/parameters/ProviderSignature"
},
{
"$ref": "#/components/parameters/ContentType"
}
],
"requestBody": {
"required": true,
"description": "Corpo assinado pelo provedor. É lido como texto e verificado byte a byte antes de qualquer interpretação.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"event_id",
"kind",
"provider_reference",
"occurred_at"
],
"properties": {
"event_id": {
"type": "string",
"maxLength": 200
},
"kind": {
"type": "string",
"enum": [
"charge.paid",
"charge.expired",
"charge.canceled",
"payout.completed",
"payout.failed",
"payout.unknown",
"refund.completed",
"refund.failed"
]
},
"amount_cents": {
"type": "integer",
"nullable": true
},
"occurred_at": {
"type": "string",
"format": "date-time"
},
"provider_reference": {
"type": "string",
"description": "Identificador do recurso no provedor: cobrança, repasse ou devolução."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Aviso recebido. O campo outcome diz o que foi feito; 200 significa registrado, não necessariamente aplicado.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProviderEventReceipt"
}
}
}
},
"401": {
"description": "Assinatura ausente, inválida ou corpo alterado depois de assinado (EVENT_UNVERIFIED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"description": "Provedor diferente do adaptador configurado (NOT_FOUND).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"413": {
"$ref": "#/components/responses/TooLarge"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"received",
"outcome"
],
"properties": {
"received": {
"type": "boolean",
"enum": [
true
]
},
"outcome": {
"type": "string",
"enum": [
"applied",
"duplicate",
"ignored",
"unknown_charge"
],
"description": "applied: mudou a cobrança. duplicate: o mesmo event_id já estava no livro. ignored: a cobrança não estava mais pendente. unknown_charge: nenhuma cobrança corresponde."
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/fees/currentVersão de tarifa vigenteVersões de tarifa são imutáveis e nunca apagadas; mudar tarifa é publicar a próxima. Não há endpoint para publicar: isso é da área administrativa, na etapa 6.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getCurrentFees",
"tags": [
"money"
],
"summary": "Versão de tarifa vigente",
"description": "Versões de tarifa são imutáveis e nunca apagadas; mudar tarifa é publicar a próxima. Não há endpoint para publicar: isso é da área administrativa, na etapa 6.",
"responses": {
"200": {
"description": "Tarifas em vigor.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeeVersion"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/EmailNotVerified"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"description": "Política comercial em vigor. Não inclui o custo do provedor.",
"required": [
"version",
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents",
"currency"
],
"properties": {
"version": {
"type": "integer"
},
"payment_fee_cents": {
"type": "integer",
"description": "Parte fixa da tarifa por venda, em centavos."
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Parte percentual por venda, em pontos-base (99 = 0,99%). Tarifa = fixa + round_half_up(valor × bps / 10000), em centavos."
},
"withdrawal_fee_cents": {
"type": "integer"
},
"withdrawal_min_cents": {
"type": "integer",
"description": "Menor saque aceito."
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"nullable": true,
"description": "Soma de saques numa janela de 24 horas. Nulo é sem limite. Saques recusados ou que falharam não contam."
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"nullable": true,
"description": "Limite em 24 horas enquanto a conta tiver menos de new_account_days dias. Nulo: vale o limite geral."
},
"new_account_days": {
"type": "integer"
},
"withdrawal_review_above_cents": {
"type": "integer",
"nullable": true,
"description": "Saque até este valor segue direto ao provedor; acima, vai para a fila de revisão. Nulo: todo saque é revisado."
},
"currency": {
"type": "string",
"enum": [
"BRL"
]
}
}
}/api/v1/sellers/{seller_id}/balanceSaldo do vendedorSomado a partir do livro de lançamentos a cada consulta. Não existe coluna de saldo que possa divergir do livro.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getBalance",
"tags": [
"money"
],
"summary": "Saldo do vendedor",
"description": "Somado a partir do livro de lançamentos a cada consulta. Não existe coluna de saldo que possa divergir do livro.",
"responses": {
"200": {
"description": "Saldo derivado dos lançamentos.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Balance"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"available_cents",
"reserved_cents",
"currency",
"as_of"
],
"properties": {
"available_cents": {
"type": "integer",
"description": "Soma dos lançamentos em seller_available. Não é coluna: é sempre calculado."
},
"reserved_cents": {
"type": "integer",
"description": "Soma dos lançamentos em seller_reserved: valor comprometido em saques e devoluções ainda não finalizados. Saque com resultado desconhecido permanece aqui."
},
"currency": {
"type": "string",
"enum": [
"BRL"
]
},
"as_of": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/ledgerExtrato do vendedorLançamentos das contas do vendedor, 50 por página, do mais recente para o mais antigo. Lançamentos das contas da plataforma não aparecem aqui.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listLedgerEntries",
"tags": [
"money"
],
"summary": "Extrato do vendedor",
"description": "Lançamentos das contas do vendedor, 50 por página, do mais recente para o mais antigo. Lançamentos das contas da plataforma não aparecem aqui.",
"parameters": [
{
"$ref": "#/components/parameters/Offset"
}
],
"responses": {
"200": {
"description": "Página de lançamentos.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/LedgerEntry"
}
},
"next_offset": {
"type": "integer",
"nullable": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"account",
"amount_cents",
"currency",
"kind",
"source_kind",
"source_id",
"occurred_at",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"account": {
"$ref": "#/components/schemas/LedgerAccount"
},
"amount_cents": {
"type": "integer",
"description": "Positivo credita, negativo debita. Nunca zero."
},
"currency": {
"type": "string",
"enum": [
"BRL"
]
},
"kind": {
"type": "string",
"enum": [
"charge_settled",
"withdrawal_requested",
"withdrawal_completed",
"withdrawal_released",
"refund_requested",
"refund_completed",
"refund_released"
]
},
"source_kind": {
"type": "string",
"enum": [
"charge",
"withdrawal",
"refund"
]
},
"source_id": {
"type": "string",
"format": "uuid"
},
"occurred_at": {
"type": "string",
"format": "date-time",
"description": "Quando o fato aconteceu, segundo o aviso do provedor."
},
"created_at": {
"type": "string",
"format": "date-time",
"description": "Quando o lançamento entrou no livro."
}
}
}{
"type": "string",
"enum": [
"seller_available",
"seller_reserved"
],
"description": "Contas do vendedor. As contas da plataforma (platform_fees, provider_clearing) existem no livro mas nunca aparecem para o vendedor."
}/api/v1/sellers/{seller_id}/withdrawalsListar saques do vendedorAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listWithdrawals",
"tags": [
"withdrawals"
],
"summary": "Listar saques do vendedor",
"responses": {
"200": {
"description": "Últimos 50 saques.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Withdrawal"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"fee_version",
"total_debited_cents",
"pix_key",
"status",
"decision_reason",
"provider",
"receipt_number",
"requested_at",
"decided_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa de saque copiada da versão vigente no pedido."
},
"fee_version": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer",
"description": "Valor mais tarifa. É o que sai do disponível na hora do pedido."
},
"pix_key": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/WithdrawalStatus"
},
"decision_reason": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true,
"description": "Só existe quando o saque é concluído."
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"requested",
"rejected",
"processing",
"completed",
"failed",
"unknown"
],
"description": "requested: aguardando revisão, valor reservado. rejected: recusado, valor devolvido. processing: entregue ao provedor, valor ainda reservado. completed: pago, com comprovante. failed: provedor recusou, valor devolvido. unknown: provedor aceitou e o resultado se perdeu — o valor SEGUE reservado, de propósito."
}/api/v1/sellers/{seller_id}/withdrawalsPedir saqueReserva valor e tarifa no mesmo instante em que grava o pedido: a conferência de saldo e o lançamento acontecem sob trava do vendedor, para que dois pedidos simultâneos não gastem o mesmo dinheiro. O saque entra na fila de revisão. Até withdrawal_review_above_cents o saque segue direto ao provedor e volta como processing; acima disso, ou sem valor de revisão definido, volta como requested e aguarda a fila.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "requestWithdrawal",
"tags": [
"withdrawals"
],
"summary": "Pedir saque",
"description": "Reserva valor e tarifa no mesmo instante em que grava o pedido: a conferência de saldo e o lançamento acontecem sob trava do vendedor, para que dois pedidos simultâneos não gastem o mesmo dinheiro. O saque entra na fila de revisão. Até withdrawal_review_above_cents o saque segue direto ao provedor e volta como processing; acima disso, ou sem valor de revisão definido, volta como requested e aguarda a fila.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WithdrawalInput"
}
}
}
},
"responses": {
"201": {
"description": "Saque pedido, valor reservado.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Withdrawal"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR), abaixo do saque mínimo (WITHDRAWAL_BELOW_MINIMUM), saldo insuficiente para valor e tarifa (INSUFFICIENT_FUNDS) ou limite de 24 horas ultrapassado (DAILY_LIMIT_EXCEEDED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"amount_cents",
"pix_key"
],
"properties": {
"amount_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000
},
"pix_key": {
"type": "string",
"minLength": 5,
"maxLength": 100,
"description": "Chave de destino. Nesta etapa nenhum valor é transferido."
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"fee_version",
"total_debited_cents",
"pix_key",
"status",
"decision_reason",
"provider",
"receipt_number",
"requested_at",
"decided_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa de saque copiada da versão vigente no pedido."
},
"fee_version": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer",
"description": "Valor mais tarifa. É o que sai do disponível na hora do pedido."
},
"pix_key": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/WithdrawalStatus"
},
"decision_reason": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true,
"description": "Só existe quando o saque é concluído."
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"requested",
"rejected",
"processing",
"completed",
"failed",
"unknown"
],
"description": "requested: aguardando revisão, valor reservado. rejected: recusado, valor devolvido. processing: entregue ao provedor, valor ainda reservado. completed: pago, com comprovante. failed: provedor recusou, valor devolvido. unknown: provedor aceitou e o resultado se perdeu — o valor SEGUE reservado, de propósito."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/withdrawals/{withdrawal_id}Detalhe do saqueAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getWithdrawal",
"tags": [
"withdrawals"
],
"summary": "Detalhe do saque",
"responses": {
"200": {
"description": "Saque.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Withdrawal"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"fee_version",
"total_debited_cents",
"pix_key",
"status",
"decision_reason",
"provider",
"receipt_number",
"requested_at",
"decided_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa de saque copiada da versão vigente no pedido."
},
"fee_version": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer",
"description": "Valor mais tarifa. É o que sai do disponível na hora do pedido."
},
"pix_key": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/WithdrawalStatus"
},
"decision_reason": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true,
"description": "Só existe quando o saque é concluído."
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"requested",
"rejected",
"processing",
"completed",
"failed",
"unknown"
],
"description": "requested: aguardando revisão, valor reservado. rejected: recusado, valor devolvido. processing: entregue ao provedor, valor ainda reservado. completed: pago, com comprovante. failed: provedor recusou, valor devolvido. unknown: provedor aceitou e o resultado se perdeu — o valor SEGUE reservado, de propósito."
}/api/v1/sellers/{seller_id}/withdrawals/{withdrawal_id}/receiptComprovante do saqueSó existe para saque concluído. Emitir comprovante de operação não concluída é o tipo de documento que confunde quem recebe.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getWithdrawalReceipt",
"tags": [
"withdrawals"
],
"summary": "Comprovante do saque",
"description": "Só existe para saque concluído. Emitir comprovante de operação não concluída é o tipo de documento que confunde quem recebe.",
"responses": {
"200": {
"description": "Comprovante.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WithdrawalReceipt"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Saque ainda não concluído (RECEIPT_UNAVAILABLE).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"receipt_number",
"withdrawal_id",
"seller_name",
"seller_legal_name",
"amount_cents",
"fee_cents",
"total_debited_cents",
"pix_key",
"requested_at",
"finished_at",
"currency",
"simulated",
"notice"
],
"properties": {
"receipt_number": {
"type": "string"
},
"withdrawal_id": {
"type": "string",
"format": "uuid"
},
"seller_name": {
"type": "string"
},
"seller_legal_name": {
"type": "string"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer"
},
"pix_key": {
"type": "string"
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"finished_at": {
"type": "string",
"format": "date-time"
},
"currency": {
"type": "string",
"enum": [
"BRL"
]
},
"simulated": {
"type": "boolean"
},
"notice": {
"type": "string",
"description": "Aviso que precisa aparecer no documento enquanto o ambiente for simulado."
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/refundsListar devoluções do vendedorAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listRefunds",
"tags": [
"refunds"
],
"summary": "Listar devoluções do vendedor",
"responses": {
"200": {
"description": "Últimas 50 devoluções.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Refund"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"charge_id",
"amount_cents",
"reason",
"status",
"provider",
"receipt_number",
"requested_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"charge_id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"reason": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"requested",
"completed",
"failed"
],
"description": "requested reserva o valor; completed abate da cobrança; failed devolve ao disponível."
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}/api/v1/sellers/{seller_id}/refundsPedir devoluçãoReserva o valor e entrega o pedido ao provedor. Uma devolução em aberto por cobrança, garantido por índice do banco: dois pedidos simultâneos não passam os dois. A tarifa da cobrança não é devolvida.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "requestRefund",
"tags": [
"refunds"
],
"summary": "Pedir devolução",
"description": "Reserva o valor e entrega o pedido ao provedor. Uma devolução em aberto por cobrança, garantido por índice do banco: dois pedidos simultâneos não passam os dois. A tarifa da cobrança não é devolvida.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RefundInput"
}
}
}
},
"responses": {
"201": {
"description": "Devolução pedida, valor reservado.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Refund"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"description": "Cobrança inexistente ou de outro vendedor (NOT_FOUND). Responde igual nos dois casos.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"409": {
"description": "Cobrança não paga (CHARGE_NOT_REFUNDABLE) ou já com devolução em análise (REFUND_IN_PROGRESS).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR), valor acima do restante devolvível (AMOUNT_ABOVE_REMAINING) ou saldo insuficiente (INSUFFICIENT_FUNDS).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"charge_id",
"amount_cents",
"reason"
],
"properties": {
"charge_id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000,
"description": "Não pode passar do que resta devolver da cobrança. A tarifa da cobrança não volta."
},
"reason": {
"type": "string",
"minLength": 1,
"maxLength": 500
}
}
}{
"type": "object",
"required": [
"id",
"charge_id",
"amount_cents",
"reason",
"status",
"provider",
"receipt_number",
"requested_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"charge_id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"reason": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"requested",
"completed",
"failed"
],
"description": "requested reserva o valor; completed abate da cobrança; failed devolve ao disponível."
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/withdrawalsFila de revisão de saquesExige papel de operador da plataforma, concedido fora da API por linha de comando. Para quem não é operador a rota responde 404, sem revelar que existe.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listWithdrawalQueue",
"tags": [
"admin"
],
"summary": "Fila de revisão de saques",
"description": "Exige papel de operador da plataforma, concedido fora da API por linha de comando. Para quem não é operador a rota responde 404, sem revelar que existe.",
"parameters": [
{
"$ref": "#/components/parameters/WithdrawalStatusFilter"
}
],
"responses": {
"200": {
"description": "Saques mais antigos primeiro.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AdminWithdrawal"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"allOf": [
{
"$ref": "#/components/schemas/Withdrawal"
},
{
"type": "object",
"required": [
"seller_id",
"seller_name"
],
"properties": {
"seller_id": {
"type": "string",
"format": "uuid"
},
"seller_name": {
"type": "string"
}
}
}
]
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"fee_version",
"total_debited_cents",
"pix_key",
"status",
"decision_reason",
"provider",
"receipt_number",
"requested_at",
"decided_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa de saque copiada da versão vigente no pedido."
},
"fee_version": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer",
"description": "Valor mais tarifa. É o que sai do disponível na hora do pedido."
},
"pix_key": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/WithdrawalStatus"
},
"decision_reason": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true,
"description": "Só existe quando o saque é concluído."
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"requested",
"rejected",
"processing",
"completed",
"failed",
"unknown"
],
"description": "requested: aguardando revisão, valor reservado. rejected: recusado, valor devolvido. processing: entregue ao provedor, valor ainda reservado. completed: pago, com comprovante. failed: provedor recusou, valor devolvido. unknown: provedor aceitou e o resultado se perdeu — o valor SEGUE reservado, de propósito."
}/api/v1/admin/withdrawals/{withdrawal_id}/decisionDecidir um saqueRecusar devolve valor e tarifa ao disponível e exige motivo. Aprovar apenas entrega o pedido ao provedor: o dinheiro segue reservado até o aviso de resultado chegar. Decidir duas vezes responde 409.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "decideWithdrawal",
"tags": [
"admin"
],
"summary": "Decidir um saque",
"description": "Recusar devolve valor e tarifa ao disponível e exige motivo. Aprovar apenas entrega o pedido ao provedor: o dinheiro segue reservado até o aviso de resultado chegar. Decidir duas vezes responde 409.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DecisionInput"
}
}
}
},
"responses": {
"200": {
"description": "Saque depois da decisão.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Withdrawal"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "O saque já saiu da fila de revisão (ALREADY_DECIDED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR) ou recusa sem motivo (REASON_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
},
"502": {
"description": "O provedor não aceitou o repasse (PROVIDER_REFUSED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"decision"
],
"properties": {
"decision": {
"type": "string",
"enum": [
"approve",
"reject"
]
},
"reason": {
"type": "string",
"maxLength": 500,
"description": "Obrigatório na recusa."
}
}
}{
"type": "object",
"required": [
"id",
"amount_cents",
"fee_cents",
"fee_version",
"total_debited_cents",
"pix_key",
"status",
"decision_reason",
"provider",
"receipt_number",
"requested_at",
"decided_at",
"finished_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa de saque copiada da versão vigente no pedido."
},
"fee_version": {
"type": "integer"
},
"total_debited_cents": {
"type": "integer",
"description": "Valor mais tarifa. É o que sai do disponível na hora do pedido."
},
"pix_key": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/WithdrawalStatus"
},
"decision_reason": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
},
"receipt_number": {
"type": "string",
"nullable": true,
"description": "Só existe quando o saque é concluído."
},
"requested_at": {
"type": "string",
"format": "date-time"
},
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"finished_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"requested",
"rejected",
"processing",
"completed",
"failed",
"unknown"
],
"description": "requested: aguardando revisão, valor reservado. rejected: recusado, valor devolvido. processing: entregue ao provedor, valor ainda reservado. completed: pago, com comprovante. failed: provedor recusou, valor devolvido. unknown: provedor aceitou e o resultado se perdeu — o valor SEGUE reservado, de propósito."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/api-keysListar chaves de acessoAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listApiKeys",
"tags": [
"keys"
],
"summary": "Listar chaves de acesso",
"responses": {
"200": {
"description": "Chaves do vendedor, sem segredo.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ApiKey"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"name",
"prefix",
"created_at",
"last_used_at",
"revoked_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"prefix": {
"type": "string",
"description": "Começo do segredo, para reconhecer a chave sem revelá-la. O segredo completo nunca é devolvido de novo."
},
"created_at": {
"type": "string",
"format": "date-time"
},
"last_used_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"revoked_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}/api/v1/sellers/{seller_id}/api-keysCriar chave de acessoO segredo é devolvido apenas nesta resposta. O servidor guarda só o digest. A chave autentica em Authorization: Bearer e alcanca apenas cobrancas e saldo do proprio vendedor.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "createApiKey",
"tags": [
"keys"
],
"summary": "Criar chave de acesso",
"description": "O segredo é devolvido apenas nesta resposta. O servidor guarda só o digest. A chave autentica em Authorization: Bearer e alcanca apenas cobrancas e saldo do proprio vendedor.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"additionalProperties": false,
"required": [
"name"
],
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 60
},
"scopes": {
"type": "array",
"items": {
"type": "string",
"enum": [
"charges:read",
"charges:write",
"balance:read"
]
},
"minItems": 1,
"maxItems": 3,
"description": "Sem escopo declarado a chave nasce so de leitura. Saque, devolucao e gestao de credenciais nao tem escopo: exigem entrada com senha e segundo fator."
}
}
}
}
}
},
"responses": {
"201": {
"description": "Chave criada.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ApiKeyCreated"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"name",
"prefix",
"secret",
"notice"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"prefix": {
"type": "string"
},
"secret": {
"type": "string",
"description": "Aparece uma vez só. O servidor guarda apenas o digest, então não há como mostrá-lo de novo. Nesta etapa ainda não autentica chamadas."
},
"notice": {
"type": "string"
}
}
}/api/v1/sellers/{seller_id}/api-keys/{key_id}Revogar chaveRevogar é definitivo. Revogar de novo responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "revokeApiKey",
"tags": [
"keys"
],
"summary": "Revogar chave",
"description": "Revogar é definitivo. Revogar de novo responde 404.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"responses": {
"204": {
"description": "Chave revogada."
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}/api/v1/sellers/{seller_id}/webhookDestino dos avisosAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getWebhook",
"tags": [
"webhooks"
],
"summary": "Destino dos avisos",
"responses": {
"200": {
"description": "Configuração atual e eventos disponíveis.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"endpoint",
"available_events"
],
"properties": {
"endpoint": {
"oneOf": [
{
"$ref": "#/components/schemas/WebhookEndpoint"
},
{
"type": "null"
}
]
},
"available_events": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"url",
"events",
"enabled",
"updated_at"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"description": "O segredo de assinatura nunca é devolvido."
}/api/v1/sellers/{seller_id}/webhookDefinir destino dos avisosAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "saveWebhook",
"tags": [
"webhooks"
],
"summary": "Definir destino dos avisos",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookInput"
}
}
}
},
"responses": {
"200": {
"description": "Destino salvo.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/WebhookEndpoint"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR) ou destino apontando para rede interna (DESTINATION_REFUSED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"url",
"events"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"maxLength": 500,
"description": "Endereços que resolvem para rede interna são recusados, na configuração e de novo na hora de entregar."
},
"events": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean",
"default": true
}
}
}{
"type": "object",
"required": [
"url",
"events",
"enabled",
"updated_at"
],
"properties": {
"url": {
"type": "string",
"format": "uri"
},
"events": {
"type": "array",
"items": {
"type": "string"
}
},
"enabled": {
"type": "boolean"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
},
"description": "O segredo de assinatura nunca é devolvido."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/sellers/{seller_id}/webhook/deliveriesHistórico de entregasÚltimas 50 tentativas, com situação, número de tentativas e o erro da última.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listWebhookDeliveries",
"tags": [
"webhooks"
],
"summary": "Histórico de entregas",
"description": "Últimas 50 tentativas, com situação, número de tentativas e o erro da última.",
"responses": {
"200": {
"description": "Entregas.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WebhookDelivery"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"event",
"status",
"attempts",
"last_status_code",
"last_error",
"created_at",
"delivered_at",
"next_attempt_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"event": {
"type": "string"
},
"status": {
"type": "string",
"enum": [
"pending",
"delivered",
"failed",
"dropped"
],
"description": "pending ainda será tentado; failed esgotou as seis tentativas; dropped perdeu o destino."
},
"attempts": {
"type": "integer"
},
"last_status_code": {
"type": "integer",
"nullable": true
},
"last_error": {
"type": "string",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"delivered_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"next_attempt_at": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/notificationsNovidades da contaAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listNotifications",
"tags": [
"notifications"
],
"summary": "Novidades da conta",
"parameters": [
{
"$ref": "#/components/parameters/UnreadOnly"
}
],
"responses": {
"200": {
"description": "Até 50 novidades, da mais recente para a mais antiga.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"unread"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Notification"
}
},
"unread": {
"type": "integer"
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"action",
"target_id",
"metadata",
"created_at",
"read"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"action": {
"type": "string"
},
"target_id": {
"type": "string",
"nullable": true
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"read": {
"type": "boolean"
}
},
"description": "Derivada da auditoria, que já é somente-adição. Só as marcas de leitura são guardadas à parte."
}/api/v1/sellers/{seller_id}/notifications/readMarcar como lidasAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "markNotificationsRead",
"tags": [
"notifications"
],
"summary": "Marcar como lidas",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReadInput"
}
}
}
},
"responses": {
"204": {
"description": "Marcadas."
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"properties": {
"ids": {
"type": "array",
"maxItems": 200,
"items": {
"type": "string",
"format": "uuid"
}
},
"all": {
"type": "boolean"
}
},
"description": "Informe ids ou all."
}/api/v1/sellers/{seller_id}/ticketsListar solicitaçõesAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "listTickets",
"tags": [
"support"
],
"summary": "Listar solicitações",
"responses": {
"200": {
"description": "Solicitações do vendedor.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Ticket"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"subject",
"category",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"status": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/ticketsAbrir solicitaçãoAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "openTicket",
"tags": [
"support"
],
"summary": "Abrir solicitação",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TicketInput"
}
}
}
},
"responses": {
"201": {
"description": "Solicitação aberta com a primeira mensagem.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Ticket"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"subject",
"category",
"message"
],
"properties": {
"subject": {
"type": "string",
"minLength": 1,
"maxLength": 160
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"message": {
"type": "string",
"minLength": 1,
"maxLength": 2000
}
}
}{
"type": "object",
"required": [
"id",
"subject",
"category",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"status": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/tickets/{ticket_id}Conversa da solicitaçãoAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getTicket",
"tags": [
"support"
],
"summary": "Conversa da solicitação",
"responses": {
"200": {
"description": "Solicitação com as mensagens em ordem.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TicketDetail"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"allOf": [
{
"$ref": "#/components/schemas/Ticket"
},
{
"type": "object",
"required": [
"messages"
],
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"author_side",
"body",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"author_side": {
"type": "string",
"enum": [
"seller",
"platform"
]
},
"body": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
]
}{
"type": "object",
"required": [
"id",
"subject",
"category",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"status": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}/api/v1/sellers/{seller_id}/tickets/{ticket_id}/messagesResponder na conversaMensagens são somente-adição: corrigir é escrever de novo, não reescrever.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "replyTicket",
"tags": [
"support"
],
"summary": "Responder na conversa",
"description": "Mensagens são somente-adição: corrigir é escrever de novo, não reescrever.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MessageInput"
}
}
}
},
"responses": {
"201": {
"description": "Mensagem adicionada.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ok"
],
"properties": {
"ok": {
"type": "boolean"
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "A solicitação já foi encerrada (TICKET_RESOLVED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"body"
],
"properties": {
"body": {
"type": "string",
"minLength": 1,
"maxLength": 2000
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/metricsEstado operacional das filas e do dinheiro em andamentoExige papel de operador da plataforma. Para quem não é operador a rota responde 404, sem revelar que existe. Os números contam quanto dinheiro está parado e onde, por isso não são públicos.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "operationalMetrics",
"tags": [
"admin"
],
"summary": "Estado operacional das filas e do dinheiro em andamento",
"description": "Exige papel de operador da plataforma. Para quem não é operador a rota responde 404, sem revelar que existe. Os números contam quanto dinheiro está parado e onde, por isso não são públicos.",
"responses": {
"200": {
"description": "Contagens no instante da consulta e o que passou do limite.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"collected_at",
"counters",
"queues",
"money",
"alerts"
],
"properties": {
"collected_at": {
"type": "string",
"format": "date-time"
},
"counters": {
"type": "object",
"additionalProperties": {
"type": "integer"
},
"description": "Acumulados desde que o processo subiu; zeram no reinício."
},
"queues": {
"type": "object",
"required": [
"webhooks_pending",
"webhooks_failed",
"webhooks_dropped",
"webhooks_overdue",
"email_pending"
],
"properties": {
"webhooks_pending": {
"type": "integer",
"minimum": 0,
"description": "Avisos aguardando entrega."
},
"webhooks_failed": {
"type": "integer",
"minimum": 0,
"description": "Avisos que falharam e ainda serão tentados."
},
"webhooks_dropped": {
"type": "integer",
"minimum": 0,
"description": "Avisos que esgotaram as tentativas. O lojista não vai receber."
},
"webhooks_overdue": {
"type": "integer",
"minimum": 0,
"description": "Entregas marcadas para o passado e paradas."
},
"email_pending": {
"type": "integer",
"minimum": 0,
"description": "Mensagens ainda não entregues."
}
}
},
"money": {
"type": "object",
"required": [
"charges_pending",
"withdrawals_awaiting_review",
"withdrawals_at_provider",
"withdrawals_unknown",
"refunds_open"
],
"properties": {
"charges_pending": {
"type": "integer",
"minimum": 0,
"description": "Cobranças aguardando pagamento."
},
"withdrawals_awaiting_review": {
"type": "integer",
"minimum": 0,
"description": "Saques esperando decisão."
},
"withdrawals_at_provider": {
"type": "integer",
"minimum": 0,
"description": "Saques entregues ao provedor."
},
"withdrawals_unknown": {
"type": "integer",
"minimum": 0,
"description": "Saques sem resultado conhecido. Valor segue reservado."
},
"refunds_open": {
"type": "integer",
"minimum": 0,
"description": "Devoluções em andamento."
}
}
},
"alerts": {
"type": "array",
"description": "Vazio quando nenhum limite foi ultrapassado.",
"items": {
"type": "object",
"required": [
"metric",
"value",
"threshold"
],
"properties": {
"metric": {
"type": "string"
},
"value": {
"type": "integer"
},
"threshold": {
"type": "integer"
}
}
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"404": {
"$ref": "#/components/responses/NotFound"
}
}
}/api/v1/auth/second-factorSituacao do segundo fator da contaAutenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "secondFactorState",
"tags": [
"auth"
],
"summary": "Situacao do segundo fator da conta",
"responses": {
"200": {
"description": "Estado atual.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"enabled",
"pending",
"required",
"recovery_codes_left",
"verified_in_session"
],
"properties": {
"enabled": {
"type": "boolean"
},
"pending": {
"type": "boolean",
"description": "Comecou o cadastro e nao confirmou. Nao vale nada ate confirmar."
},
"required": {
"type": "boolean",
"description": "Verdadeiro para operador da plataforma."
},
"recovery_codes_left": {
"type": "integer",
"minimum": 0
},
"verified_in_session": {
"type": "boolean",
"description": "Esta sessao provou o segundo fator."
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
}
}
}/api/v1/auth/second-factorSegunda etapa da entradaRecebe o desafio devolvido pelo login e o codigo. A sessao so nasce aqui. O desafio e de uso unico, vale cinco minutos e fecha depois de cinco tentativas.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "completeSecondFactor",
"tags": [
"auth"
],
"summary": "Segunda etapa da entrada",
"description": "Recebe o desafio devolvido pelo login e o codigo. A sessao so nasce aqui. O desafio e de uso unico, vale cinco minutos e fecha depois de cinco tentativas.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"challenge",
"code"
],
"properties": {
"challenge": {
"type": "string",
"pattern": "^[a-f0-9]{64}$"
},
"code": {
"type": "string",
"minLength": 6,
"maxLength": 11,
"description": "Seis digitos do aplicativo, ou um codigo de recuperacao."
}
}
}
}
}
},
"responses": {
"200": {
"description": "Sessao criada; o cookie vem em Set-Cookie.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"user_id",
"name",
"email",
"email_verified",
"csrf_token"
],
"properties": {
"user_id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"email": {
"type": "string",
"format": "email"
},
"email_verified": {
"type": "boolean"
},
"csrf_token": {
"type": "string"
},
"used_recovery_code": {
"type": "boolean"
},
"recovery_codes_left": {
"type": "integer",
"minimum": 0
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"$ref": "#/components/parameters/Origin"
}
],
"security": []
}/api/v1/auth/second-factorRemover o segundo fatorExige senha e codigo, porque desligar a protecao e o que alguem faria com uma sessao sua aberta. Operador da plataforma nao pode remover.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "disableSecondFactor",
"tags": [
"auth"
],
"summary": "Remover o segundo fator",
"description": "Exige senha e codigo, porque desligar a protecao e o que alguem faria com uma sessao sua aberta. Operador da plataforma nao pode remover.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"password",
"code"
],
"properties": {
"password": {
"type": "string",
"minLength": 1,
"maxLength": 128
},
"code": {
"type": "string",
"minLength": 6,
"maxLength": 11
}
}
}
}
}
},
"responses": {
"204": {
"description": "Removido."
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/ForbiddenRole"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
]
}/api/v1/auth/second-factor/setupGerar o segredo do segundo fatorO segredo aparece uma vez. Enquanto nao for confirmado, o segundo fator nao vale e a senha continua entrando sozinha.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "startSecondFactor",
"tags": [
"auth"
],
"summary": "Gerar o segredo do segundo fator",
"description": "O segredo aparece uma vez. Enquanto nao for confirmado, o segundo fator nao vale e a senha continua entrando sozinha.",
"responses": {
"200": {
"description": "Segredo gerado.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"secret",
"otpauth_url",
"notice"
],
"properties": {
"secret": {
"type": "string"
},
"otpauth_url": {
"type": "string"
},
"notice": {
"type": "string"
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"409": {
"$ref": "#/components/responses/VersionConflict"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
]
}/api/v1/auth/second-factor/confirmConfirmar o segundo fator e receber os codigos de recuperacaoPede um codigo gerado pelo aplicativo: sem essa prova alguem ativaria a protecao com um segredo que nunca funcionou e se trancaria fora. Os codigos de recuperacao aparecem so aqui.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "confirmSecondFactor",
"tags": [
"auth"
],
"summary": "Confirmar o segundo fator e receber os codigos de recuperacao",
"description": "Pede um codigo gerado pelo aplicativo: sem essa prova alguem ativaria a protecao com um segredo que nunca funcionou e se trancaria fora. Os codigos de recuperacao aparecem so aqui.",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"code"
],
"properties": {
"code": {
"type": "string",
"minLength": 6,
"maxLength": 6
}
}
}
}
}
},
"responses": {
"200": {
"description": "Ativado.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"recovery_codes",
"notice"
],
"properties": {
"recovery_codes": {
"type": "array",
"items": {
"type": "string"
}
},
"notice": {
"type": "string"
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"$ref": "#/components/responses/OriginInvalid"
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"$ref": "#/components/responses/VersionConflict"
},
"415": {
"$ref": "#/components/responses/UnsupportedMedia"
},
"422": {
"description": "Código do segundo fator inválido (SECOND_FACTOR_INVALID). Não é erro de forma do pedido, então não traz field_errors.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
]
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/overviewVisão da operaçãoContagens e receita no instante da consulta. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminOverview",
"tags": [
"admin"
],
"summary": "Visão da operação",
"description": "Contagens e receita no instante da consulta. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdminOverview"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"sellers",
"charges",
"revenue",
"queues",
"alerts",
"payments_enabled"
],
"properties": {
"sellers": {
"type": "object",
"required": [
"total",
"by_status"
],
"properties": {
"total": {
"type": "integer"
},
"by_status": {
"type": "object",
"additionalProperties": {
"type": "integer"
}
}
}
},
"charges": {
"type": "object",
"required": [
"paid_count",
"paid_cents",
"pending_count"
],
"properties": {
"paid_count": {
"type": "integer"
},
"paid_cents": {
"type": "integer"
},
"pending_count": {
"type": "integer"
}
}
},
"revenue": {
"type": "object",
"description": "Somada da conta platform_fees do livro de lançamentos.",
"required": [
"payment_fees_cents",
"withdrawal_fees_cents",
"total_cents"
],
"properties": {
"payment_fees_cents": {
"type": "integer"
},
"withdrawal_fees_cents": {
"type": "integer"
},
"total_cents": {
"type": "integer"
}
}
},
"queues": {
"type": "object",
"required": [
"sellers_awaiting_review",
"withdrawals_awaiting_review",
"withdrawals_unknown",
"tickets_open"
],
"properties": {
"sellers_awaiting_review": {
"type": "integer"
},
"withdrawals_awaiting_review": {
"type": "integer"
},
"withdrawals_unknown": {
"type": "integer"
},
"tickets_open": {
"type": "integer"
}
}
},
"alerts": {
"type": "array",
"items": {
"type": "object",
"required": [
"metric",
"value",
"threshold"
],
"properties": {
"metric": {
"type": "string"
},
"value": {
"type": "integer"
},
"threshold": {
"type": "integer"
}
}
}
},
"payments_enabled": {
"type": "boolean"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/sellersVendedores da plataformaCadastros aguardando análise primeiro. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminListSellers",
"tags": [
"admin"
],
"summary": "Vendedores da plataforma",
"description": "Cadastros aguardando análise primeiro. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AdminSeller"
}
},
"next_offset": {
"type": "integer",
"nullable": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"name": "status",
"in": "query",
"required": false,
"schema": {
"$ref": "#/components/schemas/SellerStatus"
}
},
{
"name": "q",
"in": "query",
"required": false,
"description": "Busca parcial, sem diferenciar maiúsculas. Curingas são tratados como texto.",
"schema": {
"type": "string",
"maxLength": 120
}
},
{
"$ref": "#/components/parameters/Offset"
}
]
}{
"type": "object",
"description": "Documento do vendedor não é devolvido.",
"required": [
"id",
"legal_name",
"trade_name",
"status",
"version",
"created_at",
"updated_at",
"owner_name",
"owner_email"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"legal_name": {
"type": "string"
},
"trade_name": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/SellerStatus"
},
"version": {
"type": "integer"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"owner_name": {
"type": "string",
"nullable": true
},
"owner_email": {
"type": "string",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"draft",
"verification_pending",
"needs_changes",
"approved",
"rejected"
],
"description": "approved é a aprovação da plataforma, não do provedor; nenhuma rota depende dele para liberar pagamento."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/sellers/{seller_id}Cadastro de um vendedorResponsáveis, envios de verificação e saldo. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminGetSeller",
"tags": [
"admin"
],
"summary": "Cadastro de um vendedor",
"description": "Responsáveis, envios de verificação e saldo. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdminSellerDetail"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"id",
"legal_name",
"trade_name",
"status",
"version",
"created_at",
"updated_at",
"members",
"verification",
"balance"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"legal_name": {
"type": "string"
},
"trade_name": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/SellerStatus"
},
"version": {
"type": "integer"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"members": {
"type": "array",
"items": {
"type": "object",
"required": [
"name",
"email",
"role",
"email_verified"
],
"properties": {
"name": {
"type": "string"
},
"email": {
"type": "string"
},
"role": {
"type": "string",
"enum": [
"owner",
"finance",
"developer",
"viewer"
]
},
"email_verified": {
"type": "boolean"
}
}
}
},
"verification": {
"type": "array",
"items": {
"allOf": [
{
"$ref": "#/components/schemas/VerificationCase"
},
{
"type": "object",
"properties": {
"decided_at": {
"type": "string",
"format": "date-time",
"nullable": true
}
}
}
]
}
},
"balance": {
"type": "object",
"required": [
"available_cents",
"reserved_cents"
],
"properties": {
"available_cents": {
"type": "integer"
},
"reserved_cents": {
"type": "integer"
}
}
}
}
}{
"type": "string",
"enum": [
"draft",
"verification_pending",
"needs_changes",
"approved",
"rejected"
],
"description": "approved é a aprovação da plataforma, não do provedor; nenhuma rota depende dele para liberar pagamento."
}{
"type": "object",
"required": [
"id",
"version",
"status",
"business_url",
"segment",
"description",
"consent_version",
"submitted_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"version": {
"type": "integer"
},
"status": {
"type": "string",
"enum": [
"submitted",
"needs_changes",
"approved",
"rejected"
]
},
"business_url": {
"type": "string",
"format": "uri"
},
"segment": {
"$ref": "#/components/schemas/Segment"
},
"description": {
"type": "string"
},
"consent_version": {
"type": "string"
},
"submitted_at": {
"type": "string",
"format": "date-time"
},
"decision_reason": {
"type": "string",
"nullable": true
}
}
}{
"type": "string",
"enum": [
"game_items",
"digital_products",
"other"
]
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/sellers/{seller_id}/decisionDecidir cadastro de vendedorSó vale para cadastro em verification_pending. Aprovar é decisão da plataforma e não substitui o cadastro no provedor. Pedir ajuste permite reenvio; recusar encerra. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminDecideSeller",
"tags": [
"admin"
],
"summary": "Decidir cadastro de vendedor",
"description": "Só vale para cadastro em verification_pending. Aprovar é decisão da plataforma e não substitui o cadastro no provedor. Pedir ajuste permite reenvio; recusar encerra. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerDecisionInput"
}
}
}
},
"responses": {
"200": {
"description": "Cadastro depois da decisão.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SellerDecided"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Versão diferente da lida (VERSION_CONFLICT), cadastro fora de análise (ALREADY_DECIDED) ou sem envio (NO_SUBMISSION).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR) ou motivo ausente (REASON_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"decision",
"expected_version"
],
"properties": {
"decision": {
"type": "string",
"enum": [
"approve",
"needs_changes",
"reject"
]
},
"reason": {
"type": "string",
"maxLength": 500,
"description": "Obrigatório para needs_changes e reject. O vendedor lê este texto."
},
"expected_version": {
"type": "integer",
"minimum": 1,
"description": "Versão do cadastro que o operador leu."
}
}
}{
"type": "object",
"required": [
"id",
"legal_name",
"trade_name",
"status",
"version",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"legal_name": {
"type": "string"
},
"trade_name": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/SellerStatus"
},
"version": {
"type": "integer"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "string",
"enum": [
"draft",
"verification_pending",
"needs_changes",
"approved",
"rejected"
],
"description": "approved é a aprovação da plataforma, não do provedor; nenhuma rota depende dele para liberar pagamento."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/chargesCobranças de todos os vendedoresExige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminListCharges",
"tags": [
"admin"
],
"summary": "Cobranças de todos os vendedores",
"description": "Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AdminCharge"
}
},
"next_offset": {
"type": "integer",
"nullable": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"$ref": "#/components/parameters/ChargeStatusFilter"
},
{
"name": "q",
"in": "query",
"required": false,
"description": "Busca parcial, sem diferenciar maiúsculas. Curingas são tratados como texto.",
"schema": {
"type": "string",
"maxLength": 120
}
},
{
"$ref": "#/components/parameters/Offset"
}
]
}{
"type": "object",
"description": "Cobrança vista pela operação. O código do checkout não é devolvido.",
"required": [
"id",
"amount_cents",
"fee_cents",
"customer_name",
"product",
"status",
"expired_by_time",
"provider",
"provider_charge_id",
"simulated",
"expires_at",
"paid_at",
"created_at",
"updated_at",
"fee_version",
"refunded_cents",
"seller_id",
"seller_name"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"amount_cents": {
"type": "integer"
},
"fee_cents": {
"type": "integer",
"description": "Tarifa copiada da versão vigente na criação. Mudar a tarifa não altera cobranças já criadas."
},
"customer_name": {
"type": "string"
},
"product": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/ChargeStatus"
},
"expired_by_time": {
"type": "boolean",
"description": "Verdadeiro quando ainda está \"pending\" e já passou de expires_at. Serve para a interface, não muda o estado gravado."
},
"provider": {
"type": "string"
},
"provider_charge_id": {
"type": "string"
},
"simulated": {
"type": "boolean",
"description": "Verdadeiro enquanto o adaptador não move dinheiro real."
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"paid_at": {
"type": "string",
"format": "date-time",
"nullable": true
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"fee_version": {
"type": "integer",
"description": "Versão de tarifa que valia quando a cobrança foi criada. Publicar uma versão nova não altera cobranças existentes."
},
"refunded_cents": {
"type": "integer",
"description": "Soma das devoluções concluídas. O restante devolvível é amount_cents menos este valor."
},
"seller_id": {
"type": "string",
"format": "uuid"
},
"seller_name": {
"type": "string"
}
}
}{
"type": "string",
"enum": [
"pending",
"paid",
"expired",
"canceled"
],
"description": "Situação gravada. Uma cobrança vencida continua \"pending\" até o provedor avisar: quem decide se um pagamento atrasado foi aceito é ele, não o relógio do servidor."
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/feesVersões de tarifaExige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminListFees",
"tags": [
"admin"
],
"summary": "Versões de tarifa",
"description": "Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"current",
"versions"
],
"properties": {
"current": {
"type": "object",
"required": [
"version",
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents"
],
"properties": {
"version": {
"type": "integer"
},
"payment_fee_cents": {
"type": "integer",
"description": "Parte fixa da tarifa por venda, em centavos."
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Parte percentual por venda, em pontos-base (99 = 0,99%). Tarifa = fixa + round_half_up(valor × bps / 10000), em centavos."
},
"withdrawal_fee_cents": {
"type": "integer"
},
"withdrawal_min_cents": {
"type": "integer",
"description": "Menor saque aceito."
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"nullable": true,
"description": "Soma de saques numa janela de 24 horas. Nulo é sem limite. Saques recusados ou que falharam não contam."
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"nullable": true,
"description": "Limite em 24 horas enquanto a conta tiver menos de new_account_days dias. Nulo: vale o limite geral."
},
"new_account_days": {
"type": "integer"
},
"withdrawal_review_above_cents": {
"type": "integer",
"nullable": true,
"description": "Saque até este valor segue direto ao provedor; acima, vai para a fila de revisão. Nulo: todo saque é revisado."
}
}
},
"versions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/FeeVersionRecord"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"required": [
"version",
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents",
"provider_pix_cost_cents",
"provider_payout_cost_cents",
"effective_from",
"note",
"created_at"
],
"properties": {
"version": {
"type": "integer"
},
"payment_fee_cents": {
"type": "integer",
"description": "Parte fixa da tarifa por venda, em centavos."
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Parte percentual por venda, em pontos-base (99 = 0,99%). Tarifa = fixa + round_half_up(valor × bps / 10000), em centavos."
},
"withdrawal_fee_cents": {
"type": "integer"
},
"withdrawal_min_cents": {
"type": "integer",
"description": "Menor saque aceito."
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"nullable": true,
"description": "Soma de saques numa janela de 24 horas. Nulo é sem limite. Saques recusados ou que falharam não contam."
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"nullable": true,
"description": "Limite em 24 horas enquanto a conta tiver menos de new_account_days dias. Nulo: vale o limite geral."
},
"new_account_days": {
"type": "integer"
},
"withdrawal_review_above_cents": {
"type": "integer",
"nullable": true,
"description": "Saque até este valor segue direto ao provedor; acima, vai para a fila de revisão. Nulo: todo saque é revisado."
},
"provider_pix_cost_cents": {
"type": "integer",
"nullable": true,
"description": "Custo por Pix informado pelo operador ao publicar. Só a operação vê."
},
"provider_payout_cost_cents": {
"type": "integer",
"nullable": true,
"description": "Custo por repasse informado pelo operador ao publicar."
},
"effective_from": {
"type": "string",
"format": "date-time"
},
"note": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/feesPublicar nova versão de tarifaCria a próxima versão, em vigor imediatamente. Cobranças e saques existentes mantêm a tarifa copiada. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminPublishFees",
"tags": [
"admin"
],
"summary": "Publicar nova versão de tarifa",
"description": "Cria a próxima versão, em vigor imediatamente. Cobranças e saques existentes mantêm a tarifa copiada. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeePublishInput"
}
}
}
},
"responses": {
"201": {
"description": "Versão publicada.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/FeeVersionRecord"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Outra versão foi publicada depois da lida (VERSION_CONFLICT).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"description": "Campos fora do formato (VALIDATION_ERROR), limites contraditórios (LIMITS_INCONSISTENT) ou tarifa abaixo do custo informado (FEE_BELOW_COST).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"description": "Uma publicação é a política inteira. Quando o custo do provedor é informado, a publicação é recusada se a tarifa da menor venda aceita (R$ 1,00) ou a de saque não cobrir o custo.",
"required": [
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents",
"provider_pix_cost_cents",
"provider_payout_cost_cents",
"note",
"expected_version"
],
"properties": {
"payment_fee_cents": {
"type": "integer",
"minimum": 0,
"maximum": 10000
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000
},
"withdrawal_fee_cents": {
"type": "integer",
"minimum": 0,
"maximum": 10000
},
"withdrawal_min_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000,
"nullable": true
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"minimum": 100,
"maximum": 100000000,
"nullable": true
},
"new_account_days": {
"type": "integer",
"minimum": 0,
"maximum": 365
},
"withdrawal_review_above_cents": {
"type": "integer",
"minimum": 0,
"maximum": 100000000,
"nullable": true
},
"provider_pix_cost_cents": {
"type": "integer",
"minimum": 0,
"maximum": 10000,
"nullable": true
},
"provider_payout_cost_cents": {
"type": "integer",
"minimum": 0,
"maximum": 10000,
"nullable": true
},
"note": {
"type": "string",
"minLength": 3,
"maxLength": 300
},
"expected_version": {
"type": "integer",
"minimum": 1,
"description": "Versão em vigor que o operador leu."
}
}
}{
"type": "object",
"required": [
"version",
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents",
"provider_pix_cost_cents",
"provider_payout_cost_cents",
"effective_from",
"note",
"created_at"
],
"properties": {
"version": {
"type": "integer"
},
"payment_fee_cents": {
"type": "integer",
"description": "Parte fixa da tarifa por venda, em centavos."
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Parte percentual por venda, em pontos-base (99 = 0,99%). Tarifa = fixa + round_half_up(valor × bps / 10000), em centavos."
},
"withdrawal_fee_cents": {
"type": "integer"
},
"withdrawal_min_cents": {
"type": "integer",
"description": "Menor saque aceito."
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"nullable": true,
"description": "Soma de saques numa janela de 24 horas. Nulo é sem limite. Saques recusados ou que falharam não contam."
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"nullable": true,
"description": "Limite em 24 horas enquanto a conta tiver menos de new_account_days dias. Nulo: vale o limite geral."
},
"new_account_days": {
"type": "integer"
},
"withdrawal_review_above_cents": {
"type": "integer",
"nullable": true,
"description": "Saque até este valor segue direto ao provedor; acima, vai para a fila de revisão. Nulo: todo saque é revisado."
},
"provider_pix_cost_cents": {
"type": "integer",
"nullable": true,
"description": "Custo por Pix informado pelo operador ao publicar. Só a operação vê."
},
"provider_payout_cost_cents": {
"type": "integer",
"nullable": true,
"description": "Custo por repasse informado pelo operador ao publicar."
},
"effective_from": {
"type": "string",
"format": "date-time"
},
"note": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/ticketsSolicitações de suporteResolvidas por último. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminListTickets",
"tags": [
"admin"
],
"summary": "Solicitações de suporte",
"description": "Resolvidas por último. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AdminTicket"
}
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"name": "status",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
}
}
]
}{
"allOf": [
{
"$ref": "#/components/schemas/Ticket"
},
{
"type": "object",
"required": [
"seller_id",
"seller_name"
],
"properties": {
"seller_id": {
"type": "string",
"format": "uuid"
},
"seller_name": {
"type": "string"
}
}
}
]
}{
"type": "object",
"required": [
"id",
"subject",
"category",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"status": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/tickets/{ticket_id}Conversa de suporteExige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminGetTicket",
"tags": [
"admin"
],
"summary": "Conversa de suporte",
"description": "Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AdminTicketDetail"
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"allOf": [
{
"$ref": "#/components/schemas/TicketDetail"
},
{
"type": "object",
"required": [
"seller_id",
"seller_name"
],
"properties": {
"seller_id": {
"type": "string",
"format": "uuid"
},
"seller_name": {
"type": "string"
}
}
}
]
}{
"allOf": [
{
"$ref": "#/components/schemas/Ticket"
},
{
"type": "object",
"required": [
"messages"
],
"properties": {
"messages": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"author_side",
"body",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"author_side": {
"type": "string",
"enum": [
"seller",
"platform"
]
},
"body": {
"type": "string"
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}
}
}
}
]
}{
"type": "object",
"required": [
"id",
"subject",
"category",
"status",
"created_at",
"updated_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"subject": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"payments",
"withdrawals",
"account",
"other"
]
},
"status": {
"type": "string",
"enum": [
"open",
"in_progress",
"resolved"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/tickets/{ticket_id}/messagesResponder solicitaçãoGrava a mensagem como da plataforma e atualiza a situação. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminAnswerTicket",
"tags": [
"admin"
],
"summary": "Responder solicitação",
"description": "Grava a mensagem como da plataforma e atualiza a situação. Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"parameters": [
{
"$ref": "#/components/parameters/Origin"
},
{
"$ref": "#/components/parameters/CsrfToken"
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PlatformReplyInput"
}
}
}
},
"responses": {
"201": {
"description": "Resposta gravada.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ok",
"status"
],
"properties": {
"ok": {
"type": "boolean"
},
"status": {
"type": "string",
"enum": [
"in_progress",
"resolved"
]
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"409": {
"description": "Solicitação já encerrada (TICKET_RESOLVED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"type": "object",
"additionalProperties": false,
"required": [
"body",
"status"
],
"properties": {
"body": {
"type": "string",
"minLength": 1,
"maxLength": 2000
},
"status": {
"type": "string",
"enum": [
"in_progress",
"resolved"
]
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/admin/audit-eventsAuditoria da plataformaExige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "adminListAuditEvents",
"tags": [
"admin"
],
"summary": "Auditoria da plataforma",
"description": "Exige papel de operador e segundo fator verificado na sessão. Para quem não é operador responde 404.",
"responses": {
"200": {
"description": "Resposta.",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"items",
"next_offset"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/AdminAuditEvent"
}
},
"next_offset": {
"type": "integer",
"nullable": true
}
}
}
}
}
},
"401": {
"$ref": "#/components/responses/Unauthenticated"
},
"403": {
"description": "Operador sem segundo fator verificado nesta sessão (SECOND_FACTOR_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"404": {
"$ref": "#/components/responses/NotFound"
},
"422": {
"$ref": "#/components/responses/ValidationError"
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
},
"parameters": [
{
"name": "scope",
"in": "query",
"required": false,
"schema": {
"type": "string",
"enum": [
"all",
"operator"
],
"default": "all"
}
},
{
"$ref": "#/components/parameters/Offset"
}
]
}{
"allOf": [
{
"$ref": "#/components/schemas/AuditEvent"
},
{
"type": "object",
"required": [
"seller_id",
"seller_name",
"actor_name",
"actor_is_operator"
],
"properties": {
"seller_id": {
"type": "string",
"format": "uuid",
"nullable": true
},
"seller_name": {
"type": "string",
"nullable": true
},
"actor_name": {
"type": "string",
"nullable": true
},
"actor_is_operator": {
"type": "boolean"
}
}
}
]
}{
"type": "object",
"required": [
"id",
"action",
"created_at"
],
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"action": {
"type": "string",
"description": "Nome do evento, como charge.paid, verification.approved ou fees.published. A lista cresce com o produto."
},
"target_id": {
"type": "string",
"nullable": true
},
"metadata": {
"type": "object",
"additionalProperties": true
},
"created_at": {
"type": "string",
"format": "date-time"
}
}
}{
"type": "object",
"required": [
"code",
"message",
"request_id"
],
"properties": {
"code": {
"type": "string"
},
"message": {
"type": "string",
"description": "Texto em português do Brasil, pronto para exibição."
},
"request_id": {
"type": "string",
"format": "uuid"
}
}
}/api/v1/public/pricingTabela de tarifas públicaPolítica comercial em vigor, sem sessão, para a página inicial. Não inclui o custo do provedor.
Autenticação: veja security no contrato abaixo e as definições ao final desta página. Se a operação não sobrescrever security, vale a configuração global.
{
"operationId": "getPublicPricing",
"tags": [
"checkout"
],
"summary": "Tabela de tarifas pública",
"description": "Política comercial em vigor, sem sessão, para a página inicial. Não inclui o custo do provedor.",
"security": [],
"responses": {
"200": {
"description": "Versão em vigor.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PublicPricing"
}
}
}
},
"429": {
"$ref": "#/components/responses/RateLimited"
},
"500": {
"$ref": "#/components/responses/InternalError"
}
}
}{
"allOf": [
{
"$ref": "#/components/schemas/FeeVersion"
},
{
"type": "object",
"required": [
"payments_enabled"
],
"properties": {
"payments_enabled": {
"type": "boolean",
"description": "Falso enquanto não houver provedor contratado."
}
}
}
]
}{
"type": "object",
"description": "Política comercial em vigor. Não inclui o custo do provedor.",
"required": [
"version",
"payment_fee_cents",
"payment_fee_bps",
"withdrawal_fee_cents",
"withdrawal_min_cents",
"withdrawal_daily_limit_cents",
"withdrawal_daily_limit_new_cents",
"new_account_days",
"withdrawal_review_above_cents",
"currency"
],
"properties": {
"version": {
"type": "integer"
},
"payment_fee_cents": {
"type": "integer",
"description": "Parte fixa da tarifa por venda, em centavos."
},
"payment_fee_bps": {
"type": "integer",
"minimum": 0,
"maximum": 1000,
"description": "Parte percentual por venda, em pontos-base (99 = 0,99%). Tarifa = fixa + round_half_up(valor × bps / 10000), em centavos."
},
"withdrawal_fee_cents": {
"type": "integer"
},
"withdrawal_min_cents": {
"type": "integer",
"description": "Menor saque aceito."
},
"withdrawal_daily_limit_cents": {
"type": "integer",
"nullable": true,
"description": "Soma de saques numa janela de 24 horas. Nulo é sem limite. Saques recusados ou que falharam não contam."
},
"withdrawal_daily_limit_new_cents": {
"type": "integer",
"nullable": true,
"description": "Limite em 24 horas enquanto a conta tiver menos de new_account_days dias. Nulo: vale o limite geral."
},
"new_account_days": {
"type": "integer"
},
"withdrawal_review_above_cents": {
"type": "integer",
"nullable": true,
"description": "Saque até este valor segue direto ao provedor; acima, vai para a fila de revisão. Nulo: todo saque é revisado."
},
"currency": {
"type": "string",
"enum": [
"BRL"
]
}
}
}{
"securitySchemes": {
"SessionCookie": {
"type": "apiKey",
"in": "cookie",
"name": "movvi_session",
"description": "Sessão opaca criada no login. HttpOnly, SameSite=Lax, Secure quando a origem é HTTPS. Não há autenticação Bearer nesta etapa."
}
},
"parameters": {
"Origin": {
"name": "Origin",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "Obrigatório em todo método diferente de GET, HEAD e OPTIONS. Precisa ser exatamente PUBLIC_APP_URL; qualquer outro valor responde 403 ORIGIN_INVALID."
},
"CsrfToken": {
"name": "X-CSRF-Token",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "Obrigatório nas alterações com sessão. Valor devolvido em csrf_token pelo login ou por GET /api/v1/auth/session."
},
"SellerId": {
"name": "seller_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
"Offset": {
"name": "offset",
"in": "query",
"required": false,
"schema": {
"type": "integer",
"minimum": 0,
"maximum": 1000000,
"default": 0
}
},
"ContentType": {
"name": "Content-Type",
"in": "header",
"required": true,
"schema": {
"type": "string",
"enum": [
"application/json"
]
},
"description": "Obrigatório em toda alteração, inclusive nas que não têm corpo: o servidor lê o corpo antes de rotear e responde 415 JSON_REQUIRED sem este cabeçalho."
},
"ChargeId": {
"name": "charge_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
"CheckoutToken": {
"name": "token",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^[a-f0-9]{32}$"
},
"description": "Vai na URL do checkout. Não revela o vendedor nem a cobrança."
},
"ProviderName": {
"name": "provider",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^[a-z0-9_-]{1,40}$"
},
"description": "Precisa ser o adaptador configurado; qualquer outro responde 404."
},
"ProviderSignature": {
"name": "X-Provider-Signature",
"in": "header",
"required": true,
"schema": {
"type": "string"
},
"description": "HMAC-SHA256 do corpo exato recebido. É o que autentica o aviso: este endpoint não exige Origin nem sessão, porque a chamada vem dos servidores do provedor."
},
"IdempotencyKey": {
"name": "Idempotency-Key",
"in": "header",
"required": false,
"schema": {
"type": "string",
"pattern": "^[A-Za-z0-9_-]{16,128}$"
},
"description": "Repetir a mesma chave com o mesmo corpo devolve a primeira resposta em vez de criar outra cobrança. A mesma chave com corpo diferente responde 409."
},
"ChargeStatusFilter": {
"name": "status",
"in": "query",
"required": false,
"schema": {
"$ref": "#/components/schemas/ChargeStatus"
}
},
"WithdrawalId": {
"name": "withdrawal_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
"WithdrawalStatusFilter": {
"name": "status",
"in": "query",
"required": false,
"schema": {
"$ref": "#/components/schemas/WithdrawalStatus"
}
},
"ApiKeyId": {
"name": "key_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
"TicketId": {
"name": "ticket_id",
"in": "path",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
"UnreadOnly": {
"name": "unread",
"in": "query",
"required": false,
"schema": {
"type": "boolean"
}
}
},
"responses": {
"Accepted": {
"description": "Pedido aceito. A mensagem é neutra e não confirma a existência da conta.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Message"
}
}
}
},
"Message": {
"description": "Operação concluída.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Message"
}
}
}
},
"Unauthenticated": {
"description": "Sem sessão (UNAUTHENTICATED) ou sessão expirada/revogada (SESSION_EXPIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"OriginInvalid": {
"description": "Origem da requisição não permitida (ORIGIN_INVALID).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"ForbiddenMutation": {
"description": "Origem não permitida (ORIGIN_INVALID) ou X-CSRF-Token ausente/incorreto (CSRF_INVALID).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"ForbiddenRole": {
"description": "Origem, CSRF, e-mail não confirmado ou vínculo sem permissão (FORBIDDEN).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"EmailNotVerified": {
"description": "E-mail ainda não confirmado (EMAIL_NOT_VERIFIED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"NotFound": {
"description": "Recurso inexistente ou sem vínculo do usuário (NOT_FOUND).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"VersionConflict": {
"description": "expected_version diferente da versão atual (VERSION_CONFLICT).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"ValidationError": {
"description": "Campos fora do formato (VALIDATION_ERROR).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationError"
}
}
}
},
"TooLarge": {
"description": "Corpo acima de 32768 bytes (BODY_TOO_LARGE).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"UnsupportedMedia": {
"description": "Content-Type diferente de application/json (JSON_REQUIRED).",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"RateLimited": {
"description": "Limite de tentativas atingido (RATE_LIMITED). A janela é de 10 minutos.",
"headers": {
"Retry-After": {
"schema": {
"type": "integer"
},
"description": "Sempre 600."
}
},
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
},
"InternalError": {
"description": "Falha interna (INTERNAL_ERROR). Detalhes não são expostos; use request_id para localizar no log.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
}
}
}[
{
"SessionCookie": []
}
]