{"openapi":"3.0.0","paths":{"/health":{"get":{"description":"Responde enquanto o processo está vivo. É o que o load balancer usa para decidir reiniciar a task.","operationId":"HealthController_check","parameters":[],"responses":{"200":{"description":"Processo vivo","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Indicador estático de liveness","type":"string","enum":["ok"]}},"required":["status"]}}}}},"summary":"Liveness","tags":["health"]}},"/health/ready":{"get":{"description":"Verifica as dependências (banco). É o que decide se a task recebe tráfego — falha aqui tira a instância do balanceamento sem matá-la.","operationId":"HealthController_ready","parameters":[],"responses":{"200":{"description":"Pronta para receber tráfego","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Pronta para tráfego ou degradada","type":"string","enum":["ok","degraded"]},"checks":{"description":"Resultado de cada dependência verificada","type":"object","properties":{"database":{"description":"Conexão com o Postgres respondendo","type":"boolean"}},"required":["database"]}},"required":["status","checks"]}}}},"503":{"description":"Degradada, não deve receber tráfego","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"description":"Pronta para tráfego ou degradada","type":"string","enum":["ok","degraded"]},"checks":{"description":"Resultado de cada dependência verificada","type":"object","properties":{"database":{"description":"Conexão com o Postgres respondendo","type":"boolean"}},"required":["database"]}},"required":["status","checks"]}}}}},"summary":"Readiness","tags":["health"]}},"/v1/products":{"post":{"description":"Cria um produto do catálogo com preço MENSAL fixo ou variável via endpoint. O tipo de preço é imutável depois de criado.","operationId":"ProductsController_create","parameters":[{"name":"Idempotency-Key","in":"header","description":"Chave única sua — repetir devolve a mesma resposta","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Nome do produto — é o que o assinante lê na fatura","type":"string","minLength":1,"maxLength":120},"description":{"description":"Descrição interna, opcional","type":"string","maxLength":500,"nullable":true},"externalRef":{"description":"Seu identificador para este produto — devolvido nos webhooks e no endpoint de preço","type":"string","minLength":1,"maxLength":120,"nullable":true},"pricing":{"description":"Como o preço deste produto é definido. O modo é imutável depois de criado","oneOf":[{"type":"object","properties":{"mode":{"description":"Preço fixo: o valor mensal está na tabela","type":"string","enum":["fixed"]},"monthlyPriceCents":{"description":"Preço MENSAL em centavos — o período do plano multiplica","type":"integer","minimum":0,"exclusiveMinimum":false}},"required":["mode","monthlyPriceCents"]},{"type":"object","properties":{"mode":{"description":"Preço variável: o motor pergunta o valor ao seu endpoint a cada ciclo","type":"string","enum":["endpoint"]},"url":{"description":"URL https do seu endpoint de preço","type":"string","format":"uri"},"capCents":{"description":"Teto por cobrança em centavos — resposta acima disso é tratada como falha","type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["mode","url","capCents"]}]}},"required":["name","pricing"]}}}},"responses":{"201":{"description":"Produto criado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}}}},"400":{"description":"Payload inválido ou Idempotency-Key ausente","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Criar produto","tags":["Produtos"]},"get":{"description":"Catálogo completo, paginado, mais recentes primeiro.","operationId":"ProductsController_list","parameters":[{"name":"page","required":false,"in":"query","description":"Página, começando em 1","schema":{"description":"Página, começando em 1","type":"integer","minimum":1,"exclusiveMinimum":false,"default":1}},{"name":"pageSize","required":false,"in":"query","description":"Itens por página (máximo 100)","schema":{"description":"Itens por página (máximo 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false,"default":25}}],"responses":{"200":{"description":"Página de produtos","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Records of the current page","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"description":"Current page (1-based)","type":"integer"},"pageSize":{"description":"Records per page","type":"integer"},"totalRecords":{"description":"Total records matching the filters","type":"integer"},"totalPages":{"description":"Total pages for the current pageSize","type":"integer"}},"required":["page","pageSize","totalRecords","totalPages"]}},"required":["data","pagination"]}}}}},"security":[{"bearer":[]}],"summary":"Listar produtos","tags":["Produtos"]}},"/v1/products/{productId}":{"get":{"description":"Um produto do catálogo pelo id.","operationId":"ProductsController_get","parameters":[{"name":"productId","required":true,"in":"path","description":"Id do produto","schema":{"type":"string"}}],"responses":{"200":{"description":"Produto","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}}}},"404":{"description":"Produto não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Detalhar produto","tags":["Produtos"]},"patch":{"description":"Preço novo vale a partir das próximas faturas. Campos do outro modo de preço são recusados com 409.","operationId":"ProductsController_patch","parameters":[{"name":"productId","required":true,"in":"path","description":"Id do produto","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Novo nome","type":"string","minLength":1,"maxLength":120},"description":{"description":"Nova descrição","type":"string","maxLength":500,"nullable":true},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false},"endpointUrl":{"description":"Nova URL do endpoint (só produto variável)","type":"string","format":"uri"},"capCents":{"description":"Novo teto por cobrança (só produto variável)","type":"integer","minimum":0,"exclusiveMinimum":true}}}}}},"responses":{"200":{"description":"Produto atualizado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}}}},"409":{"description":"Tentativa de mexer no modo de preço, que é imutável","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Editar produto","tags":["Produtos"]}},"/v1/products/{productId}/archive":{"post":{"description":"Bloqueia planos novos com este produto; assinaturas existentes seguem faturando. Produto nunca é apagado.","operationId":"ProductsController_archive","parameters":[{"name":"productId","required":true,"in":"path","description":"Id do produto","schema":{"type":"string"}}],"responses":{"200":{"description":"Produto arquivado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}}}},"404":{"description":"Produto não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Arquivar produto","tags":["Produtos"]}},"/v1/products/{productId}/unarchive":{"post":{"description":"Volta a aceitar o produto em planos novos.","operationId":"ProductsController_unarchive","parameters":[{"name":"productId","required":true,"in":"path","description":"Id do produto","schema":{"type":"string"}}],"responses":{"200":{"description":"Produto reativado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do produto","type":"string","format":"uuid"},"name":{"description":"Nome do produto","type":"string"},"description":{"description":"Descrição interna","type":"string","nullable":true},"externalRef":{"description":"Seu identificador para este produto","type":"string","nullable":true},"pricingMode":{"description":"fixed (preço mensal na tabela) ou endpoint (seu sistema responde)","type":"string","enum":["fixed","endpoint"],"x-enumNames":["fixed","endpoint"]},"monthlyPriceCents":{"description":"Valor em centavos, sempre inteiro (24990 = R$ 249,90)","type":"integer","minimum":0,"exclusiveMinimum":false,"nullable":true},"endpointUrl":{"description":"URL do endpoint de preço — nulo em produto fixo","type":"string","nullable":true},"capCents":{"description":"Teto por cobrança em centavos — nulo em produto fixo","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não entra em plano novo","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","description","externalRef","pricingMode","monthlyPriceCents","endpointUrl","capCents","archivedAt","createdAt"]}}}},"404":{"description":"Produto não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Reativar produto","tags":["Produtos"]}},"/v1/products/{productId}/pricing-test":{"post":{"description":"Dispara uma chamada real com mode: test e o payload de exemplo, e devolve o resultado cru — status, latência e validação do formato. Ninguém descobre integração quebrada na primeira fatura.","operationId":"ProductsController_pricingTest","parameters":[{"name":"productId","required":true,"in":"path","description":"Id do produto de preço variável","schema":{"type":"string"}}],"responses":{"200":{"description":"Resultado cru da chamada de teste","content":{"application/json":{"schema":{"type":"object","properties":{"outcome":{"description":"Resultado da chamada de teste","type":"string","enum":["ok","skip","timeout","http_error","invalid_response","over_cap"]},"amountCents":{"description":"Valor devolvido, quando ok","type":"integer","nullable":true},"description":{"description":"Descrição devolvida","type":"string","nullable":true},"responseStatus":{"description":"HTTP status","type":"integer","nullable":true},"latencyMs":{"description":"Latência","type":"integer"},"responseBody":{"description":"Corpo cru da resposta","type":"string","nullable":true}},"required":["outcome","amountCents","description","responseStatus","latencyMs","responseBody"]}}}},"404":{"description":"Produto não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Testar o endpoint de preço","tags":["Produtos"]}},"/v1/plans":{"post":{"description":"A oferta completa num POST: período, método padrão, parcelamento máximo (independente do período), fidelidade e os produtos com suas réguas de desconto por faixa de ciclo — a primeira regra que casa com o ciclo ganha.","operationId":"PlansController_create","parameters":[{"name":"Idempotency-Key","in":"header","description":"Chave única sua — repetir devolve a mesma resposta","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Nome do plano","type":"string","minLength":1,"maxLength":120},"periodMonths":{"description":"Meses por ciclo (1, 3, 6, 12) — cada ciclo cobra período × o mensal de cada produto","oneOf":[{"type":"number","minimum":1,"maximum":1},{"type":"number","minimum":3,"maximum":3},{"type":"number","minimum":6,"maximum":6},{"type":"number","minimum":12,"maximum":12}]},"defaultPaymentMethod":{"description":"Método padrão de quem assinar — cada assinatura pode sobrescrever","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista). Independente do período: semestral à vista é válido","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":12,"exclusiveMaximum":false,"default":1},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro; a tratativa de quebra é do lojista","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true},"items":{"description":"Produtos do plano","type":"array","minItems":1,"maxItems":20,"items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"discounts":{"description":"Régua de desconto deste produto. Quando duas regras pegam o mesmo ciclo, a primeira da lista ganha","type":"array","maxItems":20,"items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]},"default":[]}},"required":["productId"]}}},"required":["name","periodMonths","defaultPaymentMethod","items"]}}}},"responses":{"201":{"description":"Plano criado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do plano","type":"string","format":"uuid"},"name":{"description":"Nome do plano","type":"string"},"version":{"description":"Versão vigente da oferta — toda edição cria uma versão nova; assinantes ficam pinados na deles","type":"integer"},"periodMonths":{"description":"Meses por ciclo","type":"integer"},"defaultPaymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer"},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não aceita assinatura nova","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"},"items":{"description":"Produtos e réguas de desconto do plano","type":"array","items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"position":{"description":"Ordem do item no plano","type":"integer"},"discounts":{"description":"Régua de desconto do produto, na ordem de prioridade","type":"array","items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]}}},"required":["productId","position","discounts"]}}},"required":["id","name","version","periodMonths","defaultPaymentMethod","maxInstallments","commitmentCycles","archivedAt","createdAt","items"]}}}},"409":{"description":"Produto arquivado no plano","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}},"422":{"description":"Desconto em produto variável — o valor já vem do seu endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Criar plano","tags":["Planos"]},"get":{"description":"As ofertas, paginadas, mais recentes primeiro.","operationId":"PlansController_list","parameters":[{"name":"page","required":false,"in":"query","description":"Página, começando em 1","schema":{"description":"Página, começando em 1","type":"integer","minimum":1,"exclusiveMinimum":false,"default":1}},{"name":"pageSize","required":false,"in":"query","description":"Itens por página (máximo 100)","schema":{"description":"Itens por página (máximo 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false,"default":25}}],"responses":{"200":{"description":"Página de planos","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Records of the current page","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do plano","type":"string","format":"uuid"},"name":{"description":"Nome do plano","type":"string"},"version":{"description":"Versão vigente da oferta — toda edição cria uma versão nova; assinantes ficam pinados na deles","type":"integer"},"periodMonths":{"description":"Meses por ciclo","type":"integer"},"defaultPaymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer"},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não aceita assinatura nova","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","version","periodMonths","defaultPaymentMethod","maxInstallments","commitmentCycles","archivedAt","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"description":"Current page (1-based)","type":"integer"},"pageSize":{"description":"Records per page","type":"integer"},"totalRecords":{"description":"Total records matching the filters","type":"integer"},"totalPages":{"description":"Total pages for the current pageSize","type":"integer"}},"required":["page","pageSize","totalRecords","totalPages"]}},"required":["data","pagination"]}}}}},"security":[{"bearer":[]}],"summary":"Listar planos","tags":["Planos"]}},"/v1/plans/{planId}":{"put":{"description":"A oferta completa de novo: cria a próxima versão base. Assinantes existentes seguem pinados na versão deles — só quem assinar daqui em diante pega a nova. Propagar para quem já assina é uma operação separada e explícita.","operationId":"PlansController_releaseNewVersion","parameters":[{"name":"planId","required":true,"in":"path","description":"Id do plano","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Nome do plano","type":"string","minLength":1,"maxLength":120},"periodMonths":{"description":"Meses por ciclo (1, 3, 6, 12) — cada ciclo cobra período × o mensal de cada produto","oneOf":[{"type":"number","minimum":1,"maximum":1},{"type":"number","minimum":3,"maximum":3},{"type":"number","minimum":6,"maximum":6},{"type":"number","minimum":12,"maximum":12}]},"defaultPaymentMethod":{"description":"Método padrão de quem assinar — cada assinatura pode sobrescrever","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista). Independente do período: semestral à vista é válido","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":12,"exclusiveMaximum":false,"default":1},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro; a tratativa de quebra é do lojista","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true},"items":{"description":"Produtos do plano","type":"array","minItems":1,"maxItems":20,"items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"discounts":{"description":"Régua de desconto deste produto. Quando duas regras pegam o mesmo ciclo, a primeira da lista ganha","type":"array","maxItems":20,"items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]},"default":[]}},"required":["productId"]}}},"required":["name","periodMonths","defaultPaymentMethod","items"]}}}},"responses":{"200":{"description":"Plano na nova versão","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do plano","type":"string","format":"uuid"},"name":{"description":"Nome do plano","type":"string"},"version":{"description":"Versão vigente da oferta — toda edição cria uma versão nova; assinantes ficam pinados na deles","type":"integer"},"periodMonths":{"description":"Meses por ciclo","type":"integer"},"defaultPaymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer"},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não aceita assinatura nova","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"},"items":{"description":"Produtos e réguas de desconto do plano","type":"array","items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"position":{"description":"Ordem do item no plano","type":"integer"},"discounts":{"description":"Régua de desconto do produto, na ordem de prioridade","type":"array","items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]}}},"required":["productId","position","discounts"]}}},"required":["id","name","version","periodMonths","defaultPaymentMethod","maxInstallments","commitmentCycles","archivedAt","createdAt","items"]}}}},"404":{"description":"Plano não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Publicar uma nova versão do plano","tags":["Planos"]},"get":{"description":"O plano com itens e réguas de desconto.","operationId":"PlansController_get","parameters":[{"name":"planId","required":true,"in":"path","description":"Id do plano","schema":{"type":"string"}}],"responses":{"200":{"description":"Plano","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do plano","type":"string","format":"uuid"},"name":{"description":"Nome do plano","type":"string"},"version":{"description":"Versão vigente da oferta — toda edição cria uma versão nova; assinantes ficam pinados na deles","type":"integer"},"periodMonths":{"description":"Meses por ciclo","type":"integer"},"defaultPaymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer"},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não aceita assinatura nova","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"},"items":{"description":"Produtos e réguas de desconto do plano","type":"array","items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"position":{"description":"Ordem do item no plano","type":"integer"},"discounts":{"description":"Régua de desconto do produto, na ordem de prioridade","type":"array","items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]}}},"required":["productId","position","discounts"]}}},"required":["id","name","version","periodMonths","defaultPaymentMethod","maxInstallments","commitmentCycles","archivedAt","createdAt","items"]}}}},"404":{"description":"Plano não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Detalhar plano","tags":["Planos"]}},"/v1/plans/{planId}/archive":{"post":{"description":"Sem assinaturas novas; as existentes seguem faturando.","operationId":"PlansController_archive","parameters":[{"name":"planId","required":true,"in":"path","description":"Id do plano","schema":{"type":"string"}}],"responses":{"200":{"description":"Plano arquivado","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador do plano","type":"string","format":"uuid"},"name":{"description":"Nome do plano","type":"string"},"version":{"description":"Versão vigente da oferta — toda edição cria uma versão nova; assinantes ficam pinados na deles","type":"integer"},"periodMonths":{"description":"Meses por ciclo","type":"integer"},"defaultPaymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer"},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","nullable":true},"archivedAt":{"description":"Quando foi arquivado — arquivado não aceita assinatura nova","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criado","type":"string","format":"date-time"}},"required":["id","name","version","periodMonths","defaultPaymentMethod","maxInstallments","commitmentCycles","archivedAt","createdAt"]}}}},"404":{"description":"Plano não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Arquivar plano","tags":["Planos"]}},"/v1/subscriptions":{"post":{"description":"Cria (ou reaproveita, pelo externalRef) o cliente final e o vincula ao plano. chargeDay omitido assume o dia da criação travado em 28; paymentMethod omitido herda o padrão do plano. A primeira fatura nasce no próximo ciclo de geração.","operationId":"SubscriptionsController_create","parameters":[{"name":"Idempotency-Key","in":"header","description":"Chave única sua — repetir devolve a mesma resposta","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"planId":{"description":"Plano a atribuir","type":"string","format":"uuid"},"customer":{"description":"Cliente final — criado ou reaproveitado pelo externalRef","type":"object","properties":{"externalRef":{"description":"O identificador do cliente NO SEU SISTEMA — é ele que devolvemos em webhooks e no endpoint de preço","type":"string","minLength":1,"maxLength":120},"name":{"description":"Nome do cliente final","type":"string","minLength":1,"maxLength":200},"email":{"description":"E-mail do cliente final","type":"string","format":"email"},"document":{"description":"CPF/CNPJ, opcional — alguns gateways exigem para emitir","type":"string","minLength":11,"maxLength":18,"nullable":true}},"required":["externalRef","name","email"]},"paymentMethod":{"description":"Método de pagamento: card, pix ou boleto. Pix e boleto são sempre à vista","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"chargeDay":{"description":"Dia da cobrança (1 a 28). Omitido: o dia da criação, travado em 28","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":28,"exclusiveMaximum":false},"firstChargeDate":{"description":"Data da primeira cobrança (YYYY-MM-DD), hoje ou futura. Omitida: cobramos assim que a folga de geração permite. Sem chargeDay junto, o dia dela vira a âncora dos próximos ciclos","type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"}},"required":["planId","customer"]}}}},"responses":{"201":{"description":"Assinatura criada","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da assinatura","type":"string","format":"uuid"},"planId":{"description":"Plano atribuído","type":"string","format":"uuid"},"planVersion":{"description":"Versão do plano pinada na adesão — edições do plano base não mexem aqui","type":"integer"},"customized":{"description":"true quando esta assinatura roda uma versão própria (condição negociada)","type":"boolean"},"customer":{"description":"Cliente final","type":"object","properties":{"id":{"description":"Nosso identificador do cliente","type":"string","format":"uuid"},"externalRef":{"description":"O seu identificador do cliente","type":"string"},"name":{"description":"Nome","type":"string"},"email":{"description":"E-mail","type":"string"}},"required":["id","externalRef","name","email"]},"status":{"description":"Estado da assinatura","type":"string","enum":["active","canceled"]},"chargeDay":{"description":"Dia do vencimento das faturas (1 a 28)","type":"integer"},"paymentMethod":{"description":"Método efetivo desta assinatura","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"paymentMethodSource":{"description":"De onde veio o método: padrão do plano ou override na criação","type":"string","enum":["plan_default","override"]},"cycleCount":{"description":"Faturas já geradas para esta assinatura","type":"integer"},"commitmentCycles":{"description":"Fidelidade congelada na adesão — só registro","type":"integer","nullable":true},"nextDueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"startedAt":{"description":"Quando a assinatura começou","type":"string","format":"date-time"},"canceledAt":{"description":"Quando foi cancelada","type":"string","format":"date-time","nullable":true}},"required":["id","planId","planVersion","customized","customer","status","chargeDay","paymentMethod","paymentMethodSource","cycleCount","commitmentCycles","nextDueDate","startedAt","canceledAt"]}}}},"404":{"description":"Plano não encontrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}},"409":{"description":"Plano arquivado não aceita assinatura nova","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Vincular um cliente a um plano","tags":["Assinaturas"]},"get":{"description":"Assinaturas com cliente, plano e ciclo, paginadas.","operationId":"SubscriptionsController_list","parameters":[{"name":"page","required":false,"in":"query","description":"Página, começando em 1","schema":{"description":"Página, começando em 1","type":"integer","minimum":1,"exclusiveMinimum":false,"default":1}},{"name":"pageSize","required":false,"in":"query","description":"Itens por página (máximo 100)","schema":{"description":"Itens por página (máximo 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false,"default":25}}],"responses":{"200":{"description":"Página de assinaturas","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Records of the current page","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador da assinatura","type":"string","format":"uuid"},"planId":{"description":"Plano atribuído","type":"string","format":"uuid"},"planVersion":{"description":"Versão do plano pinada na adesão — edições do plano base não mexem aqui","type":"integer"},"customized":{"description":"true quando esta assinatura roda uma versão própria (condição negociada)","type":"boolean"},"customer":{"description":"Cliente final","type":"object","properties":{"id":{"description":"Nosso identificador do cliente","type":"string","format":"uuid"},"externalRef":{"description":"O seu identificador do cliente","type":"string"},"name":{"description":"Nome","type":"string"},"email":{"description":"E-mail","type":"string"}},"required":["id","externalRef","name","email"]},"status":{"description":"Estado da assinatura","type":"string","enum":["active","canceled"]},"chargeDay":{"description":"Dia do vencimento das faturas (1 a 28)","type":"integer"},"paymentMethod":{"description":"Método efetivo desta assinatura","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"paymentMethodSource":{"description":"De onde veio o método: padrão do plano ou override na criação","type":"string","enum":["plan_default","override"]},"cycleCount":{"description":"Faturas já geradas para esta assinatura","type":"integer"},"commitmentCycles":{"description":"Fidelidade congelada na adesão — só registro","type":"integer","nullable":true},"nextDueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"startedAt":{"description":"Quando a assinatura começou","type":"string","format":"date-time"},"canceledAt":{"description":"Quando foi cancelada","type":"string","format":"date-time","nullable":true}},"required":["id","planId","planVersion","customized","customer","status","chargeDay","paymentMethod","paymentMethodSource","cycleCount","commitmentCycles","nextDueDate","startedAt","canceledAt"]}},"pagination":{"type":"object","properties":{"page":{"description":"Current page (1-based)","type":"integer"},"pageSize":{"description":"Records per page","type":"integer"},"totalRecords":{"description":"Total records matching the filters","type":"integer"},"totalPages":{"description":"Total pages for the current pageSize","type":"integer"}},"required":["page","pageSize","totalRecords","totalPages"]}},"required":["data","pagination"]}}}}},"security":[{"bearer":[]}],"summary":"Listar assinaturas","tags":["Assinaturas"]}},"/v1/subscriptions/{subscriptionId}/preview":{"get":{"description":"Roda a mesma decisão pura da geração — régua do ciclo seguinte, itens e parcelamento — e devolve a fatura simulada. Zero efeitos: nada é gravado, emitido ou consumido. Item variável aparece como pending com a nota de como o pull resolveria o valor.","operationId":"SubscriptionsController_previewNext","parameters":[{"name":"subscriptionId","required":true,"in":"path","description":"Assinatura a simular","schema":{"type":"string"}}],"responses":{"200":{"description":"A próxima fatura, simulada","content":{"application/json":{"schema":{"type":"object","properties":{"subscriptionId":{"description":"Assinatura simulada","type":"string","format":"uuid"},"cycle":{"description":"O ciclo que seria cobrado (o próximo)","type":"integer"},"dueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"paymentMethod":{"description":"Método efetivo: o override da assinatura ou o padrão do plano","type":"string"},"installments":{"description":"Parcelas no cartão — nulo quando à vista ou método não-cartão","type":"integer","nullable":true},"fixedTotalCents":{"description":"Soma dos itens de preço fixo, em centavos — itens variáveis entram como zero","type":"integer"},"hasPendingItems":{"description":"true quando há item variável: o total final depende do seu endpoint de preço","type":"boolean"},"items":{"description":"Itens exatamente como a geração real os montaria","type":"array","items":{"type":"object","properties":{"productId":{"description":"Produto do item","type":"string","format":"uuid"},"productName":{"description":"Nome que iria para a fatura","type":"string"},"pricingSource":{"description":"table (preço fixo) ou endpoint (variável)","type":"string"},"pricingStatus":{"description":"priced (valor fechado) ou pending (aguarda o pull)","type":"string"},"monthlyPriceCents":{"description":"Preço mensal de tabela — nulo em item variável","type":"integer","nullable":true},"months":{"description":"Meses do período multiplicando o mensal","type":"integer"},"discountPercent":{"description":"Desconto da régua que casa com este ciclo","type":"number","nullable":true},"amountCents":{"description":"Valor do item — nulo em item variável","type":"integer","nullable":true},"note":{"description":"Como o valor variável seria resolvido na geração real","type":"string","nullable":true}},"required":["productId","productName","pricingSource","pricingStatus","monthlyPriceCents","months","discountPercent","amountCents","note"]}}},"required":["subscriptionId","cycle","dueDate","paymentMethod","installments","fixedTotalCents","hasPendingItems","items"]}}}},"404":{"description":"Assinatura não encontrada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}},"409":{"description":"Assinatura cancelada não tem próxima fatura","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"],"example":{"type":"engine.subscription_already_canceled","title":"Conflito","status":409}}}}}},"security":[{"bearer":[]}],"summary":"Simular a próxima fatura (dry-run)","tags":["Assinaturas"]}},"/v1/subscriptions/{subscriptionId}":{"get":{"description":"Uma assinatura pelo id.","operationId":"SubscriptionsController_get","parameters":[{"name":"subscriptionId","required":true,"in":"path","description":"Id da assinatura","schema":{"type":"string"}}],"responses":{"200":{"description":"Assinatura","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da assinatura","type":"string","format":"uuid"},"planId":{"description":"Plano atribuído","type":"string","format":"uuid"},"planVersion":{"description":"Versão do plano pinada na adesão — edições do plano base não mexem aqui","type":"integer"},"customized":{"description":"true quando esta assinatura roda uma versão própria (condição negociada)","type":"boolean"},"customer":{"description":"Cliente final","type":"object","properties":{"id":{"description":"Nosso identificador do cliente","type":"string","format":"uuid"},"externalRef":{"description":"O seu identificador do cliente","type":"string"},"name":{"description":"Nome","type":"string"},"email":{"description":"E-mail","type":"string"}},"required":["id","externalRef","name","email"]},"status":{"description":"Estado da assinatura","type":"string","enum":["active","canceled"]},"chargeDay":{"description":"Dia do vencimento das faturas (1 a 28)","type":"integer"},"paymentMethod":{"description":"Método efetivo desta assinatura","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"paymentMethodSource":{"description":"De onde veio o método: padrão do plano ou override na criação","type":"string","enum":["plan_default","override"]},"cycleCount":{"description":"Faturas já geradas para esta assinatura","type":"integer"},"commitmentCycles":{"description":"Fidelidade congelada na adesão — só registro","type":"integer","nullable":true},"nextDueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"startedAt":{"description":"Quando a assinatura começou","type":"string","format":"date-time"},"canceledAt":{"description":"Quando foi cancelada","type":"string","format":"date-time","nullable":true}},"required":["id","planId","planVersion","customized","customer","status","chargeDay","paymentMethod","paymentMethodSource","cycleCount","commitmentCycles","nextDueDate","startedAt","canceledAt"]}}}},"404":{"description":"Assinatura não encontrada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Detalhar assinatura","tags":["Assinaturas"]}},"/v1/subscriptions/{subscriptionId}/customize":{"post":{"description":"Clona o plano numa versão própria (custom) com os termos informados e re-pina só esta assinatura — o plano base e os demais assinantes não mudam. Vale a partir do próximo ciclo.","operationId":"SubscriptionsController_customize","parameters":[{"name":"subscriptionId","required":true,"in":"path","description":"Id da assinatura","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"periodMonths":{"description":"Meses por ciclo desta assinatura","oneOf":[{"type":"number","minimum":1,"maximum":1},{"type":"number","minimum":3,"maximum":3},{"type":"number","minimum":6,"maximum":6},{"type":"number","minimum":12,"maximum":12}]},"defaultPaymentMethod":{"description":"Método padrão desta versão","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"maxInstallments":{"description":"Parcelamento máximo no cartão (1 = à vista)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":12,"exclusiveMaximum":false,"default":1},"commitmentCycles":{"description":"Fidelidade em ciclos — só registro","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true},"items":{"description":"Itens e réguas desta condição individual","type":"array","minItems":1,"maxItems":20,"items":{"type":"object","properties":{"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"discounts":{"description":"Régua de desconto deste produto. Quando duas regras pegam o mesmo ciclo, a primeira da lista ganha","type":"array","maxItems":20,"items":{"type":"object","properties":{"percent":{"description":"Percentual de desconto (1 a 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false},"fromCycle":{"description":"Primeiro ciclo em que a regra vale (ciclo = fatura)","type":"integer","minimum":1,"exclusiveMinimum":false},"toCycle":{"description":"Último ciclo em que a regra vale — omita para desconto sem fim","type":"integer","minimum":1,"exclusiveMinimum":false,"nullable":true}},"required":["percent","fromCycle"]},"default":[]}},"required":["productId"]}}},"required":["periodMonths","defaultPaymentMethod","items"]}}}},"responses":{"200":{"description":"Assinatura na versão própria","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da assinatura","type":"string","format":"uuid"},"planId":{"description":"Plano atribuído","type":"string","format":"uuid"},"planVersion":{"description":"Versão do plano pinada na adesão — edições do plano base não mexem aqui","type":"integer"},"customized":{"description":"true quando esta assinatura roda uma versão própria (condição negociada)","type":"boolean"},"customer":{"description":"Cliente final","type":"object","properties":{"id":{"description":"Nosso identificador do cliente","type":"string","format":"uuid"},"externalRef":{"description":"O seu identificador do cliente","type":"string"},"name":{"description":"Nome","type":"string"},"email":{"description":"E-mail","type":"string"}},"required":["id","externalRef","name","email"]},"status":{"description":"Estado da assinatura","type":"string","enum":["active","canceled"]},"chargeDay":{"description":"Dia do vencimento das faturas (1 a 28)","type":"integer"},"paymentMethod":{"description":"Método efetivo desta assinatura","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"paymentMethodSource":{"description":"De onde veio o método: padrão do plano ou override na criação","type":"string","enum":["plan_default","override"]},"cycleCount":{"description":"Faturas já geradas para esta assinatura","type":"integer"},"commitmentCycles":{"description":"Fidelidade congelada na adesão — só registro","type":"integer","nullable":true},"nextDueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"startedAt":{"description":"Quando a assinatura começou","type":"string","format":"date-time"},"canceledAt":{"description":"Quando foi cancelada","type":"string","format":"date-time","nullable":true}},"required":["id","planId","planVersion","customized","customer","status","chargeDay","paymentMethod","paymentMethodSource","cycleCount","commitmentCycles","nextDueDate","startedAt","canceledAt"]}}}},"404":{"description":"Assinatura não encontrada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Condição individual para esta assinatura","tags":["Assinaturas"]}},"/v1/subscriptions/{subscriptionId}/cancel":{"post":{"description":"Encerra a assinatura e devolve o estado da fidelidade — o motor registra o compromisso, a tratativa de quebra é sua.","operationId":"SubscriptionsController_cancel","parameters":[{"name":"subscriptionId","required":true,"in":"path","description":"Id da assinatura","schema":{"type":"string"}}],"responses":{"200":{"description":"Assinatura cancelada, com o estado da fidelidade","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da assinatura","type":"string","format":"uuid"},"planId":{"description":"Plano atribuído","type":"string","format":"uuid"},"planVersion":{"description":"Versão do plano pinada na adesão — edições do plano base não mexem aqui","type":"integer"},"customized":{"description":"true quando esta assinatura roda uma versão própria (condição negociada)","type":"boolean"},"customer":{"description":"Cliente final","type":"object","properties":{"id":{"description":"Nosso identificador do cliente","type":"string","format":"uuid"},"externalRef":{"description":"O seu identificador do cliente","type":"string"},"name":{"description":"Nome","type":"string"},"email":{"description":"E-mail","type":"string"}},"required":["id","externalRef","name","email"]},"status":{"description":"Estado da assinatura","type":"string","enum":["active","canceled"]},"chargeDay":{"description":"Dia do vencimento das faturas (1 a 28)","type":"integer"},"paymentMethod":{"description":"Método efetivo desta assinatura","type":"string","enum":["card","pix","boleto"],"x-enumNames":["card","pix","boleto"]},"paymentMethodSource":{"description":"De onde veio o método: padrão do plano ou override na criação","type":"string","enum":["plan_default","override"]},"cycleCount":{"description":"Faturas já geradas para esta assinatura","type":"integer"},"commitmentCycles":{"description":"Fidelidade congelada na adesão — só registro","type":"integer","nullable":true},"nextDueDate":{"description":"Vencimento da próxima fatura (YYYY-MM-DD)","type":"string"},"startedAt":{"description":"Quando a assinatura começou","type":"string","format":"date-time"},"canceledAt":{"description":"Quando foi cancelada","type":"string","format":"date-time","nullable":true},"commitment":{"description":"Estado da fidelidade no cancelamento — o motor registra, não julga","type":"object","properties":{"cycles":{"description":"Ciclos de fidelidade combinados na adesão","type":"integer","nullable":true},"completed":{"description":"Ciclos efetivamente faturados até o cancelamento","type":"integer"},"fulfilled":{"description":"true quando o compromisso foi cumprido — a tratativa de quebra é sua","type":"boolean"}},"required":["cycles","completed","fulfilled"]}},"required":["id","planId","planVersion","customized","customer","status","chargeDay","paymentMethod","paymentMethodSource","cycleCount","commitmentCycles","nextDueDate","startedAt","canceledAt","commitment"]}}}},"409":{"description":"Assinatura já cancelada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Cancelar assinatura","tags":["Assinaturas"]}},"/v1/invoices":{"get":{"description":"Todas as faturas do motor, paginadas. Use status=awaiting_value para ver as retidas aguardando valor.","operationId":"InvoicesController_list","parameters":[{"name":"page","required":false,"in":"query","description":"Página, começando em 1","schema":{"description":"Página, começando em 1","type":"integer","minimum":1,"exclusiveMinimum":false,"default":1}},{"name":"pageSize","required":false,"in":"query","description":"Itens por página (máximo 100)","schema":{"description":"Itens por página (máximo 100)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":100,"exclusiveMaximum":false,"default":25}},{"name":"status","required":false,"in":"query","description":"Filtra por estado — awaiting_value lista as retidas","schema":{"description":"Filtra por estado — awaiting_value lista as retidas","type":"string","enum":["draft","awaiting_value","ready","issued","paid","overdue","canceled"]}}],"responses":{"200":{"description":"Página de faturas","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Records of the current page","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador da fatura","type":"string","format":"uuid"},"subscriptionId":{"description":"Assinatura dona da fatura","type":"string","format":"uuid"},"cycle":{"description":"Ciclo da assinatura que esta fatura representa","type":"integer"},"status":{"description":"Estado: awaiting_value é a fatura retida aguardando valor do seu endpoint","type":"string","enum":["draft","awaiting_value","ready","issued","paid","overdue","canceled"]},"dueDate":{"description":"Vencimento (YYYY-MM-DD) — o chargeDay da assinatura","type":"string"},"paymentMethod":{"description":"Método de pagamento desta fatura","type":"string"},"installments":{"description":"Parcelas no cartão — nulo quando à vista ou método sem parcela","type":"integer","nullable":true},"totalCents":{"description":"Total em centavos — nulo enquanto houver item aguardando valor","type":"integer","nullable":true},"gatewayInvoiceId":{"description":"Id da cobrança no seu gateway, após a emissão","type":"string","nullable":true},"issuedAt":{"description":"Quando foi emitida no gateway","type":"string","format":"date-time","nullable":true},"paidAt":{"description":"Quando foi paga","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi gerada","type":"string","format":"date-time"}},"required":["id","subscriptionId","cycle","status","dueDate","paymentMethod","installments","totalCents","gatewayInvoiceId","issuedAt","paidAt","createdAt"]}},"pagination":{"type":"object","properties":{"page":{"description":"Current page (1-based)","type":"integer"},"pageSize":{"description":"Records per page","type":"integer"},"totalRecords":{"description":"Total records matching the filters","type":"integer"},"totalPages":{"description":"Total pages for the current pageSize","type":"integer"}},"required":["page","pageSize","totalRecords","totalPages"]}},"required":["data","pagination"]}}}}},"security":[{"bearer":[]}],"summary":"Listar faturas","tags":["Faturas"]}},"/v1/invoices/{invoiceId}":{"get":{"description":"A fatura com itens (snapshot de preço e desconto) e o histórico cru das chamadas ao seu endpoint de preço.","operationId":"InvoicesController_get","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"Id da fatura","schema":{"type":"string"}}],"responses":{"200":{"description":"Fatura completa","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da fatura","type":"string","format":"uuid"},"subscriptionId":{"description":"Assinatura dona da fatura","type":"string","format":"uuid"},"cycle":{"description":"Ciclo da assinatura que esta fatura representa","type":"integer"},"status":{"description":"Estado: awaiting_value é a fatura retida aguardando valor do seu endpoint","type":"string","enum":["draft","awaiting_value","ready","issued","paid","overdue","canceled"]},"dueDate":{"description":"Vencimento (YYYY-MM-DD) — o chargeDay da assinatura","type":"string"},"paymentMethod":{"description":"Método de pagamento desta fatura","type":"string"},"installments":{"description":"Parcelas no cartão — nulo quando à vista ou método sem parcela","type":"integer","nullable":true},"totalCents":{"description":"Total em centavos — nulo enquanto houver item aguardando valor","type":"integer","nullable":true},"gatewayInvoiceId":{"description":"Id da cobrança no seu gateway, após a emissão","type":"string","nullable":true},"issuedAt":{"description":"Quando foi emitida no gateway","type":"string","format":"date-time","nullable":true},"paidAt":{"description":"Quando foi paga","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi gerada","type":"string","format":"date-time"},"items":{"description":"Itens da fatura, com snapshot de preço e desconto","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do item","type":"string","format":"uuid"},"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"productName":{"description":"Nome congelado na geração","type":"string"},"pricingSource":{"description":"De onde o valor veio","type":"string","enum":["table","endpoint","manual"]},"pricingStatus":{"description":"pending = aguardando valor","type":"string","enum":["pending","priced","skipped"]},"months":{"description":"Meses cobertos pelo ciclo","type":"integer"},"monthlyPriceCents":{"description":"Preço mensal congelado — nulo em item variável","type":"integer","nullable":true},"discountPercent":{"description":"Desconto aplicado pela régua neste ciclo","type":"integer","nullable":true},"amountCents":{"description":"Valor final do item — congelado, auditável","type":"integer","nullable":true},"description":{"description":"A linha que o assinante lê","type":"string","nullable":true}},"required":["id","productId","productName","pricingSource","pricingStatus","months","monthlyPriceCents","discountPercent","amountCents","description"]}},"pricingAttempts":{"description":"Histórico cru das chamadas ao seu endpoint de preço","type":"array","items":{"type":"object","properties":{"attempt":{"description":"Número da tentativa","type":"integer"},"url":{"description":"URL chamada","type":"string"},"outcome":{"description":"Resultado da chamada ao seu endpoint","type":"string","enum":["ok","skip","timeout","http_error","invalid_response","over_cap"]},"responseStatus":{"description":"HTTP status devolvido, quando houve resposta","type":"integer","nullable":true},"latencyMs":{"description":"Latência da chamada","type":"integer","nullable":true},"responseBody":{"description":"Corpo cru da resposta — é com isso que seu time debuga","type":"string","nullable":true},"createdAt":{"description":"Quando a tentativa aconteceu","type":"string","format":"date-time"}},"required":["attempt","url","outcome","responseStatus","latencyMs","responseBody","createdAt"]}}},"required":["id","subscriptionId","cycle","status","dueDate","paymentMethod","installments","totalCents","gatewayInvoiceId","issuedAt","paidAt","createdAt","items","pricingAttempts"]}}}},"404":{"description":"Fatura não encontrada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Detalhar fatura","tags":["Faturas"]}},"/v1/invoices/{invoiceId}/retry-pricing":{"post":{"description":"Re-dispara a chamada ao seu endpoint para todo item pendente desta fatura, fora do cronograma de backoff.","operationId":"InvoicesController_retryPricing","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"Id da fatura","schema":{"type":"string"}}],"responses":{"200":{"description":"Itens re-disparados","content":{"application/json":{"schema":{"type":"object","properties":{"retried":{"description":"Quantos itens pendentes foram re-disparados agora","type":"integer"}},"required":["retried"]}}}},"404":{"description":"Fatura não encontrada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Retentar o pricing agora","tags":["Faturas"]}},"/v1/invoices/{invoiceId}/items/{itemId}/value":{"post":{"description":"Destrava um item aguardando valor com o montante informado (pricingSource: manual). Quando todos os itens fecham, a fatura vai a ready e é emitida.","operationId":"InvoicesController_manualValue","parameters":[{"name":"invoiceId","required":true,"in":"path","description":"Id da fatura","schema":{"type":"string"}},{"name":"itemId","required":true,"in":"path","description":"Id do item aguardando valor","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"amount":{"description":"Valor do item em centavos — destrava a fatura retida","type":"integer","minimum":0,"exclusiveMinimum":false},"description":{"description":"Linha da fatura, opcional","type":"string","maxLength":300,"nullable":true}},"required":["amount"]}}}},"responses":{"200":{"description":"Fatura após o destravamento","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da fatura","type":"string","format":"uuid"},"subscriptionId":{"description":"Assinatura dona da fatura","type":"string","format":"uuid"},"cycle":{"description":"Ciclo da assinatura que esta fatura representa","type":"integer"},"status":{"description":"Estado: awaiting_value é a fatura retida aguardando valor do seu endpoint","type":"string","enum":["draft","awaiting_value","ready","issued","paid","overdue","canceled"]},"dueDate":{"description":"Vencimento (YYYY-MM-DD) — o chargeDay da assinatura","type":"string"},"paymentMethod":{"description":"Método de pagamento desta fatura","type":"string"},"installments":{"description":"Parcelas no cartão — nulo quando à vista ou método sem parcela","type":"integer","nullable":true},"totalCents":{"description":"Total em centavos — nulo enquanto houver item aguardando valor","type":"integer","nullable":true},"gatewayInvoiceId":{"description":"Id da cobrança no seu gateway, após a emissão","type":"string","nullable":true},"issuedAt":{"description":"Quando foi emitida no gateway","type":"string","format":"date-time","nullable":true},"paidAt":{"description":"Quando foi paga","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi gerada","type":"string","format":"date-time"},"items":{"description":"Itens da fatura, com snapshot de preço e desconto","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do item","type":"string","format":"uuid"},"productId":{"description":"Produto do catálogo","type":"string","format":"uuid"},"productName":{"description":"Nome congelado na geração","type":"string"},"pricingSource":{"description":"De onde o valor veio","type":"string","enum":["table","endpoint","manual"]},"pricingStatus":{"description":"pending = aguardando valor","type":"string","enum":["pending","priced","skipped"]},"months":{"description":"Meses cobertos pelo ciclo","type":"integer"},"monthlyPriceCents":{"description":"Preço mensal congelado — nulo em item variável","type":"integer","nullable":true},"discountPercent":{"description":"Desconto aplicado pela régua neste ciclo","type":"integer","nullable":true},"amountCents":{"description":"Valor final do item — congelado, auditável","type":"integer","nullable":true},"description":{"description":"A linha que o assinante lê","type":"string","nullable":true}},"required":["id","productId","productName","pricingSource","pricingStatus","months","monthlyPriceCents","discountPercent","amountCents","description"]}},"pricingAttempts":{"description":"Histórico cru das chamadas ao seu endpoint de preço","type":"array","items":{"type":"object","properties":{"attempt":{"description":"Número da tentativa","type":"integer"},"url":{"description":"URL chamada","type":"string"},"outcome":{"description":"Resultado da chamada ao seu endpoint","type":"string","enum":["ok","skip","timeout","http_error","invalid_response","over_cap"]},"responseStatus":{"description":"HTTP status devolvido, quando houve resposta","type":"integer","nullable":true},"latencyMs":{"description":"Latência da chamada","type":"integer","nullable":true},"responseBody":{"description":"Corpo cru da resposta — é com isso que seu time debuga","type":"string","nullable":true},"createdAt":{"description":"Quando a tentativa aconteceu","type":"string","format":"date-time"}},"required":["attempt","url","outcome","responseStatus","latencyMs","responseBody","createdAt"]}}},"required":["id","subscriptionId","cycle","status","dueDate","paymentMethod","installments","totalCents","gatewayInvoiceId","issuedAt","paidAt","createdAt","items","pricingAttempts"]}}}},"409":{"description":"Item não está aguardando valor","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Informar valor manualmente","tags":["Faturas"]}},"/v1/integration":{"get":{"description":"Secret vigente (últimos 4), janela de graça de uma rotação em curso e o webhook de alertas.","operationId":"IntegrationController_status","parameters":[],"responses":{"200":{"description":"Estado da integração","content":{"application/json":{"schema":{"type":"object","properties":{"secretLastFour":{"description":"Últimos 4 caracteres do secret de integração vigente","type":"string"},"previousSecretExpiresAt":{"description":"Até quando o secret anterior ainda é aceito (janela de graça da rotação)","type":"string","format":"date-time","nullable":true},"alertWebhookUrl":{"description":"URL que recebe os alertas e eventos, se configurada","type":"string","nullable":true}},"required":["secretLastFour","previousSecretExpiresAt","alertWebhookUrl"]}}}}},"security":[{"bearer":[]}],"summary":"Estado da integração","tags":["Integração"]}},"/v1/integration/secret/rotate":{"post":{"description":"O novo secret assina na hora; o anterior segue aceito por 24 horas — rotação sem downtime.","operationId":"IntegrationController_rotateSecret","parameters":[],"responses":{"200":{"description":"Novo secret em claro — guarde agora","content":{"application/json":{"schema":{"type":"object","properties":{"secret":{"description":"O novo secret em claro — o anterior segue aceito por 24 horas","type":"string"},"previousSecretExpiresAt":{"description":"Quando o secret anterior deixa de ser aceito","type":"string","format":"date-time"}},"required":["secret","previousSecretExpiresAt"]}}}}},"security":[{"bearer":[]}],"summary":"Gerar novo secret de integração","tags":["Integração"]}},"/v1/integration/alert-webhook":{"put":{"description":"Para onde avisamos na hora: endpoint de preço falhando, fatura retida, cobrança recusada. null desliga.","operationId":"IntegrationController_setAlertWebhook","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"URL https do seu webhook — null desliga","type":"string","format":"uri","nullable":true}},"required":["url"]}}}},"responses":{"200":{"description":"Estado atualizado","content":{"application/json":{"schema":{"type":"object","properties":{"secretLastFour":{"description":"Últimos 4 caracteres do secret de integração vigente","type":"string"},"previousSecretExpiresAt":{"description":"Até quando o secret anterior ainda é aceito (janela de graça da rotação)","type":"string","format":"date-time","nullable":true},"alertWebhookUrl":{"description":"URL que recebe os alertas e eventos, se configurada","type":"string","nullable":true}},"required":["secretLastFour","previousSecretExpiresAt","alertWebhookUrl"]}}}}},"security":[{"bearer":[]}],"summary":"Configurar o webhook de alertas","tags":["Integração"]}},"/v1/integration/api-keys":{"post":{"description":"A chave em claro aparece UMA vez na resposta.","operationId":"IntegrationController_createApiKey","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Nome da chave (ex.: producao, staging)","type":"string","minLength":1,"maxLength":120}},"required":["name"]}}}},"responses":{"201":{"description":"Chave criada","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da chave","type":"string","format":"uuid"},"name":{"description":"Nome dado à chave","type":"string"},"lastUsedAt":{"description":"Último uso","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criada","type":"string","format":"date-time"},"plainKey":{"description":"A chave em claro — mostrada UMA vez, guarde agora","type":"string"}},"required":["id","name","lastUsedAt","createdAt","plainKey"]}}}}},"security":[{"bearer":[]}],"summary":"Criar API key","tags":["Integração"]},"get":{"description":"Sem o valor em claro — só nome, uso e criação.","operationId":"IntegrationController_listApiKeys","parameters":[],"responses":{"200":{"description":"Chaves ativas","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador da chave","type":"string","format":"uuid"},"name":{"description":"Nome dado à chave","type":"string"},"lastUsedAt":{"description":"Último uso","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criada","type":"string","format":"date-time"}},"required":["id","name","lastUsedAt","createdAt"]}}}}}},"security":[{"bearer":[]}],"summary":"Listar API keys ativas","tags":["Integração"]}},"/v1/integration/api-keys/{apiKeyId}":{"delete":{"description":"A chave para de autenticar imediatamente.","operationId":"IntegrationController_revokeApiKey","parameters":[{"name":"apiKeyId","required":true,"in":"path","description":"Id da chave","schema":{"type":"string"}}],"responses":{"200":{"description":"Chave revogada","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"description":"Identificador da chave","type":"string","format":"uuid"},"name":{"description":"Nome dado à chave","type":"string"},"lastUsedAt":{"description":"Último uso","type":"string","format":"date-time","nullable":true},"createdAt":{"description":"Quando foi criada","type":"string","format":"date-time"}},"required":["id","name","lastUsedAt","createdAt"]}}}},"401":{"description":"Chave não encontrada ou já revogada","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"]}}}}},"security":[{"bearer":[]}],"summary":"Revogar API key","tags":["Integração"]}},"/v1/events":{"get":{"description":"Tudo que o motor conta pra você vira evento persistido — este endpoint devolve o histórico com cursor, inclusive o que o seu webhook perdeu. O corpo de cada evento é idêntico ao entregue no webhook.","operationId":"EventsController_list","parameters":[{"name":"cursor","required":false,"in":"query","description":"Id do último evento da página anterior — devolvemos os seguintes","schema":{"description":"Id do último evento da página anterior — devolvemos os seguintes","type":"string","format":"uuid"}},{"name":"type","required":false,"in":"query","description":"Filtra por tipo de evento","schema":{"description":"Filtra por tipo de evento","type":"string"}},{"name":"from","required":false,"in":"query","description":"Só eventos a partir deste instante","schema":{"description":"Só eventos a partir deste instante","type":"string","format":"date-time"}},{"name":"to","required":false,"in":"query","description":"Só eventos até este instante","schema":{"description":"Só eventos até este instante","type":"string","format":"date-time"}},{"name":"limit","required":false,"in":"query","description":"Tamanho da página (padrão 50)","schema":{"description":"Tamanho da página (padrão 50)","type":"integer","minimum":1,"exclusiveMinimum":false,"maximum":200,"exclusiveMaximum":false}}],"responses":{"200":{"description":"Página de eventos, mais antiga primeiro","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"description":"Eventos em ordem de ocorrência","type":"array","items":{"type":"object","properties":{"id":{"description":"Identificador do evento — também é o cursor","type":"string","format":"uuid"},"type":{"description":"Tipo do evento (invoice.issued, invoice.paid, invoice.overdue, invoice.held, pricing.failing, pricing.recovered, subscription.canceled)","type":"string"},"occurredAt":{"description":"Quando o evento aconteceu","type":"string","format":"date-time"},"data":{"description":"Payload do evento, o mesmo corpo entregue no webhook","type":"object","additionalProperties":{}},"delivery":{"description":"Situação da entrega no seu webhook","type":"object","properties":{"status":{"description":"pending, delivered, failed ou skipped (sem webhook cadastrado)","type":"string"},"attempts":{"description":"Tentativas de entrega já feitas","type":"integer"},"deliveredAt":{"description":"Quando o webhook aceitou","type":"string","format":"date-time","nullable":true},"lastError":{"description":"Último erro de entrega, sem tradução","type":"string","nullable":true}},"required":["status","attempts","deliveredAt","lastError"]}},"required":["id","type","occurredAt","data","delivery"]}},"nextCursor":{"description":"Cursor da próxima página — nulo quando acabou","type":"string","format":"uuid","nullable":true}},"required":["data","nextCursor"]}}}}},"security":[{"bearer":[]}],"summary":"Listar eventos (replay completo)","tags":["Eventos"]}},"/v1/integration/alert-webhook/test":{"post":{"description":"Envia um evento de exemplo assinado para o webhook cadastrado e devolve o resultado cru — status, corpo e latência.","operationId":"EventsController_testAlertWebhook","parameters":[],"responses":{"200":{"description":"Resultado cru da entrega de teste","content":{"application/json":{"schema":{"type":"object","properties":{"delivered":{"description":"Se o seu endpoint aceitou (2xx)","type":"boolean"},"responseStatus":{"description":"Status HTTP devolvido — nulo quando nem respondeu","type":"integer","nullable":true},"responseBody":{"description":"Corpo cru da resposta, truncado","type":"string","nullable":true},"latencyMs":{"description":"Tempo de resposta em milissegundos","type":"integer"},"error":{"description":"Erro de rede/timeout, sem tradução","type":"string","nullable":true}},"required":["delivered","responseStatus","responseBody","latencyMs","error"]}}}},"409":{"description":"Nenhum webhook de alertas cadastrado","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"description":"Stable machine-readable error code (e.g. identity.email_already_in_use)","type":"string"},"title":{"description":"Error class name","type":"string"},"status":{"description":"HTTP status code","type":"integer"},"detail":{"description":"Human-readable message, safe to display to end users","type":"string"},"requestId":{"description":"Correlation id — send it to support to locate the full trail","type":"string","nullable":true},"meta":{"description":"Structured details safe for the frontend (field errors, ids)","type":"object","additionalProperties":{}}},"required":["type","title","status","detail","requestId"],"example":{"type":"engine.integration_settings_missing","title":"Conflito","status":409}}}}}},"security":[{"bearer":[]}],"summary":"Testar o webhook de alertas","tags":["Eventos","Integração"]}}},"info":{"title":"Revtriever Motor de Cobrança","description":"API pública do motor de cobrança por assinatura. Autentique com `Authorization: Bearer rk_…` (API key). Todo POST que cria recurso exige o header `Idempotency-Key`. Valores monetários são sempre centavos inteiros. Erros seguem problem+json: `{ type, title, status, detail, requestId, meta? }`.","version":"1.0.0","contact":{}},"tags":[{"name":"Produtos","description":"Catálogo: preço mensal fixo ou variável via endpoint, espelhado no gateway"},{"name":"Planos","description":"A oferta: período, método padrão, parcelamento e a régua de descontos — versionada"},{"name":"Assinaturas","description":"O vínculo cliente↔plano: criação, customização por assinante, preview e cancelamento"},{"name":"Faturas","description":"O que o ciclo gerou: acompanhamento e os destravamentos da fatura retida"},{"name":"Eventos","description":"Tudo que o motor conta, com replay por cursor"},{"name":"Integração","description":"Secret HMAC, webhook de alertas e API keys"}],"servers":[],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http"}},"schemas":{}}}