Docs

Buscar na documentação

Guias, endpoints e eventos

Ir ao painel

Referência da API

Todas as chamadas Bearer da API de integração. Autentique com Authorization: Bearer bk_…. Campos marcados com * são obrigatórios.

Entitlements

get/v1/entitlements

Entitlements de um cliente (o que ele pode usar AGORA)

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).

Parâmetros

CampoTipoEmDescrição
emailstringqueryAlternativa ao external_id (evite — PII em query string/logs).
external_idstringqueryO id do cliente no SEU app / SaaS (Customer.external_id). Preferido.

Respostas

200
CampoTipoDescrição
customer_id *string?null = cliente não encontrado
subscriptions *EntitlementsSubscriptionRow[]assinaturas não canceladas + entitlements do plano
merged_entitlements *objecta UNIÃO das capacidades de active/trialing/past_due (o que aplicar)
{
  "customer_id": "string",
  "subscriptions": [
    {
      "id": "string",
      "status": "string",
      "plan_id": "string",
      "interval": "string",
      "current_period_end": "2026-01-01T00:00:00Z",
      "entitlements": {}
    }
  ],
  "merged_entitlements": {}
}
400Nem `external_id` nem `email` informados.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}

Assinaturas

get/v1/subscriptions

Listar as assinaturas do tenant — keyset paginado

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.

Parâmetros

CampoTipoEmDescrição
afterstringquerycursor da página anterior (o campo `next` da resposta)
limitintegerquerytamanho da página (default 100, máx 500)
offer_idstringqueryfiltra pela oferta (offer_01...)
statusstringqueryfiltra por status; um ou vários por vírgula (ex.: `active` ou `active,past_due`). Valor fora do conjunto conhecido ⟹ 400.

Respostas

200
CampoTipoDescrição
results *SubscriptionPayload[]
next *string?cursor da próxima página (null=fim)
{
  "results": [
    {
      "subscription_id": "string",
      "status": "string",
      "customer": {
        "id": "string",
        "email": "string",
        "external_id": "string"
      },
      "plan_id": "string",
      "plan_name": "string",
      "interval": "string",
      "current_period_end": "2026-01-01T00:00:00Z",
      "cancel_at_period_end": true,
      "collection_method": "string",
      "payment_method": null,
      "next_charge_amount_cents": 0,
      "currency": "string",
      "pending_offer": null,
      "entitlements": {},
      "last_payment": null,
      "tracking": null
    }
  ],
  "next": "string"
}
400`status` fora do conjunto conhecido (o corpo traz `accepted`).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
get/v1/subscriptions/{subscription_id}

Detalhe de UMA assinatura (estado atual, qualquer status)

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).

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

200
CampoTipoDescrição
subscription_id *stringsub_…
status *stringtrialing | active | past_due | suspended | canceled | pending_first_payment
customer *SubCustomer
plan_id *stringidentificador oficial do plano (plan_…)
plan_name *stringnome do plano, só para exibição
interval *stringmonth | year
current_period_end *string? (date-time)null no trial
cancel_at_period_end *booleantrue = a assinatura será cancelada no fim do ciclo (não renova)
collection_method *stringcard_auto | pix_manual
payment_method *anynull em Pix/sem cartão
next_charge_amount_cents *integervalor do próximo ciclo, em centavos
currency *string
pending_offer *anytroca agendada, se houver
entitlements *objectcapacidades; CHEIO mesmo em suspended/canceled
last_paymentanyo pagamento liquidado; null sem cobrança. Omitido nas listas
trackinganyatribuição do link; null sem contexto. Omitido nas listas
{
  "subscription_id": "string",
  "status": "string",
  "customer": {
    "id": "string",
    "email": "string",
    "external_id": "string"
  },
  "plan_id": "string",
  "plan_name": "string",
  "interval": "string",
  "current_period_end": "2026-01-01T00:00:00Z",
  "cancel_at_period_end": true,
  "collection_method": "string",
  "payment_method": null,
  "next_charge_amount_cents": 0,
  "currency": "string",
  "pending_offer": null,
  "entitlements": {},
  "last_payment": null,
  "tracking": null
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/cancel

Cancelar uma assinatura (imediato ou no fim do período)

Auth: Authorization: Bearer <tenant_api_key> com scope write (liberado mesmo com a conta em modo só leitura). Dois modos:

  • 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.
  • 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}).

