Introduction
The Collection Flow v1 API programmatically exposes everything the dashboard does in the collection operation: customers, charges, collection rules, agreements, disputes, tasks, imports, and webhooks.
This documentation is optimized for LLMs: the full Markdown index lives at /llms.txt and the API contract at /openapi/openapi-v1-en.yaml (-pt and -es variants in the same directory). Prefer those sources over scraping the HTML.
Format
The API accepts and returns JSON only (UTF-8). Send Content-Type: application/json on every request with a body.
| Field type | Format |
|---|---|
| Fields | camelCase in responses and request bodies (dueDate, documentNumber) |
| Dates | ISO 8601 in UTC. E.g.: 2026-07-23T12:00:00.000Z |
| Monetary amounts | Returned as decimal strings ("1500.00") to avoid precision loss; accepted as numbers in requests |
| List filters | Query string in snake_case (due_date_from, person_id) — see Pagination and filters |
Conventions
| Convention | Description |
|---|---|
:id | Path variable that must be replaced in the URL. |
... | Response content truncated for readability. |
$DUNNING_TOKEN | Your API key. To test from the command line, export it: export DUNNING_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxx and paste the documentation's commands into your terminal. |
Error envelope
Every error responds with a stable envelope — a human-readable message, a machine-stable code (and details when useful):
{
"message": "Permissão insuficiente",
"code": "FORBIDDEN"
}
Always branch on code (VALIDATION_ERROR, UNAUTHORIZED, FORBIDDEN, NOT_FOUND, CONFLICT, IDEMPOTENCY_KEY_REUSED, RATE_LIMITED, INTERNAL_ERROR...) — the message text can change without notice.
Response codes
The API uses standard HTTP status codes:
| Code | Description | |
|---|---|---|
| ✅ | 200 OK | Successful request with a response body. |
| ✅ | 201 Created | Resource created successfully. |
| ✅ | 204 No Content | Successful request, no response body. |
| ❌ | 400 Bad Request | Malformed request — invalid JSON, invalid idempotency header. |
| ❌ | 401 Unauthorized | API key missing, invalid, revoked, or expired. |
| ❌ | 403 Forbidden | Key lacks the required scope, or the resource is admin-only and not exposed via API. |
| ❌ | 404 Not Found | Resource or route does not exist (or belongs to another organization). |
| ❌ | 409 Conflict | State conflict — X-Idempotency-Key reuse, invalid transition. |
| ❌ | 422 Unprocessable Entity | Well-formed request whose data fails business validation. |
| ❌ | 429 Too Many Requests | Rate limit exceeded — wait for Retry-After. |
| ❌ | 5xx | Server error — see below for how to retry. |
5xx errors and retries
500, 502, 503, and 504 indicate a failure on our side, almost always transient. Your integration should:
- Retry with exponential backoff (e.g.: 1s, 2s, 4s, 8s...) and a cap on attempts — never in a tight loop.
- Use
X-Idempotency-Keyon mutations — the retry returns the original response instead of duplicating the operation. - Treat network timeouts as 5xx: not getting a response doesn't mean the operation didn't run; idempotency resolves the ambiguity.
On 429, wait the number of seconds in the Retry-After header before the next attempt.
Next steps
- Authentication — API keys and scopes.
- Endpoints — environments and base URLs.
- OpenAPI specifications — the full contract in OpenAPI 3.1.
- Rate limiting — limits and response headers.
- Pagination and filters — listings and iteration.
- Idempotency — safe retries on mutations.
- Webhooks — real-time events, no polling.