# Changelog

## Setembro de 2026

### 10 de setembro

**O formulário HTML agora envia um contêiner assinado.** Em vez de campos de cobrança separados — `data` (base64url do JSON) e `signature` (HMAC-SHA256 da string `data`). O endpoint mudou de `invoices/createFromForm` para `invoices/form`. Os formulários antigos não funcionam mais e precisam ser remontados: veja [Assinatura do formulário HTML](./creating-invoices/html-forms/form-signature.md).

### 8 de setembro

**Os campos numéricos no corpo do webhook agora são números.** Seis campos que antes eram enviados como strings agora são enviados como números: `project.commissionRate`, `invoice.commissionFiatUSD`, `invoice.amountFiatUSD`, `invoice.amountFiat`, `invoice.calcAmountFiat`, `payment.amount`. O conjunto de campos, os seus nomes e a sua ordem não mudaram.

Tenha em mente: zeros à direita são descartados, então um valor de 10.00 chega como 10. Valores abaixo de 0.0001 chegam em notação exponencial, por exemplo 1.0e-6 — o parse padrão de JSON retorna o número correto; só o parse manual de strings quebra.

As notificações montadas antes da atualização e ainda não entregues chegam no formato antigo. O receptor deve aceitar as duas variantes até a fila esvaziar — isso leva no máximo dois dias.

### 6 de setembro

**Os campos numéricos nas respostas da API agora são números.** Afeta `invoices/list`, `payments/list` e `invoices/create`.

| Campo               | Antes            | Depois |
| ------------------- | ---------------- | ------ |
| `commissionFiatUSD` | `"0.10"`         | `0.1`  |
| `amountFiatUSD`     | `"10.00"`        | `10`   |
| `amountFiat`        | `"1000.00"`      | `1000` |
| `views`             | `"0"`            | `0`    |
| `payment.amount`    | `"10.500000000"` | `10.5` |

**Uma chave restrita a um projeto agora aplica a restrição em todos os métodos.** Antes, alguns métodos ignoravam o projeto. Agora ela é um filtro nos métodos de listagem, e uma requisição para a cobrança ou carteira de outro projeto é rejeitada com `Restricted project`. Um método que não consegue respeitar a restrição de projeto fica fechado para essa chave. Os detalhes estão na seção “Escopo da chave”.

**A lista de pagamentos agora retorna pagamentos não vinculados.** Antes, `payments/list` retornava somente pagamentos ligados a uma cobrança. Agora os resultados incluem todos os pagamentos das suas carteiras; um não vinculado vem sem o bloco `invoice`. São exatamente os pagamentos necessários para a vinculação manual via `invoices/bindPayment`.

**O cancelamento de cobranças agora distingue os motivos de recusa.** Antes, tanto uma cobrança inexistente quanto condições não atendidas retornavam um `Invoice not found` genérico. Agora `Invoice not found` significa apenas que a cobrança não existe, enquanto condições não atendidas retornam `Invoice cannot be canceled`.

**Identificadores malformados agora são rejeitados.** `invoices/list` valida `invoiceId`, `invoiceUid` e `projectId`; `payments/list` — `walletId` e `invoiceId`. Um valor que não se encaixa retorna `Parameter is filled in incorrectly` com o nome do campo. Antes, esse parâmetro era descartado silenciosamente e os resultados voltavam sem o filtro.

**Os limites de período agora incluem o dia inteiro.** `startDate` e `endDate` são interpretados de `00:00:00` a `23:59:59`. Antes, o dia final era cortado por inteiro, e uma consulta de um dia retornava somente registros criados exatamente à meia-noite. Afeta `invoices/list`, `payments/list`, `statistics/invoices` e `statistics/payments`.

**Um campo de projeto foi adicionado ao histórico de saldo.** Cada operação no método `billing/history` agora carrega um campo `projectId`. Para operações no nível da conta — recargas e bônus — ele é `null`.

### 4 de setembro

**A descrição e os dados de serviço voltam na forma original.** Os campos `description` e `serviceData` eram guardados codificados, e nas respostas da API uma aspa chegava como `&quot;` e um sinal de menor como `<`. Agora é retornado exatamente o que o lojista enviou. Ao renderizar em HTML, faça o escape do valor do seu lado.

**Os formulários HTML aceitam somente POST.** Criar uma cobrança abrindo um link com parâmetros na barra de endereço não funciona mais — os parâmetros são lidos somente do corpo da requisição. Se você usava links, substitua-os por um formulário com `method="post"`.

### 3 de setembro

**As notificações de webhook agora são assinadas.** Foram adicionados os cabeçalhos `X-Timestamp` e `X-Signature`; a assinatura é calculada com HMAC-SHA256 sobre o segredo do webhook. Verificar a assinatura permite distinguir uma notificação genuína de uma falsificação. A mecânica e os exemplos estão na seção “Verificação da assinatura do webhook”.

A mudança é retrocompatível: se você não adicionar a verificação, o seu manipulador continua funcionando como antes.