reason opcional (≤300) vai ao e-mail de cancelamento. 404 se é de outro tenant ou não existe.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Corpo da requisição

CampoTipoDescrição
reasonstringmotivo do cancelamento (≤300)
at_period_endbooleantrue = agenda o cancelamento p/ o fim do período (reversível); false/omitido = cancela imediatamente (terminal)

Exemplo de requisição

{
  "reason": "string",
  "at_period_end": false
}

Respostas

200
CampoTipoDescrição
statusstringcanceled (modo imediato)
okboolean
cancel_at_period_endbooleantrue quando agendado p/ o fim do período
current_period_endstring? (date-time)quando agendado: até quando o acesso continua
{
  "status": "string",
  "ok": true,
  "cancel_at_period_end": true,
  "current_period_end": "2026-01-01T00:00:00Z"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422Há um QR Pix ainda pagável, ou o estado atual não permite cancelar/agendar.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/cancel-plan-change

Cancelar uma troca de plano AGENDADA

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.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

200
CampoTipoDescrição
subscription *anyassinatura sem o pending_offer
plan_change *objectresultado do cancelamento
{
  "subscription": null,
  "plan_change": {}
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422Não há troca de plano agendada.
CampoTipoDescrição
error *string
{
  "error": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/cancel/undo

Desfazer um cancelamento agendado

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.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

200
CampoTipoDescrição
ok *boolean
cancel_at_period_end *booleanfalse após desfazer
{
  "ok": true,
  "cancel_at_period_end": true
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422Não há cancelamento agendado para desfazer.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/change-plan

Trocar o plano de uma assinatura (upgrade/downgrade)

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": "..."}).

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Corpo da requisição

CampoTipoDescrição
offer_id *stringo id da oferta ALVO (offer_01...)
keep_couponbooleanleva o cupom ativo para a nova oferta (default: false)

Exemplo de requisição

{
  "offer_id": "string",
  "keep_coupon": false
}

Respostas

200
CampoTipoDescrição
subscription *anya assinatura já atualizada
plan_change *objectresultado da troca. Chaves: kind, effect, charge_cents, applies_at…
{
  "subscription": null,
  "plan_change": {}
}
400`offer_id` ausente.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422Troca de plano inválida (regra de negócio).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/charge-now

Cobrar agora (enfileira o billing run da assinatura)

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.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

202
CampoTipoDescrição
ok *boolean
message *string
{
  "ok": true,
  "message": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
409Assinatura fora da janela de cobrança (`status` no corpo) ou renovações da conta pausadas.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
get/v1/subscriptions/{subscription_id}/gateway-events

Timeline do gateway de uma assinatura (auditoria)

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.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

200
CampoTipoDescrição
results *GatewayEventRow[]
{
  "results": [
    {
      "id": "string",
      "provider": "string",
      "kind": "string",
      "outcome": "string",
      "code": "string",
      "gateway_id": "string",
      "detail_code": "string",
      "http_status": 0,
      "amount_cents": 0,
      "created_at": "2026-01-01T00:00:00Z"
    }
  ]
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/remove-coupon

Remover o cupom de uma assinatura

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.

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Respostas

200
CampoTipoDescrição
removed *integerquantos resgates foram desativados
{
  "removed": 0
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/subscriptions/{subscription_id}/reschedule

Reagendar a data da próxima cobrança de uma assinatura

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).

Parâmetros

CampoTipoEmDescrição
subscription_id *stringpath

Corpo da requisição

CampoTipoDescrição
next_billing_at *string (date-time)nova data (ISO 8601, no futuro)

Exemplo de requisição

{
  "next_billing_at": "2026-01-01T00:00:00Z"
}

Respostas

200
CampoTipoDescrição
subscription *objecta assinatura já atualizada (shape do webhook)
next_billing_at *string (date-time)
{
  "subscription": {},
  "next_billing_at": "2026-01-01T00:00:00Z"
}
400Data inválida ou no passado.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita) ou `account_locked` (conta ribbo em modo só leitura).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
409Há uma cobrança ou QR Pix em aberto neste ciclo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422O status da assinatura não permite reagendar.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}

Clientes

post/v1/customers/{external_id}

Atualizar o cadastro de um cliente (nome, e-mail, telefone)

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.

Parâmetros

CampoTipoEmDescrição
external_id *stringpath

Corpo da requisição

CampoTipoDescrição
namestring
emailstring (email)
phonestringcelular em E.164, ex.: +5511999999999

Exemplo de requisição

{
  "name": "string",
  "email": "string",
  "phone": "string"
}

Respostas

200
CampoTipoDescrição
name *string
email *string
phone *string
notice *string?sync do gateway falhou (não-fatal)
{
  "name": "string",
  "email": "string",
  "phone": "string",
  "notice": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422E-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`.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/customers/{external_id}/email

Atualizar o e-mail de um cliente

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": "..."}).

Parâmetros

CampoTipoEmDescrição
external_id *stringpath

Corpo da requisição

CampoTipoDescrição
email *string (email)o novo e-mail do cliente

Exemplo de requisição

{
  "email": "string"
}

Respostas

200
CampoTipoDescrição
email *stringo e-mail já atualizado
notice *string?aviso não-fatal (ex.: sync do gateway)
{
  "email": "string",
  "notice": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422E-mail inválido ou já usado por outro cliente do tenant.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
get/v1/customers/{external_id}/payments

Histórico de pagamentos de um cliente — keyset paginado

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.

Parâmetros

CampoTipoEmDescrição
afterstringquerycursor da página anterior (o campo `next` da resposta)
external_id *stringpath
limitintegerquerytamanho da página (default 100, máx 500)

Respostas

200
CampoTipoDescrição
results *ApiPaymentRow[]
next *string?cursor da próxima página (null=fim)
{
  "results": [
    {
      "payment_id": "string",
      "status": "string",
      "kind": "string",
      "method": "string",
      "method_kind": "string",
      "amount_cents": 0,
      "currency": "string",
      "refunded_amount_cents": 0,
      "refund_in_flight": true,
      "refund_reason": "string",
      "failure_code": "string",
      "gateway_charge_id": "string",
      "provider": "string",
      "card": {},
      "paid_at": "2026-01-01T00:00:00Z",
      "reference": {},
      "customer": {}
    }
  ],
  "next": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
get/v1/customers/{external_id}/subscriptions

Listar as assinaturas de um cliente

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.

Parâmetros

CampoTipoEmDescrição
external_id *stringpath

Respostas

200
CampoTipoDescrição
customer_id *string
subscriptions *SubscriptionPayload[]
{
  "customer_id": "string",
  "subscriptions": [
    {
      "subscription_id": "string",
      "status": "string",
      "customer": {
        "id": "string",
        "email": "string",
        "external_id": "string"
      },
      "plan_id": "string",
      "plan_name": "string",
      "interval": "string",
      "current_period_end": "2026-01-01T00:00:00Z",
      "cancel_at_period_end": true,
      "collection_method": "string",
      "payment_method": null,
      "next_charge_amount_cents": 0,
      "currency": "string",
      "pending_offer": null,
      "entitlements": {},
      "last_payment": null,
      "tracking": null
    }
  ]
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}

Pagamentos

get/v1/payments/{payment_id}

Detalhe de um pagamento (com itens)

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.

Parâmetros

CampoTipoEmDescrição
payment_id *stringpath

Respostas

200
CampoTipoDescrição
payment_id *string
status *stringprocessing | paid | failed | refunded | chargedback
kind *stringrecurring | one_time
method *stringcard | pix
method_kind *string
amount_cents *integer
currency *string
refunded_amount_cents *integer
refund_in_flight *booleanestorno commitado, ainda não reconciliado
refund_reason *string
failure_code *stringmotivo da recusa (ex.: insufficient_funds)
gateway_charge_id *string
provider *stringpagarme | stripe | asaas
card *object{brand, last4} — NUNCA o PAN
paid_at *string? (date-time)
reference *object?{type: subscription|order, id}
customer *object?{external_id, email}
items *object[]itens da cobrança: {id, kind, amount_cents, refunded_amount_cents, refunded}
{
  "payment_id": "string",
  "status": "string",
  "kind": "string",
  "method": "string",
  "method_kind": "string",
  "amount_cents": 0,
  "currency": "string",
  "refunded_amount_cents": 0,
  "refund_in_flight": true,
  "refund_reason": "string",
  "failure_code": "string",
  "gateway_charge_id": "string",
  "provider": "string",
  "card": {},
  "paid_at": "2026-01-01T00:00:00Z",
  "reference": {},
  "customer": {},
  "items": [
    {}
  ]
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
post/v1/payments/{payment_id}/refund

Estornar um pagamento (total ou parcial)

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.

Parâmetros

CampoTipoEmDescrição
payment_id *stringpath

Corpo da requisição

CampoTipoDescrição
amount_cents *integervalor a estornar, em centavos
reason *stringmotivo do estorno (obrigatório, ≤300)
revokestringsubscription | grant | none. Se omitido, revoga o acesso apropriado (assinatura p/ fatura, concessão p/ pedido); mande none p/ não revogar
confirm_runwaybooleanreenvie true quando o 422 pedir: confirma estornar uma fatura que financiou runway pré-pago

Exemplo de requisição

{
  "amount_cents": 0,
  "reason": "string",
  "revoke": "string",
  "confirm_runway": false
}

Respostas

200
CampoTipoDescrição
level *stringsuccess | warning
message *string
{
  "level": "string",
  "message": "string"
}
400`amount_cents` ausente ou não inteiro.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
401Não autorizado: sem header, chave inválida ou revogada, ou tenant suspenso.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
403`insufficient_scope` (chave `read` numa rota de escrita). Esta rota segue liberada com a conta ribbo em modo só leitura.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
404Não existe ou pertence a outro tenant (indistinguíveis de propósito).
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}
422O 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.
CampoTipoDescrição
error *string
requires_confirmation *string"runway"
{
  "error": "string",
  "requires_confirmation": "string"
}
429Limite de requisições da rota excedido. Não cobra nada; faça backoff e tente de novo.
CampoTipoDescrição
error *stringmensagem legível
codestringcódigo estável, quando a rota define um
{
  "error": "string",
  "code": "string"
}

Pedidos

Indicações

Campanhas de renovação

Eventos (webhooks)

O que a ribbo envia ao seu endpoint (POST assinado) a cada evento. Cada evento traz o envelope + o data. Para o envelope, a validação HMAC e os retries, veja o guia de Webhooks.

Assinatura

postsubscription.activated

Assinatura ativada

Status possíveisactivetrialing

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.updated

Assinatura atualizada

Status possíveisactivepast_duesuspendedcanceledtrialing

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.plan_changed

Plano alterado

Status possíveisactive

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.plan_change_scheduled

Troca de plano agendada

Status possíveisactive

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.plan_change_canceled

Troca de plano cancelada

Status possíveisactive

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.trial_started

Trial iniciado

Status possíveistrialing

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
  }
}
postsubscription.past_due

Assinatura inadimplente

Status possíveispast_due

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.suspended

Assinatura suspensa

Status possíveissuspended

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postsubscription.canceled

Assinatura cancelada

Status possíveiscanceled

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}

Fatura

postinvoice.paid

Fatura paga

Status possíveisactivetrialing

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postinvoice.payment_failed

Falha no pagamento da fatura

Status possíveispast_duesuspended

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}

Pedido

postorder.paid

Pedido pago

Status possíveispaid

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).

Campos de data

CampoTipoDescrição
order_idstring
statusstring
customerobject
plan_idstring
plan_namestringNome do plano, só para exibição.
quantityinteger
amount_centsinteger
unit_amount_centsinteger
currencystring
paid_atstring (date-time)
target_subscription_idstringA assinatura que um order.paid de renovação/extensão estendeu; senão null.
entitlementsobjectCRU: nunca multiplicado por quantity.
grant_daysintegerCRU: nunca multiplicado por quantity.
paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}
postorder.refunded

Pedido estornado

Status possíveisrefunded

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).

Campos de data

CampoTipoDescrição
order_idstring
statusstring
customerobject
plan_idstring
plan_namestringNome do plano, só para exibição.
quantityinteger
amount_centsinteger
unit_amount_centsinteger
currencystring
paid_atstring (date-time)
target_subscription_idstringA assinatura que um order.paid de renovação/extensão estendeu; senão null.
entitlementsobjectCRU: nunca multiplicado por quantity.
grant_daysintegerCRU: nunca multiplicado por quantity.
paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}

Pagamento

postpayment.refunded

Pagamento estornado

Status possíveisactivepast_duecanceledpaidrefunded

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).

Campos de data

CampoTipoDescrição
subscription_idstring
statusanyA ÚNICA fonte de verdade sobre o acesso do cliente.
customerobject
plan_idstringIdentificador oficial do plano.
plan_namestringNome do plano, só para exibição.
intervalIntervalEnum
current_period_endstring (date-time)
cancel_at_period_endbooleantrue = cancelamento agendado para o fim do ciclo (não renova).
collection_methodCollectionMethodEnum
payment_methodobjectCartão mascarado (nunca o PAN) ou `null` (Pix/sem cartão).
next_charge_amount_centsintegerValor final do próximo ciclo, em centavos.
currencystring
pending_offerobjectTroca de plano AGENDADA (downgrade/troca de ciclo), se houver.
entitlementsobjectCapacidades do plano. Vem CHEIO mesmo em suspended/past_due/canceled: decida o acesso por `status`, não pela presença disto.
last_paymentobjectO pagamento liquidado. No invoice.paid é o desta fatura; null sem cobrança.
trackingobjectUTMs/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.

Exemplo (envelope completo)

{
  "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
    }
  }
}

Indicação

postreferral.created

Indicação criada

Status possíveispending

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).

Campos de data

CampoTipoDescrição
referral_idstring
statusanypending (created) → qualified → rewarded; ou reverted.
referrerobjectQuem indicou (o indicador).
referredobjectQuem foi indicado.
rewardobjectSnapshot da recompensa desta indicação (fallback: config do programa).

Exemplo (envelope completo)

{
  "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
    }
  }
}
postreferral.qualified

Indicação qualificada

Status possíveisqualified

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).

Campos de data

CampoTipoDescrição
referral_idstring
statusanypending (created) → qualified → rewarded; ou reverted.
referrerobjectQuem indicou (o indicador).
referredobjectQuem foi indicado.
rewardobjectSnapshot da recompensa desta indicação (fallback: config do programa).

Exemplo (envelope completo)

{
  "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
    }
  }
}
postreferral.rewarded

Recompensa de indicação concedida

Status possíveisrewarded

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).

Campos de data

CampoTipoDescrição
referral_idstring
statusanypending (created) → qualified → rewarded; ou reverted.
referrerobjectQuem indicou (o indicador).
referredobjectQuem foi indicado.
rewardobjectSnapshot da recompensa desta indicação (fallback: config do programa).

Exemplo (envelope completo)

{
  "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
    }
  }
}
postreferral.reverted

Recompensa de indicação revertida

Status possíveisreverted

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).

Campos de data

CampoTipoDescrição
referral_idstring
statusanypending (created) → qualified → rewarded; ou reverted.
referrerobjectQuem indicou (o indicador).
referredobjectQuem foi indicado.
rewardobjectSnapshot da recompensa desta indicação (fallback: config do programa).

Exemplo (envelope completo)

{
  "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
    }
  }
}