Convenções
Valem para toda a API.
Dinheiro em centavos
Todo valor é um inteiro em centavos. amount_cents: 1990 = R$ 19,90. Nunca há float.
A moeda vem no campo currency em minúsculo (ex.: "brl").
IDs com prefixo
Os IDs são ULIDs com prefixo, ordenáveis por tempo:
| Prefixo | Recurso |
|---|---|
cus_ | cliente |
sub_ | assinatura |
inv_ | fatura |
pay_ | pagamento |
ord_ | pedido avulso |
plan_ | plano |
offer_ | oferta |
evt_ | evento de webhook |
O plano é identificado por plan_id (o plan_name vem junto, só para exibição) e a oferta
por offer_id. O seu external_id do cliente é a chave que você controla e usa para
casar com o seu sistema: as rotas de cliente (/v1/customers/{external_id}/...) usam ele.
Datas
UTC, formato ISO-8601 (ex.: 2026-09-01T00:00:00Z). Campos de data podem vir null (ex.:
current_period_end antes da primeira cobrança).
Paginação por cursor (keyset)
Listas usam cursor, não offset. Passe ?limit= (default 100, máx 500) e ?after=<cursor>; a
resposta traz { "results": [...], "next": "<cursor>" | null }. Pagine até next ser null.
curl "https://api.ribbo.app/v1/customers/cliente-123/payments?limit=50" -H "Authorization: Bearer bk_..."
# use o "next" da resposta como ?after= na próxima página
Erros
O corpo de erro é {"error":"mensagem"}. Algumas rotas incluem campos extras, como code
(ex.: data_passada no reagendamento), status ou requires_confirmation. Exceções: o
404 de um recurso que não existe e o 429 podem vir no formato {"detail":"mensagem"}, e o
estorno recusado pelo gateway volta {"level":"error","message":"..."}. Decida pelo código HTTP.
| Código | Significado |
|---|---|
400 | input inválido (ex.: campo obrigatório ausente) |
401 | não autorizado |
403 | insufficient_scope (escopo insuficiente) ou account_locked (conta em modo só leitura) |
404 | não existe ou é de outro tenant (indistinguível de propósito) |
409 | conflito de estado (ex.: não há fatura aberta, assinatura fora da janela de cobrança) |
422 | regra de negócio (ex.: troca de plano inválida, telefone inválido) |
429 | limite de requisições da rota excedido |
202 | aceito e enfileirado (ex.: cobrar agora) |
Idempotência
A ribbo é idempotente por semântica, não por header:
- As consultas (
GET) são seguras de repetir. charge-nowe o estorno têm anti-duplicidade embutido.- Webhooks trazem
X-Billing-Event-Idpara você deduplicar (a entrega é at-least-once).
Limites de uso (rate limit)
Cada rota tem o seu próprio limite por minuto. Ao exceder, você recebe 429. As rotas de
leitura são mais folgadas; as que movem dinheiro (estornar, cobrar, trocar plano) são mais
restritas. Um 429 não cobra nada: faça backoff e tente de novo. Para varrer muitos
registros, use a paginação por cursor em vez de repetir a mesma chamada em rajada.