{"openapi":"3.1.0","info":{"title":"ribbo API","version":"1.0.0","description":"API de integração da **ribbo**: cobrança recorrente para quem constrói SaaS.\n\nCom esta API o seu sistema (app, site, backend) lê e gerencia assinaturas, consulta as\ncapacidades (entitlements) de cada cliente, processa estornos, gera links de pagamento e\nrecebe **webhooks assinados** a cada evento de cobrança. A recorrência é gerida pela ribbo:\nvocê não fala com o gateway.\n\n> **A assinatura nasce no checkout da ribbo.** Não existe endpoint para criar assinatura: o\n> cliente assina pela página de checkout (o número do cartão nunca toca o seu servidor). A API\n> serve para ler e operar as assinaturas que já existem.\n\n## Autenticação\nTodas as chamadas usam **Bearer token** com a sua API key (prefixo `bk_`), no header:\n\n```\nAuthorization: Bearer bk_sua_chave_aqui\n```\n\nGere e revogue chaves no painel (**Configurações → API keys**). A chave em claro é mostrada\n**uma única vez**. Cada chave tem um **escopo**: `read` (só leitura) ou `write` (leitura +\nações que movem dinheiro ou estado, como trocar plano, estornar, cancelar, cobrar agora). Uma\nchave `read` chamando uma rota de escrita recebe **403 `insufficient_scope`**.\n\n## Convenções\n- **Dinheiro sempre em centavos** (inteiro): `amount_cents: 1990` = R$ 19,90. Nunca há float.\n- **IDs com prefixo** (ULID): `sub_…` (assinatura), `cus_…` (cliente), `inv_…` (fatura),\n  `pay_…` (pagamento), `ord_…` (pedido avulso), `evt_…` (evento), `plan_…` (plano),\n  `offer_…` (oferta). O plano é identificado por `plan_id` (com `plan_name` só para exibição)\n  e a oferta por `offer_id`. O seu `external_id` do cliente é a chave que você controla e usa\n  para casar com o seu sistema.\n- **Moeda** em minúsculo: `\"brl\"`.\n- **Datas** em UTC, ISO-8601.\n- **Paginação por cursor (keyset)**: passe `?limit=` (default 100, máx 500) e `?after=<cursor>`;\n  a resposta traz `{results:[...], next: <cursor>|null}`. Pagine até `next` ser `null`.\n- **Erros**: corpo `{\"error\": \"mensagem\"}` (algumas rotas incluem `code` ou outros campos).\n  Códigos: `400` (input inválido), `401` (não autorizado), `403` (`insufficient_scope`, ou\n  `account_locked` quando a sua conta ribbo está em modo só leitura; estorno, cancelamento e edição\n  de cliente seguem liberados), `404` (não existe ou é de\n  outro tenant, indistinguíveis de propósito), `409` (conflito de estado), `422` (regra de\n  negócio), `429` (limite de requisições), `202` (aceito e enfileirado).\n- **Idempotência semântica**: as consultas são seguras de repetir; as ações de dinheiro\n  (cobrar agora, estornar) têm anti-duplicidade embutido.\n\n## Webhooks\nA ribbo envia um `POST` assinado a cada evento (ver a seção **Webhooks** abaixo). Valide a\nassinatura `X-Billing-Signature` e trate cada `X-Billing-Event-Id` de forma idempotente.\n\n> 🔑 **Regra de ouro:** o campo `entitlements` vem **cheio mesmo quando a assinatura está\n> `suspended`/`past_due`/`canceled`**. Decida o acesso do cliente por `data.status`, **nunca**\n> pela presença de `entitlements`, senão você re-libera acesso a um inadimplente.\n","contact":{"name":"ribbo"}},"paths":{"/v1/customers/{external_id}":{"post":{"operationId":"customers_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Edita os campos INFORMADOS (nome/e-mail/telefone; `null`/ausente = não mexe) do cliente (por `external_id`): local + sync no gateway (e-mail, nome e telefone) + AuditLog. `doc` e `external_id` NÃO são editáveis (identidade fiscal / chave da integração). O cadastro precisa terminar com um **celular válido**: `phone` em formato internacional E.164 (ex.: `+5511999999999`; número brasileiro sem `+` vira `+55`). Cliente antigo sem telefone: qualquer edição exige informar um. 404 se é de outro tenant ou não existe; 422 se o e-mail é inválido/em uso, o telefone é inválido ou falta o celular.","summary":"Atualizar o cadastro de um cliente (nome, e-mail, telefone)","parameters":[{"in":"path","name":"external_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerUpdateReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CustomerUpdateReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CustomerUpdateReq"}}}},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerUpdateResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"E-mail inválido ou em uso (`já existe um cliente com esse e-mail neste tenant`), `telefone inválido` ou `informe o celular do cliente`."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/customers/{external_id}/email":{"post":{"operationId":"customers_email_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Atualiza o e-mail do cliente (por `external_id`): local + sync no gateway + AuditLog (a MESMA regra do painel). 404 se é de outro tenant ou não existe; 422 se o e-mail é inválido (`{\"error\": \"...\"}`).","summary":"Atualizar o e-mail de um cliente","parameters":[{"in":"path","name":"external_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerEmailReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CustomerEmailReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CustomerEmailReq"}}},"required":true},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerEmailResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"E-mail inválido ou já usado por outro cliente do tenant."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/customers/{external_id}/payments":{"get":{"operationId":"customers_payments_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Os pagamentos do cliente (por `external_id`), recorrentes e avulsos, em lotes. Pagine até `next` vir `null`: pegue `next`, mande em `?after=`, repita. Keyset (ordenado por id ULID = cronológico) — aguenta históricos longos sem degradar. 404 se o cliente não existe.","summary":"Histórico de pagamentos de um cliente — keyset paginado","parameters":[{"in":"query","name":"after","schema":{"type":"string"},"description":"cursor da página anterior (o campo `next` da resposta)"},{"in":"path","name":"external_id","schema":{"type":"string"},"required":true},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"tamanho da página (default 100, máx 500)"}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCustomerPaymentsResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/customers/{external_id}/subscriptions":{"get":{"operationId":"customers_subscriptions_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Todas as assinaturas do cliente (por `external_id`), em QUALQUER status (inclusive `canceled`) — o receptor decide por `status`, nunca pela presença de `entitlements`. Mesmo shape do webhook e do `GET /v1/subscriptions/{id}`, sem `last_payment`/`tracking` (omitidos nas listas). 404 se o cliente é de outro tenant ou não existe.","summary":"Listar as assinaturas de um cliente","parameters":[{"in":"path","name":"external_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCustomerSubsResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/entitlements":{"get":{"operationId":"entitlements_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Lista as assinaturas do cliente (identificado por `external_id` OU `email`) que não estão `canceled`, cada uma com os entitlements do plano, e devolve `merged_entitlements`: a união das capacidades das assinaturas `active`, `trialing` e `past_due` (uma `suspended` aparece na lista mas não soma). Os entitlements vêm sempre do catálogo atual: editar o plano reflete aqui na hora. Cliente inexistente = 200 com `customer_id: null` (nunca 404). Informe `external_id` (preferido; `email` em query vira log). Um dos dois é obrigatório (400 sem nenhum).","summary":"Entitlements de um cliente (o que ele pode usar AGORA)","parameters":[{"in":"query","name":"email","schema":{"type":"string"},"description":"Alternativa ao external_id (evite — PII em query string/logs)."},{"in":"query","name":"external_id","schema":{"type":"string"},"description":"O id do cliente no SEU app / SaaS (Customer.external_id). Preferido."}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntitlementsResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Nem `external_id` nem `email` informados."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/orders/{order_id}/payment-link":{"get":{"operationId":"orders_payment_link_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. A 2ª via / re-acesso ao QR Pix de um pedido pendente — compra avulsa OU adiantamento de renovação —, para o sistema reenviar ao cliente pagar. Reusa `Order.access_token`; NUNCA expõe o id do pedido. 404 se é de outro tenant ou não existe; 409 se não há Pix pendente para reabrir (`{\"error\": \"pedido sem Pix pendente para reabrir\"}`).","summary":"Link de re-acesso ao Pix de um pedido (avulso ou adiantamento)","parameters":[{"in":"path","name":"order_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderPaymentLinkResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"O pedido não tem Pix pendente para reabrir."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/payments/{payment_id}":{"get":{"operationId":"payments_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. O pagamento por id, com a decomposição em itens (plano/bump/juros) e o estado de estorno. 404 se é de outro tenant ou não existe.","summary":"Detalhe de um pagamento (com itens)","parameters":[{"in":"path","name":"payment_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentDetailResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/payments/{payment_id}/refund":{"post":{"operationId":"payments_refund_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write** (liberado mesmo com a conta em modo só leitura). Estorna o `Payment` (por id). `reason` é OBRIGATÓRIO (≤300). `amount_cents` em centavos (parcial = menor que o pago; Pix só aceita estorno TOTAL, e um segundo estorno parcial na mesma cobrança só vale nos gateways que somam estornos: Stone/Pagar.me e Stripe). `revoke`: `subscription` (cancela a assinatura) | `grant` (revoga a concessão do pedido) | `none` (só devolve o dinheiro). **Se OMITIDO, o padrão é REVOGAR o acesso apropriado ao pagamento** (fatura → cancela a assinatura; pedido → revoga a concessão) — mande `revoke:\"none\"` para só devolver sem revogar. Se o estorno desfizer uma extensão/renovação, o tempo concedido é REVERTIDO automaticamente. Anti-2x embutido (o serviço nunca estorna duas vezes). 404 se o pagamento é de outro tenant ou não existe.","summary":"Estornar um pagamento (total ou parcial)","parameters":[{"in":"path","name":"payment_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRefundReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ApiRefundReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ApiRefundReq"}}},"required":true},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRefundResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`amount_cents` ausente ou não inteiro."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRefundRunwayResp"}}},"description":"O estorno atinge uma fatura que financiou runway pré-pago (reenvie com `confirm_runway: true`), ou o estorno foi recusado (`{level: \"error\", message}`): motivo ausente ou acima de 300 caracteres, valor fora de 1 centavo até o saldo estornável, pagamento que não está `paid`, parcial de Pix, `revoke` incoerente com o pagamento, ou recusa do gateway."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/referrals/link":{"get":{"operationId":"referrals_link_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Get-ou-create do código estável do cliente-indicador + a recompensa configurada e o progresso das indicações. Informe `external_id` OU `email` (400 sem nenhum). `{active:false}` se o tenant não tem programa de indicação ativo; 404 se o cliente não existe.","summary":"Link/código de indicação de um cliente + progresso","parameters":[{"in":"query","name":"email","schema":{"type":"string"},"description":"e-mail do cliente (alternativa ao external_id)"},{"in":"query","name":"external_id","schema":{"type":"string"},"description":"id do cliente no seu app / SaaS (prefira este)"}],"tags":["Integração — Indicações"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralLinkResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Nem `external_id` nem `email` informados."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Cliente não encontrado."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/renewal-campaigns/{campaign_id}/link":{"get":{"operationId":"renewal_campaigns_link_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write** (cria o link, um documento pagável). Devolve (cria-ou-obtém, idempotente) o link de renovação daquele cliente na campanha — use no botão 'antecipar renovação' do seu app. 400 sem `external_id`; 404 se a campanha não existe ou está inativa, se o cliente não existe ou se ele não está no público da campanha.","summary":"Link de renovação de UM cliente (botão da plataforma)","parameters":[{"in":"path","name":"campaign_id","schema":{"type":"string"},"required":true},{"in":"query","name":"external_id","schema":{"type":"string"},"description":"O id do cliente no SEU app / SaaS (Customer.external_id).","required":true}],"tags":["Integração — Renovação por campanha"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenewalCampaignClientLink"},"examples":{"Exemplo":{"value":{"token":"aBcD…","url":"https://checkout.seudominio.com/renovar/aBcD…","price_cents":8400,"bonus_cycles":3,"bonus_unit":"month","status":"open","starts_at":null,"offer_id":"offer_01KZ9R...","plan_id":"plan_01KZ9R...","product_id":"prod_01KZ9R..."},"summary":"exemplo"}}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`external_id` ausente."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/renewal-campaigns/{campaign_id}/links":{"get":{"operationId":"renewal_campaigns_links_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Puxa os links já gerados, em lotes. Pagine até `next` vir `null`: pegue `next`, mande em `?after=`, repita. Keyset (não offset) — aguenta centenas de milhares sem degradar. Leitura (qualquer scope). 400 se o cursor `after` é inválido; 404 se a campanha não existe.","summary":"Todos os links da campanha (lote, para e-mailar) — keyset paginado","parameters":[{"in":"query","name":"after","schema":{"type":"string"},"description":"cursor da página anterior (o campo `next` da resposta)"},{"in":"path","name":"campaign_id","schema":{"type":"string"},"required":true},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"tamanho da página (default 100, máx 500)"}],"tags":["Integração — Renovação por campanha"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenewalCampaignLinksPage"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Cursor `after` inválido."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions":{"get":{"operationId":"subscriptions_list","description":"Auth: `Authorization: Bearer <tenant_api_key>`. TODAS as assinaturas do tenant, em lotes. Filtros opcionais: `status` (um ou vários por vírgula) e `offer_id`. Pagine até `next` vir `null`: pegue `next`, mande em `?after=`, repita. Keyset (id ULID = cronológico), aguenta bases grandes sem degradar. Mesmo shape do webhook e do `GET /v1/subscriptions/{id}`, sem `last_payment`/`tracking` (omitidos nas listas). Não há POST: a assinatura nasce só no checkout.","summary":"Listar as assinaturas do tenant — keyset paginado","parameters":[{"in":"query","name":"after","schema":{"type":"string"},"description":"cursor da página anterior (o campo `next` da resposta)"},{"in":"query","name":"limit","schema":{"type":"integer"},"description":"tamanho da página (default 100, máx 500)"},{"in":"query","name":"offer_id","schema":{"type":"string"},"description":"filtra pela oferta (offer_01...)"},{"in":"query","name":"status","schema":{"type":"string"},"description":"filtra por status; um ou vários por vírgula (ex.: `active` ou `active,past_due`). Valor fora do conjunto conhecido ⟹ 400."}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiSubscriptionsListResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`status` fora do conjunto conhecido (o corpo traz `accepted`)."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}":{"get":{"operationId":"subscriptions_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. O estado ATUAL da assinatura por id — em QUALQUER status (`canceled`/`suspended` inclusive), para o sistema reconciliar quando perde um webhook. Mesmo shape do webhook (`subscription_event_payload`). O receptor decide por `status`, nunca pela presença de `entitlements`. 404 se é de outro tenant ou não existe (indistinguíveis por design).","summary":"Detalhe de UMA assinatura (estado atual, qualquer status)","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPayload"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/cancel":{"post":{"operationId":"subscriptions_cancel_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write** (liberado mesmo com a conta em modo só leitura). Dois modos:\n\n- **Imediato** (padrão): a assinatura vai para o estado TERMINAL `canceled`. RECUSA (422) enquanto houver um QR Pix pagável (cancelar às cegas arriscaria o cliente pagar sobre uma assinatura terminal). Idempotente: já cancelada devolve 200.\n- **No fim do período** (`at_period_end: true`): AGENDA o cancelamento — o acesso continua até o fim do período pago e o billing run não renova. É **REVERSÍVEL** por `POST /v1/subscriptions/{id}/cancel/undo` enquanto a assinatura segue viva. Só `active`, `trialing` e `past_due` agendam; um teste SEM cartão (sem próxima cobrança) não tem fim de período e é cancelado na hora (resposta `{status: canceled}`).\n\n`reason` opcional (≤300) vai ao e-mail de cancelamento. 404 se é de outro tenant ou não existe.","summary":"Cancelar uma assinatura (imediato ou no fim do período)","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCancelReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ApiCancelReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ApiCancelReq"}}}},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiCancelResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Há um QR Pix ainda pagável, ou o estado atual não permite cancelar/agendar."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/cancel-plan-change":{"post":{"operationId":"subscriptions_cancel_plan_change_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Cancela a troca de plano agendada; a assinatura volta sem `pending_offer`. 422 se não há troca agendada; 404 se a assinatura é de outro tenant/inexistente.","summary":"Cancelar uma troca de plano AGENDADA","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelPlanChangeResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanChangeError"}}},"description":"Não há troca de plano agendada."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/cancel/undo":{"post":{"operationId":"subscriptions_cancel_undo_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Desfaz o cancelamento AGENDADO (`at_period_end`) — a assinatura volta a renovar normalmente. Só vale enquanto está agendado e a assinatura segue viva (NÃO ressuscita uma já `canceled`, nem afeta um cancelamento imediato). Emite `subscription.updated`. 422 se não há cancelamento agendado; 404 se é de outro tenant ou não existe.","summary":"Desfazer um cancelamento agendado","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiUndoCancelResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Não há cancelamento agendado para desfazer."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/change-plan":{"post":{"operationId":"subscriptions_change_plan_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Troca a assinatura (só `active` ou `trialing`) para a `offer_id` alvo (`offer_01...`). Mesmo intervalo: mais caro = upgrade IMEDIATO com a proração cobrada no cartão salvo; mesmo preço = troca imediata sem cobrar; mais barato = AGENDADO para o fim do período (veja `pending_offer`). Intervalo diferente: se o valor anualizado sobe, a troca é imediata (mensal para anual cobra o anual menos o crédito do período; anual para mensal vira tempo de crédito, sem cobrar); se cai ou empata, é agendada. Trocas que cobram exigem cartão salvo: numa assinatura Pix elas são agendadas. Proração abaixo do mínimo do gateway: a troca é aplicada sem cobrar. Oferta de outro gateway: gera um link de pagamento no gateway novo (o cartão salvo não atravessa gateways). 400 sem `offer_id`; 404 se a sub ou a oferta são de outro tenant/inexistentes; 422 se a troca é inválida (`{\"error\": \"...\"}`).","summary":"Trocar o plano de uma assinatura (upgrade/downgrade)","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ChangePlanReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ChangePlanReq"}}},"required":true},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePlanResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`offer_id` ausente."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Troca de plano inválida (regra de negócio)."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/charge-now":{"post":{"operationId":"subscriptions_charge_now_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Roda AGORA o billing run desta assinatura, sem esperar a passada diária. Ele só cobra o que já VENCEU (`next_billing_at` no passado; numa assinatura Pix, emite o QR a partir de 3 dias antes): não antecipa um ciclo futuro, não encerra um teste antes da hora e não adianta a próxima tentativa da régua. Quando cobra, é no cartão salvo (Pix: emite o QR). Diferente do painel, que nunca cobra o cartão (gera link de pagamento), a API cobra direto. A anti-cobrança-dupla/idempotência é do próprio billing run: chamar duas vezes NÃO cobra duas vezes. Responde 202 (enfileirado; não quer dizer que houve cobrança, acompanhe pelos webhooks `invoice.paid`/`invoice.payment_failed`). 404 se é de outro tenant ou não existe. 409 se a assinatura não está numa situação cobrável (só `active`, `trialing` e `past_due` são; o corpo traz o `status` atual) ou se as renovações da conta estão pausadas.","summary":"Cobrar agora (enfileira o billing run da assinatura)","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiChargeNowResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Assinatura fora da janela de cobrança (`status` no corpo) ou renovações da conta pausadas."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/gateway-events":{"get":{"operationId":"subscriptions_gateway_events_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Os eventos que o GATEWAY respondeu nas cobranças desta assinatura (aprovação/recusa/estorno/chargeback) — feature B. Sem PII nem segredo. Teto de 200 eventos (`apps/gateways/queries.py`); sem paginação (uma sub tem poucos eventos). 404 se é de outro tenant ou não existe.","summary":"Timeline do gateway de uma assinatura (auditoria)","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionGatewayEventsResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/payment-link":{"get":{"operationId":"subscriptions_payment_link_retrieve","description":"Auth: `Authorization: Bearer <tenant_api_key>`. O link público de pagamento da fatura EM ABERTO desta assinatura (feature C), para o sistema distribuir ao cliente. NUNCA expõe id de invoice/assinatura. 404 se é de outro tenant ou não existe; 409 se não há fatura em aberto (`{\"error\": \"nenhuma fatura em aberto\"}`).","summary":"Link de pagamento da fatura em aberto de uma assinatura","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Entitlements e assinaturas"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionPaymentLinkResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Não há fatura em aberto."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/payment-method-link":{"post":{"operationId":"subscriptions_payment_method_link_create","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Gera um link OPACO que o cliente abre para trocar o CARTÃO (ou Pix↔cartão, se a oferta permitir) — SEM cobrança. Use no botão 'alterar forma de pagamento' da área de assinatura do seu app. Expira em 7 dias, SINGLE-USE. Scope **write**. No Asaas o cartão só é capturado na página hospedada de um pagamento: a troca para um cartão novo acontece ao pagar uma fatura. 404 se é de outro tenant ou não existe; 409 se a assinatura está `canceled`/`pending_first_payment` ou em teste sem cartão.","summary":"Gerar link de troca de forma de pagamento","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentMethodLinkResp"},"examples":{"Exemplo":{"value":{"token":"aBcD…","url":"https://checkout.seudominio.com/forma-de-pagamento/aBcD…","expires_at":"2026-08-17T12:00:00Z","status":"open"},"summary":"exemplo"}}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Assinatura terminal/não originada, ou em teste sem cartão."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/remove-coupon":{"post":{"operationId":"subscriptions_remove_coupon_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Os ciclos FUTUROS deixam de ser descontados; o registro da venda permanece (só para de afetar a renovação). Devolve quantos resgates foram desativados. 404 se é de outro tenant ou não existe.","summary":"Remover o cupom de uma assinatura","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRemoveCouponResp"}}},"description":""},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/renewal-link":{"post":{"operationId":"subscriptions_renewal_link_create","description":"Auth: `Authorization: Bearer <tenant_api_key>`. Gera um link de renovação da assinatura (o cliente abre e paga, e o período é ESTENDIDO). Renova sempre a PRÓPRIA oferta da assinatura: `offer_id` é opcional e, se enviado, tem de ser a oferta atual (para mudar de plano use `change-plan`). `price_cents` opcional (inteiro ≥ 1; cortesia/100% off NÃO é suportada); sem ele, o preço é o do próximo ciclo já com o cupom ativo. Expira em 7 dias. Scope **write**. 404 se é de outro tenant ou não existe.","summary":"Gerar link de renovação avulsa de uma assinatura","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRenewalLinkReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ApiRenewalLinkReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ApiRenewalLinkReq"}}}},"security":[{"tenantApiKey":[]}],"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiRenewalLinkResp"},"examples":{"Exemplo":{"value":{"token":"aBcD…","url":"https://checkout.seudominio.com/renovar/aBcD…","price_cents":8400,"expires_at":"2026-08-14T12:00:00Z","status":"active"},"summary":"exemplo"}}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`price_cents` inválido ou `offer_id` inexistente/de outro tenant."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"`offer_id` diferente da oferta da assinatura, ou validação do link."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/subscriptions/{subscription_id}/reschedule":{"post":{"operationId":"subscriptions_reschedule_create","description":"Auth: `Authorization: Bearer <tenant_api_key>` com scope **write**. Move a próxima cobrança (= fim do ciclo atual) para `next_billing_at` (ISO 8601, no FUTURO). NÃO cobra — só muda QUANDO cobra; a cadência passa a seguir a nova data. Emite `subscription.updated`. 400 se a data é inválida (`code: data_invalida`) ou passada (`data_passada`); 404 se é de outro tenant; 422 se o status não permite (`status`); 409 se há uma cobrança/QR Pix em aberto neste ciclo (`fatura_em_voo`).","summary":"Reagendar a data da próxima cobrança de uma assinatura","parameters":[{"in":"path","name":"subscription_id","schema":{"type":"string"},"required":true}],"tags":["Integração — Gerenciamento"],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescheduleReq"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/RescheduleReq"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/RescheduleReq"}}},"required":true},"security":[{"tenantApiKey":[]}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescheduleResp"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Data inválida ou no passado."},"401":{"description":"Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"403":{"description":"`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Não existe ou pertence a outro tenant (indistinguíveis de propósito).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Há uma cobrança ou QR Pix em aberto neste ciclo."},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"O status da assinatura não permite reagendar."},"429":{"description":"Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"schemas":{"ApiCancelReq":{"type":"object","properties":{"reason":{"type":"string","description":"motivo do cancelamento (≤300)"},"at_period_end":{"type":"boolean","default":false,"description":"true = agenda o cancelamento p/ o fim do período (reversível); false/omitido = cancela imediatamente (terminal)"}}},"ApiCancelResp":{"type":"object","properties":{"status":{"type":"string","description":"canceled (modo imediato)"},"ok":{"type":"boolean"},"cancel_at_period_end":{"type":"boolean","description":"true quando agendado p/ o fim do período"},"current_period_end":{"type":["string","null"],"format":"date-time","description":"quando agendado: até quando o acesso continua"}}},"ApiChargeNowResp":{"type":"object","properties":{"ok":{"type":"boolean"},"message":{"type":"string"}},"required":["message","ok"]},"ApiCustomerPaymentsResp":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/ApiPaymentRow"}},"next":{"type":["string","null"],"description":"cursor da próxima página (null=fim)"}},"required":["next","results"]},"ApiCustomerSubsResp":{"type":"object","properties":{"customer_id":{"type":"string"},"subscriptions":{"type":"array","items":{"$ref":"#/components/schemas/SubscriptionPayload"}}},"required":["customer_id","subscriptions"]},"ApiError":{"type":"object","description":"Corpo de erro padrão da API de integração (componente `ApiError`).","properties":{"error":{"type":"string","description":"mensagem legível"},"code":{"type":"string","description":"código estável, quando a rota define um"}},"required":["error"]},"ApiPaymentDetailResp":{"type":"object","properties":{"payment_id":{"type":"string"},"status":{"type":"string","description":"processing | paid | failed | refunded | chargedback"},"kind":{"type":"string","description":"recurring | one_time"},"method":{"type":"string","description":"card | pix"},"method_kind":{"type":"string"},"amount_cents":{"type":"integer"},"currency":{"type":"string"},"refunded_amount_cents":{"type":"integer"},"refund_in_flight":{"type":"boolean","description":"estorno commitado, ainda não reconciliado"},"refund_reason":{"type":"string"},"failure_code":{"type":"string","description":"motivo da recusa (ex.: insufficient_funds)"},"gateway_charge_id":{"type":"string"},"provider":{"type":"string","description":"pagarme | stripe | asaas"},"card":{"type":"object","additionalProperties":{},"description":"{brand, last4} — NUNCA o PAN"},"paid_at":{"type":["string","null"],"format":"date-time"},"reference":{"type":["object","null"],"additionalProperties":{},"description":"{type: subscription|order, id}"},"customer":{"type":["object","null"],"additionalProperties":{},"description":"{external_id, email}"},"items":{"type":"array","items":{"type":"object","additionalProperties":{}},"description":"itens da cobrança: {id, kind, amount_cents, refunded_amount_cents, refunded}"}},"required":["amount_cents","card","currency","customer","failure_code","gateway_charge_id","items","kind","method","method_kind","paid_at","payment_id","provider","reference","refund_in_flight","refund_reason","refunded_amount_cents","status"]},"ApiPaymentMethodLinkResp":{"type":"object","properties":{"token":{"type":"string"},"url":{"type":["string","null"]},"expires_at":{"type":"string","format":"date-time"},"status":{"type":"string"}},"required":["expires_at","status","token","url"]},"ApiPaymentRow":{"type":"object","properties":{"payment_id":{"type":"string"},"status":{"type":"string","description":"processing | paid | failed | refunded | chargedback"},"kind":{"type":"string","description":"recurring | one_time"},"method":{"type":"string","description":"card | pix"},"method_kind":{"type":"string"},"amount_cents":{"type":"integer"},"currency":{"type":"string"},"refunded_amount_cents":{"type":"integer"},"refund_in_flight":{"type":"boolean","description":"estorno commitado, ainda não reconciliado"},"refund_reason":{"type":"string"},"failure_code":{"type":"string","description":"motivo da recusa (ex.: insufficient_funds)"},"gateway_charge_id":{"type":"string"},"provider":{"type":"string","description":"pagarme | stripe | asaas"},"card":{"type":"object","additionalProperties":{},"description":"{brand, last4} — NUNCA o PAN"},"paid_at":{"type":["string","null"],"format":"date-time"},"reference":{"type":["object","null"],"additionalProperties":{},"description":"{type: subscription|order, id}"},"customer":{"type":["object","null"],"additionalProperties":{},"description":"{external_id, email}"}},"required":["amount_cents","card","currency","customer","failure_code","gateway_charge_id","kind","method","method_kind","paid_at","payment_id","provider","reference","refund_in_flight","refund_reason","refunded_amount_cents","status"]},"ApiRefundReq":{"type":"object","properties":{"amount_cents":{"type":"integer","description":"valor a estornar, em centavos"},"reason":{"type":"string","description":"motivo do estorno (obrigatório, ≤300)"},"revoke":{"type":"string","description":"subscription | grant | none. Se omitido, revoga o acesso apropriado (assinatura p/ fatura, concessão p/ pedido); mande none p/ não revogar"},"confirm_runway":{"type":"boolean","default":false,"description":"reenvie true quando o 422 pedir: confirma estornar uma fatura que financiou runway pré-pago"}},"required":["amount_cents","reason"]},"ApiRefundResp":{"type":"object","properties":{"level":{"type":"string","description":"success | warning"},"message":{"type":"string"}},"required":["level","message"]},"ApiRefundRunwayResp":{"type":"object","properties":{"error":{"type":"string"},"requires_confirmation":{"type":"string","description":"\"runway\""}},"required":["error","requires_confirmation"]},"ApiRemoveCouponResp":{"type":"object","properties":{"removed":{"type":"integer","description":"quantos resgates foram desativados"}},"required":["removed"]},"ApiRenewalLinkReq":{"type":"object","properties":{"offer_id":{"type":"string","description":"opcional; se enviado, a oferta ATUAL da assinatura"},"price_cents":{"type":"integer","description":"preço em centavos (≥1); default = próximo ciclo com o cupom ativo"}}},"ApiRenewalLinkResp":{"type":"object","properties":{"token":{"type":"string"},"url":{"type":["string","null"]},"price_cents":{"type":"integer"},"expires_at":{"type":"string","format":"date-time"},"status":{"type":"string"}},"required":["expires_at","price_cents","status","token","url"]},"ApiSubscriptionsListResp":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/SubscriptionPayload"}},"next":{"type":["string","null"],"description":"cursor da próxima página (null=fim)"}},"required":["next","results"]},"ApiUndoCancelResp":{"type":"object","properties":{"ok":{"type":"boolean"},"cancel_at_period_end":{"type":"boolean","description":"false após desfazer"}},"required":["cancel_at_period_end","ok"]},"CancelPlanChangeResp":{"type":"object","properties":{"subscription":{"allOf":[{"$ref":"#/components/schemas/SubscriptionPayload"}],"description":"assinatura sem o pending_offer"},"plan_change":{"type":"object","additionalProperties":{},"description":"resultado do cancelamento"}},"required":["plan_change","subscription"]},"ChangePlanReq":{"type":"object","properties":{"offer_id":{"type":"string","description":"o id da oferta ALVO (offer_01...)"},"keep_coupon":{"type":"boolean","default":false,"description":"leva o cupom ativo para a nova oferta (default: false)"}},"required":["offer_id"]},"ChangePlanResp":{"type":"object","properties":{"subscription":{"allOf":[{"$ref":"#/components/schemas/SubscriptionPayload"}],"description":"a assinatura já atualizada"},"plan_change":{"type":"object","additionalProperties":{},"description":"resultado da troca. Chaves: kind, effect, charge_cents, applies_at…"}},"required":["plan_change","subscription"]},"CustomerEmailReq":{"type":"object","properties":{"email":{"type":"string","format":"email","description":"o novo e-mail do cliente"}},"required":["email"]},"CustomerEmailResp":{"type":"object","properties":{"email":{"type":"string","description":"o e-mail já atualizado"},"notice":{"type":["string","null"],"description":"aviso não-fatal (ex.: sync do gateway)"}},"required":["email","notice"]},"CustomerUpdateReq":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string","description":"celular em E.164, ex.: +5511999999999"}}},"CustomerUpdateResp":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string"},"phone":{"type":"string"},"notice":{"type":["string","null"],"description":"sync do gateway falhou (não-fatal)"}},"required":["email","name","notice","phone"]},"EntitlementsResp":{"type":"object","properties":{"customer_id":{"type":["string","null"],"description":"null = cliente não encontrado"},"subscriptions":{"type":"array","items":{"$ref":"#/components/schemas/EntitlementsSubscriptionRow"},"description":"assinaturas não canceladas + entitlements do plano"},"merged_entitlements":{"type":"object","additionalProperties":{},"description":"a UNIÃO das capacidades de active/trialing/past_due (o que aplicar)"}},"required":["customer_id","merged_entitlements","subscriptions"]},"EntitlementsSubscriptionRow":{"type":"object","properties":{"id":{"type":"string","description":"sub_…"},"status":{"type":"string"},"plan_id":{"type":"string"},"interval":{"type":"string","description":"month | year"},"current_period_end":{"type":["string","null"],"format":"date-time"},"entitlements":{"type":"object","additionalProperties":{}}},"required":["current_period_end","entitlements","id","interval","plan_id","status"]},"GatewayEventRow":{"type":"object","properties":{"id":{"type":"string","description":"gev_…"},"provider":{"type":"string","description":"pagarme | stripe | asaas"},"kind":{"type":"string","description":"charge_card | create_pix | refund | chargeback | ..."},"outcome":{"type":"string","description":"approved | declined | error | pending | refunded | unknown"},"code":{"type":"string","description":"o nosso code (inv_/ord_) da cobrança"},"gateway_id":{"type":"string"},"detail_code":{"type":"string"},"http_status":{"type":["integer","null"]},"amount_cents":{"type":["integer","null"]},"created_at":{"type":"string","format":"date-time"}},"required":["amount_cents","code","created_at","detail_code","gateway_id","http_status","id","kind","outcome","provider"]},"OrderEventData":{"type":"object","description":"`data` dos eventos `order.*` (pagamento avulso).","properties":{"order_id":{"type":"string","example":"ord_01J…"},"status":{"type":"string"},"customer":{"type":"object","properties":{"id":{"type":"string","example":"cus_01J…"},"email":{"type":"string","format":"email"},"external_id":{"type":"string","description":"O seu ID do cliente."}}},"plan_id":{"type":"string","example":"plan_01KZ9R..."},"plan_name":{"type":"string","description":"Nome do plano, só para exibição."},"quantity":{"type":"integer"},"amount_cents":{"type":"integer"},"unit_amount_cents":{"type":"integer"},"currency":{"type":"string","example":"brl"},"paid_at":{"type":"string","format":"date-time","nullable":true},"target_subscription_id":{"type":"string","nullable":true,"description":"A assinatura que um order.paid de renovação/extensão estendeu; senão null."},"entitlements":{"type":"object","additionalProperties":true,"description":"CRU: nunca multiplicado por quantity."},"grant_days":{"type":"integer","nullable":true,"description":"CRU: nunca multiplicado por quantity."},"payment":{"type":"object","description":"O pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.","properties":{"payment_id":{"type":"string","example":"pay_01J…"},"status":{"type":"string","enum":["paid","refunded","chargedback"]},"method":{"type":"string","enum":["card","pix"]},"method_kind":{"type":"string"},"card":{"type":"object","nullable":true,"properties":{"brand":{"type":"string"},"last4":{"type":"string"}}},"amount_cents":{"type":"integer"},"paid_amount_cents":{"type":"integer"},"currency":{"type":"string","example":"brl"},"paid_at":{"type":"string","format":"date-time","nullable":true},"gateway_charge_id":{"type":"string","nullable":true},"gateway_provider":{"type":"string","example":"pagarme"}},"nullable":true},"tracking":{"type":"object","nullable":true,"description":"UTMs/click-ids do link do checkout. null sem contexto. Em renovação/upgrade vem herdada da assinatura (inherited: true). client_ip/user_agent NÃO entram (uso interno do envio ao GTM de servidor). `params` = demais parâmetros do link, sem dados pessoais.","properties":{"utm_source":{"type":"string","nullable":true},"utm_medium":{"type":"string","nullable":true},"utm_campaign":{"type":"string","nullable":true},"utm_term":{"type":"string","nullable":true},"utm_content":{"type":"string","nullable":true},"gclid":{"type":"string","nullable":true},"fbclid":{"type":"string","nullable":true},"fbc":{"type":"string","nullable":true},"fbp":{"type":"string","nullable":true},"referrer":{"type":"string","nullable":true},"landing_url":{"type":"string","nullable":true},"params":{"type":"object","additionalProperties":true,"description":"Passthrough de params arbitrários do link."},"captured_at":{"type":"string","format":"date-time"},"inherited":{"type":"boolean"}}}}},"OrderPaymentLinkResp":{"type":"object","properties":{"token":{"type":"string","description":"token opaco (access_token do pedido, não o id)"},"url":{"type":"string","description":"a URL pública que o cliente abre para pagar o Pix"},"amount_cents":{"type":"integer"},"status":{"type":"string","description":"status do pedido (pending)"}},"required":["amount_cents","status","token","url"]},"PaymentInfo":{"type":"object","description":"`last_payment`/`payment` — o pagamento liquidado (null sem cobrança). 08/2026.","properties":{"payment_id":{"type":"string"},"status":{"type":"string","description":"paid | refunded | chargedback"},"method":{"type":"string","description":"card | pix"},"method_kind":{"type":"string"},"card":{"oneOf":[{"$ref":"#/components/schemas/SubPaymentMethod"},{"type":"null"}]},"amount_cents":{"type":"integer"},"paid_amount_cents":{"type":"integer"},"currency":{"type":"string"},"paid_at":{"type":["string","null"],"format":"date-time"},"gateway_charge_id":{"type":["string","null"]},"gateway_provider":{"type":"string"}},"required":["amount_cents","card","currency","gateway_charge_id","gateway_provider","method","method_kind","paid_amount_cents","paid_at","payment_id","status"]},"PlanChangeError":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"ReferralEventData":{"type":"object","description":"`data` dos eventos `referral.*` (indicações). Discrimina por `status`.","properties":{"referral_id":{"type":"string","example":"rfr_01J…"},"status":{"allOf":[{"$ref":"#/components/schemas/ReferralEventDataStatusEnum"}],"description":"pending (created) → qualified → rewarded; ou reverted."},"referrer":{"type":"object","properties":{"id":{"type":"string","example":"cus_01J…"},"email":{"type":"string","format":"email"},"name":{"type":"string"}},"description":"Quem indicou (o indicador)."},"referred":{"type":"object","properties":{"id":{"type":"string","example":"cus_01J…"},"email":{"type":"string","format":"email"},"name":{"type":"string"}},"description":"Quem foi indicado."},"reward":{"type":"object","description":"Snapshot da recompensa desta indicação (fallback: config do programa).","properties":{"kind":{"type":"string","nullable":true,"description":"Ex.: percent_next, amount_next, percent_n, free_cycles, recurring_percent, external. Pode ser null."},"value":{"type":"integer","nullable":true},"cycles":{"type":"integer","nullable":true}}}}},"ReferralLinkResp":{"type":"object","properties":{"active":{"type":"boolean"},"code":{"type":"string","description":"código curto compartilhável"},"token":{"type":"string","description":"token opaco para a URL pública"},"link":{"type":"string","description":"URL que o cliente compartilha (/indique/<token>)"},"reward":{"$ref":"#/components/schemas/ReferralReward"},"progress":{"$ref":"#/components/schemas/ReferralProgress"}},"required":["active","code","link","progress","reward","token"]},"ReferralProgress":{"type":"object","properties":{"total":{"type":"integer"},"qualified":{"type":"integer"},"rewarded":{"type":"integer"},"reverted":{"type":"integer"}},"required":["qualified","reverted","rewarded","total"]},"ReferralReward":{"type":"object","properties":{"kind":{"type":"string"},"value":{"type":"integer"},"cycles":{"type":"integer"},"currency":{"type":"string"},"label":{"type":"string"}},"required":["currency","cycles","kind","label","value"]},"RenewalCampaignClientLink":{"type":"object","properties":{"token":{"type":"string","description":"token opaco do link (não é o id da assinatura)"},"url":{"type":"string","description":"URL pública que o cliente abre para pagar"},"price_cents":{"type":"integer","description":"preço já com desconto, em centavos"},"bonus_cycles":{"type":"integer","description":"bônus de tempo (0 = sem bônus)"},"bonus_unit":{"type":"string","description":"'month' | 'year' | '' (herda do plano)"},"status":{"type":"string","description":"open | pending | paid | failed | expired | revoked"},"starts_at":{"type":["string","null"],"format":"date-time","description":"início agendado da campanha (null = sem agenda; futuro ⟹ o link só é pagável a partir desta data)"},"offer_id":{"type":"string","description":"id da oferta da assinatura"},"plan_id":{"type":"string","description":"id do plano"},"product_id":{"type":"string","description":"id do produto"}},"required":["bonus_cycles","bonus_unit","offer_id","plan_id","price_cents","product_id","starts_at","status","token","url"]},"RenewalCampaignLinkRow":{"type":"object","properties":{"external_id":{"type":"string","description":"o id do cliente no seu app / SaaS"},"customer_email":{"type":"string"}},"required":["customer_email","external_id"]},"RenewalCampaignLinksPage":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/RenewalCampaignLinkRow"}},"next":{"type":["string","null"],"description":"cursor da próxima página (null = fim)"}},"required":["next","results"]},"RescheduleReq":{"type":"object","properties":{"next_billing_at":{"type":"string","format":"date-time","description":"nova data (ISO 8601, no futuro)"}},"required":["next_billing_at"]},"RescheduleResp":{"type":"object","properties":{"subscription":{"type":"object","additionalProperties":{},"description":"a assinatura já atualizada (shape do webhook)"},"next_billing_at":{"type":"string","format":"date-time"}},"required":["next_billing_at","subscription"]},"SubCustomer":{"type":"object","properties":{"id":{"type":"string","description":"cus_…"},"email":{"type":"string","format":"email"},"external_id":{"type":["string","null"],"description":"o seu id do cliente"}},"required":["email","external_id","id"]},"SubPaymentMethod":{"type":"object","properties":{"brand":{"type":"string"},"last4":{"type":"string"}},"required":["brand","last4"]},"SubPendingOffer":{"type":"object","properties":{"offer_id":{"type":"string"},"plan_id":{"type":"string"},"plan_name":{"type":"string","description":"nome do plano, só para exibição"},"interval":{"type":"string"},"amount_cents":{"type":"integer"},"effective_at":{"type":["string","null"],"format":"date-time"}},"required":["amount_cents","effective_at","interval","offer_id","plan_id","plan_name"]},"SubscriptionEventData":{"type":"object","description":"`data` dos eventos `subscription.*` e `invoice.*` (mesmo shape de `GET /v1/subscriptions/{id}`; nas listas, `last_payment` e `tracking` são omitidos).","properties":{"subscription_id":{"type":"string","example":"sub_01J…"},"status":{"allOf":[{"$ref":"#/components/schemas/SubscriptionEventDataStatusEnum"}],"description":"A ÚNICA fonte de verdade sobre o acesso do cliente."},"customer":{"type":"object","properties":{"id":{"type":"string","example":"cus_01J…"},"email":{"type":"string","format":"email"},"external_id":{"type":"string","description":"O seu ID do cliente."}}},"plan_id":{"type":"string","example":"plan_01KZ9R...","description":"Identificador oficial do plano."},"plan_name":{"type":"string","description":"Nome do plano, só para exibição."},"interval":{"$ref":"#/components/schemas/IntervalEnum"},"current_period_end":{"type":"string","format":"date-time","nullable":true},"cancel_at_period_end":{"type":"boolean","description":"true = cancelamento agendado para o fim do ciclo (não renova)."},"collection_method":{"$ref":"#/components/schemas/CollectionMethodEnum"},"payment_method":{"type":"object","nullable":true,"description":"Cartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).","properties":{"brand":{"type":"string"},"last4":{"type":"string"}}},"next_charge_amount_cents":{"type":"integer","description":"Valor final do próximo ciclo, em centavos."},"currency":{"type":"string","example":"brl"},"pending_offer":{"type":"object","nullable":true,"description":"Troca de plano AGENDADA (downgrade/troca de ciclo), se houver.","properties":{"offer_id":{"type":"string"},"plan_id":{"type":"string"},"plan_name":{"type":"string"},"interval":{"type":"string"},"amount_cents":{"type":"integer"},"effective_at":{"type":"string","format":"date-time","nullable":true}}},"entitlements":{"type":"object","additionalProperties":true,"description":"Capacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto."},"last_payment":{"type":"object","description":"O pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.","properties":{"payment_id":{"type":"string","example":"pay_01J…"},"status":{"type":"string","enum":["paid","refunded","chargedback"]},"method":{"type":"string","enum":["card","pix"]},"method_kind":{"type":"string"},"card":{"type":"object","nullable":true,"properties":{"brand":{"type":"string"},"last4":{"type":"string"}}},"amount_cents":{"type":"integer"},"paid_amount_cents":{"type":"integer"},"currency":{"type":"string","example":"brl"},"paid_at":{"type":"string","format":"date-time","nullable":true},"gateway_charge_id":{"type":"string","nullable":true},"gateway_provider":{"type":"string","example":"pagarme"}},"nullable":true},"tracking":{"type":"object","nullable":true,"description":"UTMs/click-ids do link do checkout. null sem contexto. Em renovação/upgrade vem herdada da assinatura (inherited: true). client_ip/user_agent NÃO entram (uso interno do envio ao GTM de servidor). `params` = demais parâmetros do link, sem dados pessoais.","properties":{"utm_source":{"type":"string","nullable":true},"utm_medium":{"type":"string","nullable":true},"utm_campaign":{"type":"string","nullable":true},"utm_term":{"type":"string","nullable":true},"utm_content":{"type":"string","nullable":true},"gclid":{"type":"string","nullable":true},"fbclid":{"type":"string","nullable":true},"fbc":{"type":"string","nullable":true},"fbp":{"type":"string","nullable":true},"referrer":{"type":"string","nullable":true},"landing_url":{"type":"string","nullable":true},"params":{"type":"object","additionalProperties":true,"description":"Passthrough de params arbitrários do link."},"captured_at":{"type":"string","format":"date-time"},"inherited":{"type":"boolean"}}}}},"SubscriptionGatewayEventsResp":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/GatewayEventRow"}}},"required":["results"]},"SubscriptionPayload":{"type":"object","description":"Shape completo da assinatura (idêntico ao payload de webhook).","properties":{"subscription_id":{"type":"string","description":"sub_…"},"status":{"type":"string","description":"trialing | active | past_due | suspended | canceled | pending_first_payment"},"customer":{"$ref":"#/components/schemas/SubCustomer"},"plan_id":{"type":"string","description":"identificador oficial do plano (plan_…)"},"plan_name":{"type":"string","description":"nome do plano, só para exibição"},"interval":{"type":"string","description":"month | year"},"current_period_end":{"type":["string","null"],"format":"date-time","description":"null no trial"},"cancel_at_period_end":{"type":"boolean","description":"true = a assinatura será cancelada no fim do ciclo (não renova)"},"collection_method":{"type":"string","description":"card_auto | pix_manual"},"payment_method":{"oneOf":[{"$ref":"#/components/schemas/SubPaymentMethod"},{"type":"null"}],"description":"null em Pix/sem cartão"},"next_charge_amount_cents":{"type":"integer","description":"valor do próximo ciclo, em centavos"},"currency":{"type":"string"},"pending_offer":{"oneOf":[{"$ref":"#/components/schemas/SubPendingOffer"},{"type":"null"}],"description":"troca agendada, se houver"},"entitlements":{"type":"object","additionalProperties":{},"description":"capacidades; CHEIO mesmo em suspended/canceled"},"last_payment":{"oneOf":[{"$ref":"#/components/schemas/PaymentInfo"},{"type":"null"}],"description":"o pagamento liquidado; null sem cobrança. Omitido nas listas"},"tracking":{"oneOf":[{"$ref":"#/components/schemas/Tracking"},{"type":"null"}],"description":"atribuição do link; null sem contexto. Omitido nas listas"}},"required":["cancel_at_period_end","collection_method","currency","current_period_end","customer","entitlements","interval","next_charge_amount_cents","payment_method","pending_offer","plan_id","plan_name","status","subscription_id"]},"SubscriptionPaymentLinkResp":{"type":"object","properties":{"token":{"type":"string","description":"token opaco (access_token da fatura, não o id)"},"url":{"type":"string","description":"a URL pública que o cliente abre para pagar"},"amount_cents":{"type":"integer"},"status":{"type":"string","description":"status da fatura em aberto"}},"required":["amount_cents","status","token","url"]},"Tracking":{"type":"object","description":"Atribuição capturada no link do checkout (null sem contexto). 08/2026.","properties":{"utm_source":{"type":["string","null"]},"utm_medium":{"type":["string","null"]},"utm_campaign":{"type":["string","null"]},"utm_term":{"type":["string","null"]},"utm_content":{"type":["string","null"]},"gclid":{"type":["string","null"]},"fbclid":{"type":["string","null"]},"fbc":{"type":["string","null"]},"fbp":{"type":["string","null"]},"referrer":{"type":["string","null"]},"landing_url":{"type":["string","null"]},"params":{"type":"object","additionalProperties":{}},"captured_at":{"type":"string","format":"date-time"},"inherited":{"type":"boolean"}},"required":["captured_at","fbc","fbclid","fbp","gclid","inherited","landing_url","params","referrer","utm_campaign","utm_content","utm_medium","utm_source","utm_term"]},"WebhookEnvelope":{"type":"object","description":"Corpo (cru) de todo POST de webhook. A assinatura HMAC é calculada sobre este corpo exato.","required":["id","type","created_at","tenant_id","data"],"properties":{"id":{"type":"string","example":"evt_01J…","description":"Igual ao header X-Billing-Event-Id. Chave de dedupe."},"type":{"type":"string","description":"Tipo do evento (ex.: invoice.paid)."},"created_at":{"type":"string","format":"date-time"},"tenant_id":{"type":"string","example":"tn_01J…","description":"ID do tenant (prefixo tn_)."},"data":{"type":"object","description":"Payload específico do tipo (ver abaixo)."}}}},"securitySchemes":{"tenantApiKey":{"type":"http","scheme":"bearer","bearerFormat":"bk_...","description":"API key do tenant (prefixo `bk_`), gerada no painel em Configurações → API keys. Header: `Authorization: Bearer bk_...`."}}},"tags":[{"name":"Integração — Entitlements e assinaturas","description":"Consultar capacidades de um cliente, listar/ler assinaturas, trocar plano, links de pagamento e histórico de pagamentos."},{"name":"Integração — Gerenciamento","description":"Ações que movem estado/dinheiro: estorno, cancelamento, cobrar agora, links de renovação e de troca de forma de pagamento, reagendar, remover cupom."},{"name":"Integração — Renovação por campanha","description":"Gerar e listar links de renovação de uma campanha para os clientes do público-alvo."},{"name":"Integração — Indicações","description":"Obter o código/link de indicação de um cliente e o progresso das recompensas."},{"name":"Webhooks","description":"Eventos que a ribbo ENVIA ao seu endpoint (POST assinado). Ver a seção webhooks."}],"webhooks":{"subscription.activated":{"post":{"summary":"Assinatura ativada","description":"A assinatura foi ativada e o acesso liberado (após a 1ª cobrança aprovada no checkout ou a reativação de uma suspensa). Possíveis `status`: `active` | `trialing`. `trialing` quando a ativação vem de um checkout com trial (ainda sem cobrança). Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active","trialing"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.activated"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.activated","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.updated":{"post":{"summary":"Assinatura atualizada","description":"Re-sync do estado atual, sem status próprio: reagendamento, troca de forma de pagamento, entitlements do plano editados (um evento por assinatura viva do plano, com o mapa novo), ou acompanhando ('companion') um evento de ciclo de vida. Possíveis `status`: `active` | `past_due` | `suspended` | `canceled` | `trialing`. É um evento de RECONCILIAÇÃO: o `status` reflete o estado ATUAL e pode ser QUALQUER um. Inclusive pode chegar logo após um evento de ciclo de vida (ex.: junto de `subscription.canceled`, com `status: canceled`). Trate como \"releia o `status` e reconcilie\". `pending_offer` vem preenchido se houver troca de plano agendada. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active","past_due","suspended","canceled","trialing"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.updated"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.updated","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.plan_changed":{"post":{"summary":"Plano alterado","description":"A troca de plano foi aplicada (upgrade imediato, ou a troca agendada entrou em vigor). `status`: `active`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.plan_changed"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.plan_changed","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.plan_change_scheduled":{"post":{"summary":"Troca de plano agendada","description":"Uma troca de plano foi AGENDADA (downgrade ou troca de ciclo) para o fim do período. Veja `pending_offer`. `status`: `active`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.plan_change_scheduled"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.plan_change_scheduled","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":{"offer_id":"offer_01KZ9R...","plan_id":"plan_01KZ9R...","plan_name":"Pro anual","interval":"year","amount_cents":49900,"effective_at":"2026-09-01T00:00:00Z"},"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.plan_change_canceled":{"post":{"summary":"Troca de plano cancelada","description":"Uma troca de plano agendada foi cancelada. `pending_offer` volta a null. `status`: `active`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.plan_change_canceled"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.plan_change_canceled","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.migration_link_issued":{"post":{"summary":"Link de migração de gateway emitido","description":"Uma troca AGENDADA para uma oferta de OUTRO gateway venceu: em vez de renovar no gateway antigo, foi emitido um link de pagamento no gateway novo (o cartão salvo não atravessa gateways). O cliente é avisado por e-mail; a assinatura migra quando o link é pago. `status`: `active`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.migration_link_issued"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.migration_link_issued","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":{"offer_id":"offer_01KZ9R...","plan_id":"plan_01KZ9R...","plan_name":"Pro anual","interval":"year","amount_cents":49900,"effective_at":"2026-09-01T00:00:00Z"},"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.trial_started":{"post":{"summary":"Trial iniciado","description":"Um trial começou, antes de qualquer cobrança. `current_period_end` vem null. `status`: `trialing`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["trialing"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.trial_started"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.trial_started","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"trialing","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":null,"cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":null,"tracking":null}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.past_due":{"post":{"summary":"Assinatura inadimplente","description":"Uma cobrança falhou e a assinatura entrou em inadimplência. A régua tenta de novo em D+1, D+3, D+5 e D+9 contados do vencimento; o acesso continua até a suspensão. `status`: `past_due`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["past_due"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.past_due"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.past_due","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"past_due","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.suspended":{"post":{"summary":"Assinatura suspensa","description":"As retentativas se esgotaram (após D+9) e a assinatura foi suspensa; volta a `active` quando o cliente paga. `entitlements` continua CHEIO: decida o acesso por `status`. `status`: `suspended`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["suspended"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.suspended"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.suspended","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"suspended","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"subscription.canceled":{"post":{"summary":"Assinatura cancelada","description":"A assinatura foi cancelada (terminal). `status`: `canceled`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["canceled"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["subscription.canceled"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"subscription.canceled","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"canceled","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"invoice.paid":{"post":{"summary":"Fatura paga","description":"Uma fatura foi paga (1ª cobrança ou renovação). Mesmo shape de assinatura. Possíveis `status`: `active` | `trialing`. `trialing` se for o pagamento inicial de um checkout com trial. `last_payment` é o pagamento DESTA fatura; `tracking` traz os UTMs/click-ids (herdados da assinatura na renovação, `inherited: true`). Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active","trialing"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["invoice.paid"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"invoice.paid","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"active","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"invoice.payment_failed":{"post":{"summary":"Falha no pagamento da fatura","description":"O pagamento de uma fatura falhou. Possíveis `status`: `past_due` | `suspended`. `past_due` durante a régua de retentativas; `suspended` quando as retentativas se esgotam (ramo terminal). Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["past_due","suspended"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["invoice.payment_failed"]},"data":{"$ref":"#/components/schemas/SubscriptionEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"invoice.payment_failed","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"past_due","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"order.paid":{"post":{"summary":"Pedido pago","description":"Um pedido avulso (pagamento único) foi pago. `status`: `paid`. `tracking` carrega os UTMs/click-ids do link de checkout; em renovação/upgrade vem herdado da assinatura (`inherited: true`). `target_subscription_id` aponta a assinatura estendida quando o order.paid é de renovação antecipada. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["paid"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["order.paid"]},"data":{"$ref":"#/components/schemas/OrderEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"order.paid","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"order_id":"ord_01J8Z9K2Q7","status":"paid","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pacote de créditos","quantity":2,"amount_cents":9980,"unit_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","target_subscription_id":null,"entitlements":{"credits":100},"grant_days":30,"payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"pix","method_kind":"pix","card":null,"amount_cents":9980,"paid_amount_cents":9980,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"order.refunded":{"post":{"summary":"Pedido estornado","description":"Um pedido avulso foi estornado. `status`: `refunded`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["refunded"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["order.refunded"]},"data":{"$ref":"#/components/schemas/OrderEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"order.refunded","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"order_id":"ord_01J8Z9K2Q7","status":"refunded","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pacote de créditos","quantity":2,"amount_cents":9980,"unit_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","target_subscription_id":null,"entitlements":{"credits":100},"grant_days":30,"payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"pix","method_kind":"pix","card":null,"amount_cents":9980,"paid_amount_cents":9980,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"payment.refunded":{"post":{"summary":"Pagamento estornado","description":"Um pagamento foi estornado, total ou parcialmente. Pode ser de ASSINATURA (renovação ou proração de upgrade/troca) ou de PEDIDO avulso. Possíveis `status`: `active` | `past_due` | `canceled` | `paid` | `refunded`. O corpo é `SubscriptionEventData` (estorno de assinatura) OU `OrderEventData` (estorno de pedido avulso), um `oneOf`. Um estorno TOTAL que revoga o acesso acompanha também `subscription.canceled` (assinatura) ou `order.refunded` (pedido); um estorno parcial ou cortesia mantém a assinatura ativa (status `active`/`past_due`). Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["active","past_due","canceled","paid","refunded"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["payment.refunded"]},"data":{"oneOf":[{"$ref":"#/components/schemas/SubscriptionEventData"},{"$ref":"#/components/schemas/OrderEventData"}]}}},"example":{"id":"evt_01J8Z9K2Q7","type":"payment.refunded","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"subscription_id":"sub_01J8Z9K2Q7","status":"refunded","customer":{"id":"cus_01J8Z9K2Q7","email":"cliente@empresa.com","external_id":"user-123"},"plan_id":"plan_01KZ9R...","plan_name":"Pro","interval":"month","current_period_end":"2026-09-01T00:00:00Z","cancel_at_period_end":false,"collection_method":"card_auto","payment_method":{"brand":"visa","last4":"4242"},"next_charge_amount_cents":4990,"currency":"brl","pending_offer":null,"entitlements":{"seats":5,"api":true},"last_payment":{"payment_id":"pay_01J8Z9K2Q7","status":"paid","method":"card","method_kind":"card","card":{"brand":"visa","last4":"4242"},"amount_cents":4990,"paid_amount_cents":4990,"currency":"brl","paid_at":"2026-08-12T14:03:11Z","gateway_charge_id":"ch_9vGZ","gateway_provider":"pagarme"},"tracking":{"utm_source":"facebook","utm_medium":"cpc","utm_campaign":"lancamento-agosto","utm_term":null,"utm_content":"ad-v2","gclid":null,"fbclid":"IwAR2xyz","fbc":"fb.1.1754990000000.IwAR2xyz","fbp":null,"referrer":"https://l.facebook.com/","landing_url":"https://pay.ribbo.app/HSHG356?utm_source=facebook&fbclid=IwAR2xyz","params":{"sck":"bio-instagram"},"captured_at":"2026-08-12T13:58:02Z","inherited":false}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"referral.created":{"post":{"summary":"Indicação criada","description":"Uma indicação foi criada (o indicado fez checkout com o código). Ainda não qualificada. `status`: `pending`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["pending"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["referral.created"]},"data":{"$ref":"#/components/schemas/ReferralEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"referral.created","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"referral_id":"rfr_01J8Z9K2Q7","status":"pending","referrer":{"id":"cus_01J8Z9AAAA","email":"indicador@empresa.com","name":"Ana"},"referred":{"id":"cus_01J8Z9BBBB","email":"novo@empresa.com","name":"Bruno"},"reward":{"kind":"percent_next","value":20,"cycles":1}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"referral.qualified":{"post":{"summary":"Indicação qualificada","description":"A indicação atingiu a condição de qualificação. `status`: `qualified`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["qualified"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["referral.qualified"]},"data":{"$ref":"#/components/schemas/ReferralEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"referral.qualified","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"referral_id":"rfr_01J8Z9K2Q7","status":"qualified","referrer":{"id":"cus_01J8Z9AAAA","email":"indicador@empresa.com","name":"Ana"},"referred":{"id":"cus_01J8Z9BBBB","email":"novo@empresa.com","name":"Bruno"},"reward":{"kind":"percent_next","value":20,"cycles":1}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"referral.rewarded":{"post":{"summary":"Recompensa de indicação concedida","description":"A recompensa da indicação foi concedida ao indicador. `status`: `rewarded`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["rewarded"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["referral.rewarded"]},"data":{"$ref":"#/components/schemas/ReferralEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"referral.rewarded","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"referral_id":"rfr_01J8Z9K2Q7","status":"rewarded","referrer":{"id":"cus_01J8Z9AAAA","email":"indicador@empresa.com","name":"Ana"},"referred":{"id":"cus_01J8Z9BBBB","email":"novo@empresa.com","name":"Bruno"},"reward":{"kind":"percent_next","value":20,"cycles":1}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}},"referral.reverted":{"post":{"summary":"Recompensa de indicação revertida","description":"A recompensa foi revertida (estorno/churn do indicado). `status`: `reverted`. Responda `2xx` para confirmar; senão a ribbo re-tenta (1min → 5min → 30min → 2h → 6h → 24h; 7 tentativas).","x-statuses":["reverted"],"tags":["Webhooks"],"parameters":[{"name":"X-Billing-Event-Id","in":"header","required":true,"schema":{"type":"string"},"description":"ID único do evento (evt_…). Trate de forma idempotente: pode chegar mais de uma vez (entrega at-least-once)."},{"name":"X-Billing-Signature","in":"header","required":true,"schema":{"type":"string","example":"ts=1690000000,v1=<hmac_hex>"},"description":"Assinatura: v1 = HMAC-SHA256(secret, f\"{ts}.{corpo_cru}\"). Valide em tempo constante sobre o corpo cru, usando o secret do endpoint."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/WebhookEnvelope"}],"properties":{"type":{"type":"string","enum":["referral.reverted"]},"data":{"$ref":"#/components/schemas/ReferralEventData"}}},"example":{"id":"evt_01J8Z9K2Q7","type":"referral.reverted","created_at":"2026-08-01T12:00:00Z","tenant_id":"tn_01J8Z9K2Q7","data":{"referral_id":"rfr_01J8Z9K2Q7","status":"reverted","referrer":{"id":"cus_01J8Z9AAAA","email":"indicador@empresa.com","name":"Ana"},"referred":{"id":"cus_01J8Z9BBBB","email":"novo@empresa.com","name":"Bruno"},"reward":{"kind":"percent_next","value":20,"cycles":1}}}}}},"responses":{"200":{"description":"Recebido. Qualquer 2xx confirma a entrega."}}}}}}