Teto por chave de API | O limite que conta o gasto que chega depois
Teto de gasto que só olha a chamada deixa passar o débito que sai na decisão assíncrona. Por que limitar dinheiro e volume, por chave, e como a integração reage ao 429.
Foto: Chris Liverani, Unsplash
Um teto de gasto diário protege o cliente de uma API paga contra o dia em que alguma coisa sai do controle: uma chave vazada, um laço que reenvia a mesma chamada, um teste de carga apontado para produção por engano. O artigo sobre teto de gasto diário em uma API de verificação explica por que esse teto é do cliente, e não do fornecedor, e como avisar antes de cortar.
Este artigo trata de duas falhas que aparecem quando o teto já existe e mesmo assim não morde onde deveria. A primeira é medir só dinheiro, quando o que escapou foi volume. A segunda é contar o gasto na chamada, quando a cobrança de uma verificação assíncrona só acontece minutos ou horas depois, fora da requisição que a abriu.
Dinheiro e volume são eixos diferentes
O guia de segurança de API da OWASP, a fundação aberta de segurança de aplicações, trata o consumo sem limite como um dos dez riscos principais da edição de 2023, o API4:2023. Entre os limites cuja ausência torna uma API vulnerável, a lista traz o limite de gasto com provedores terceiros, e as recomendações pedem duas coisas separadas: limitar quantas vezes ou com que frequência um mesmo cliente pode executar uma operação, e configurar limite de gasto para toda integração com provedor de serviço, com alerta de cobrança quando o limite não for possível.
Separar os dois eixos tem razão prática. Um teto em dinheiro, sozinho, deixa passar um volume enorme de operações baratas antes de morder, e é exatamente esse o padrão de um laço de reenvio ou de um teste mal apontado: muitas chamadas, cada uma pequena. Um teto em número de operações, sozinho, não diz nada sobre o custo de um dia em que poucas operações caras entram no fluxo. Com os dois, o que chegar primeiro barra.
O gasto que chega depois da chamada
Numa API de verificação, boa parte do custo não nasce na requisição. A integração cria a sessão, o titular passa pelo fluxo no celular, e a decisão, que é quando a verificação é cobrada, sai depois, entregue por webhook. Se o teto por chave conta só o que acontece dentro da chamada, a chave que abriu mil sessões aparece no contador com zero gasto, e a conta chega no fim do dia sem dono.
A correção é atribuir o débito da decisão à chave que criou a sessão, e manter essa atribuição nos caminhos que derivam dela: a renovação de uma sessão expirada herda a chave original, e o link de verificação emitido por uma chave passa essa chave para a sessão que nasce dele. Sem isso, o teto por chave vale para o caminho curto e falha justamente no caminho assíncrono, que é o que concentra o custo.
A mesma lógica explica por que o teto é uma porta de admissão, e não um corte no meio do fluxo. Uma verificação já admitida segue até o fim e é cobrada quando termina; o teto barra a próxima sessão. Interromper uma verificação no meio pune o titular, que já mostrou o documento, e deixa o cliente com um caso pela metade.
O que devolver quando o teto morde
A resposta certa para quem bateu no teto é o código 429, definido na seção 4 da RFC 6585 para quando o cliente enviou requisições demais num período. A seção 10.2.3 da RFC 9110 completa com o cabeçalho Retry-After, que diz quanto tempo o cliente deve esperar antes de tentar de novo. Num teto diário, esse tempo é o que falta até a virada do contador.
Do lado de quem consome, o 429 de teto não é um erro para repetir em laço. Ele é um sinal de parar de abrir sessões até o horário indicado, e de avisar alguém. O artigo sobre limite de taxa em API mostra o lado de quem consome: respeitar o Retry-After e recuar em vez de insistir.
Na UNIFOKAL, por exemplo
O painel de operação guarda, no mesmo registro do orçamento, um teto em dinheiro e um teto de operações cobradas por dia, para a organização inteira ou para uma chave. A contagem de operações é a mesma do gasto: cada operação cobrada conta uma vez. Ao alcançar o teto de operações, a criação de sessão responde 429 volume_cap_reached, com Retry-After até 00:00 UTC; ao alcançar o de dinheiro, 429 spend_cap_reached. O painel avisa ao passar de 80% de qualquer um dos dois.
O gasto por chave conta as operações cobradas das sessões que a chave criou, inclusive quando a decisão sai depois, com a renovação e o link hospedado herdando a chave de origem. Apertar um teto vale na hora; afrouxar ou desligar passa a valer na virada do dia, para que uma sessão de painel indevida não consiga liberar o orçamento de hoje. O detalhe está na documentação do painel de operação.
Como escolher os números
O ponto de partida é o histórico. O teto de operações de uma chave deve ficar acima do pico real daquela integração, com folga para o crescimento esperado, e abaixo do que seria um dia anormal. Chaves separadas por integração tornam isso possível, porque cada uma ganha o teto do próprio uso; uma chave compartilhada por três sistemas obriga a escolher um número que não serve bem a nenhum.
Depois de escolhido, o número merece revisão periódica. Um teto que nunca chega perto de 80% está largo demais para pegar um incidente; um que dispara o aviso toda semana está apertado demais e vai virar ruído. O objetivo é que o aviso seja raro, e que o 429 seja mais raro ainda.
Fontes citadas
- OWASP API Security Top 10, edição de 2023, API4:2023 Unrestricted Resource Consumption: owasp.org
- RFC 6585, Additional HTTP Status Codes, IETF, seção 4, 429 Too Many Requests: rfc-editor.org
- RFC 9110, HTTP Semantics, IETF, seção 10.2.3, Retry-After: rfc-editor.org
- Documentação do painel de operação da UNIFOKAL: o orçamento, o teto de operações e os erros
spend_cap_reachedevolume_cap_reached.
