# Receita: créditos de API

> Venda créditos pré-pagos para uma API ou uma função de IA e desconte um por chamada. Se o saldo não der, responda 402 com um link de recarga.

Os compradores pagam adiantado um pacote de créditos; cada chamada gasta alguns. O Perly Pay faz a conta: o gasto é uma única chamada atômica que não fica abaixo de zero, e cada comprador tem a própria página de recarga. Nada é cobrado sozinho: quando os créditos acabam, o comprador recarrega. Tudo sobre créditos está em [Sell credits](https://pay.perly.io/docs/credits.md); aqui, a receita em volta.

> **Nota:** Com um assistente: a skill `sell-credits` do plugin do Perly Pay faz esta receita no seu projeto. O exemplo executável é `examples/api-credits` (MIT) no repositório do plugin.

## Como funciona

1. **Um pacote de créditos** — Um produto e um preço com `model: "credit_pack"`, `unit_amount` em centavos e `credits`. Uma vez por modo.
2. **Seus usuários são clientes** — Criados uma vez com `external_id` (o seu id de usuário); depois, `credits.*` aceitam esse id.
3. **Recargas** — `credits.topUpUrl(userId)` é a página do próprio comprador: ele escolhe um pacote e paga. Cada pacote pago soma créditos.
4. **Gasto por chamada** — Primeiro `credits.consume(userId, cost, { idempotencyKey })`, depois o trabalho. Uma nova tentativa com a mesma chave devolve o primeiro gasto, então a chave de cada chamada é gerada pelo seu servidor e nunca vem de quem chama.
5. **Não deu?** — `insufficient_credits` (409) não gasta nada: responda `402` com a página de recarga, não um 500.

**Spend one request's credits**

```js
try {
  await pay.credits.consume(userId, cost, { product: PRODUCT, action: "api", idempotencyKey: `req-${userId}-${requestId}` });
} catch (e) {
  if (e.code !== "insufficient_credits") throw e;
  return reply(402, { top_up: await pay.credits.topUpUrl(userId, { product: PRODUCT }) });
}
// now do the work
```

## Execute o exemplo

1. **Instale** — `npm install` em `examples/api-credits` (Node 20.12+).
2. **Chave** — Copie `.env.example` para `.env` e coloque uma chave de teste (`sk_test_…`) em `PERLY_PAY_SECRET_KEY`.
3. **Prepare** — `npm run setup` cria o produto e o preço com a sua chave e imprime os ids deles para o `.env`.
4. **Execute** — `npm start` (ou `npm run dev`), como diz o README dele.
5. **Pague sem carteira** — Chame `POST /v1/shout` (402), abra a página que `POST /top-up` devolve, escolha um pacote, clique em **Simulate payment** na fatura e chame de novo: 200 e `X-Credits-Remaining: 499`.

## Erros comuns

- Gastar sem chave de idempotência: uma chamada repetida desconta duas vezes.
- Tirar a chave do gasto do que o cliente envia (um cabeçalho `Idempotency-Key`): a mesma chave devolve o primeiro gasto como sucesso e o cliente recebe o trabalho de novo sem pagar.
- Consultar o saldo e depois gastar em dois passos. `consume` já impede ficar abaixo de zero; o saldo é para mostrar.
- Primeiro o trabalho, depois o gasto. É o contrário: primeiro o gasto.
- Ids de teste com uma chave de produção. Produtos, preços e webhooks pertencem a um modo: antes de entrar em produção, repita a configuração com `sk_live_…`.
