You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+34-1Lines changed: 34 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -358,6 +358,27 @@ for sale in client.sales.history_autopaginate(buyer_name="Paula"):
358
358
359
359
The iterator stops when there are no more pages — no token management, no loop conditions.
360
360
361
+
### Processing pages individually
362
+
363
+
If you need to act at the end of each page — flush a batch to a database, save a checkpoint, update a progress bar — use the single-page method and control the loop yourself:
Use `*_autopaginate` when you only need to iterate all records. Use the manual loop when you need to act between pages.
381
+
361
382
---
362
383
363
384
## Sandbox Mode
@@ -418,7 +439,19 @@ Exception hierarchy:
418
439
|`APIStatusError`| other | Unexpected HTTP status |
419
440
|`HotmartError`| — | Base class for all SDK errors |
420
441
421
-
The SDK retries automatically on transient errors (5xx, 429) with exponential backoff (`0.5 × 2^attempt + jitter`, cap 30s). Configure via `max_retries`:
442
+
### Retry behavior
443
+
444
+
Not all errors are equal — the SDK handles them differently before raising:
445
+
446
+
| Behavior | Exceptions |
447
+
|----------|-----------|
448
+
|**Retried with exponential backoff** — raised only after all retries are exhausted |`RateLimitError` (429), `InternalServerError` (500, 502, 503) |
449
+
|**Triggers token refresh + one automatic retry** — never raised for an expired token |`AuthenticationError` from 401 |
450
+
|**Raised immediately, no retry**|`BadRequestError` (400), `AuthenticationError` from 403, `NotFoundError` (404), `APIStatusError`|
451
+
452
+
In practice: a `RateLimitError` in your `except` block means Hotmart was still returning 429 after all retries. An `AuthenticationError` means your credentials are genuinely invalid, not just that a token expired mid-run.
453
+
454
+
Backoff formula: `0.5s × 2^attempt + jitter` (jitter 0–0.5s, cap 30s). For 429, the `RateLimit-Reset` header is used directly when present. Configure the number of retries via `max_retries`:
Copy file name to clipboardExpand all lines: docs/CHANGELOG.md
+11Lines changed: 11 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,17 @@ O formato segue [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) e o pro
6
6
7
7
---
8
8
9
+
## [1.0.4] - 2026-03-28
10
+
11
+
Versão de manutenção com melhorias de documentação. Nenhuma mudança no código da biblioteca.
12
+
13
+
### Changed
14
+
15
+
- Seção "Processing pages individually" adicionada ao README (EN e PT-BR): padrão de loop manual com `page_token` para processamento página a página com efeitos colaterais (checkpoint, batch flush, etc.)
16
+
- Seção "Retry behavior" expandida no README (EN e PT-BR): tabela clara de quais erros são reprocessados automaticamente, quais disparam renovação de token e quais são lançados imediatamente
Copy file name to clipboardExpand all lines: docs/README-ptBR.md
+34-1Lines changed: 34 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -357,6 +357,27 @@ for venda in client.sales.history_autopaginate(buyer_name="Paula"):
357
357
358
358
O iterador para automaticamente quando não há mais páginas — sem gerenciamento de token, sem condições de loop.
359
359
360
+
### Processamento página a página
361
+
362
+
Se você precisar agir ao final de cada página — salvar um checkpoint, enviar um batch para o banco, atualizar uma barra de progresso — use o método de página única e controle o loop manualmente:
363
+
364
+
```python
365
+
page_token =None
366
+
whileTrue:
367
+
pagina = client.sales.history(start_date=1700000000000, page_token=page_token)
368
+
369
+
for venda in pagina.items:
370
+
processar(venda)
371
+
372
+
salvar_checkpoint(page_token) # efeito colateral por página
Use `*_autopaginate` quando precisar apenas iterar todos os registros. Use o loop manual quando precisar agir entre páginas.
380
+
360
381
---
361
382
362
383
## Modo Sandbox
@@ -417,7 +438,19 @@ Hierarquia de exceções:
417
438
|`APIStatusError`| outros | Status HTTP inesperado |
418
439
|`HotmartError`| — | Classe base para todos os erros do SDK |
419
440
420
-
O SDK realiza retentativas automáticas em erros transitórios (5xx, 429) com backoff exponencial (`0.5 × 2^attempt + jitter`, cap 30s). Configure via `max_retries`:
441
+
### Comportamento de retentativas
442
+
443
+
Nem todos os erros são tratados da mesma forma — o SDK age diferente antes de lançar cada um:
444
+
445
+
| Comportamento | Exceções |
446
+
|---------------|---------|
447
+
|**Reprocessado com backoff exponencial** — lançado apenas após esgotar todas as tentativas |`RateLimitError` (429), `InternalServerError` (500, 502, 503) |
448
+
|**Dispara renovação de token + uma nova tentativa automática** — nunca lançado por token expirado |`AuthenticationError` originado de 401 |
449
+
|**Lançado imediatamente, sem retentativa**|`BadRequestError` (400), `AuthenticationError` de 403, `NotFoundError` (404), `APIStatusError`|
450
+
451
+
Na prática: um `RateLimitError` no seu `except` significa que a Hotmart continuou retornando 429 mesmo após todas as tentativas. Um `AuthenticationError` indica credenciais genuinamente inválidas — não simplesmente um token expirado no meio da execução.
452
+
453
+
Fórmula do backoff: `0.5s × 2^attempt + jitter` (jitter 0–0.5s, cap 30s). Para 429, o header `RateLimit-Reset` é usado diretamente quando presente. Configure o número de tentativas via `max_retries`:
0 commit comments