Common errors
Diagnose and fix the most frequent errors
Overview
This guide helps you fix the most common issues when calling the Conta Simples API. Errors are grouped by HTTP status.
Before opening a ticket, go through the diagnostic checklist at the end of this page.
Errors by endpoint
GET /statements/v1/credit-card
| Code | Description | Common meaning |
|---|---|---|
200 | OK | Success |
400 | Bad Request | Invalid parameters |
500 | Internal Server Error | Server error |
GET /attachments/v1/content/{attachmentId}
| Code | Description | Common meaning |
|---|---|---|
200 | OK | Success (binary body) |
404 | Not Found | Attachment does not exist |
Validation errors (400)
Symptoms
400 Bad Request- Invalid parameters in the request
Common causes for GET /statements/v1/credit-card
Cause: startDate or endDate is not YYYY-MM-DD.
Wrong:
{
"startDate": "01/01/2025",
"endDate": "31/01/2025"
}
Right:
{
"startDate": "2025-01-01",
"endDate": "2025-01-31"
}
Cause: The difference between startDate and endDate is more than 62 days.
Fix: Split into smaller ranges, e.g. two requests of 45 days each for a 90-day range.
Cause: limit is below 5 or above 100.
Fix: Use a limit between 5 and 100.
Cause: startDate, endDate, or limit is missing (for query or body as documented).
Fix: Send all required fields.
Cause: Invalid JSON where a body is used.
Check: double-quoted strings, commas between properties, matching braces. Validate with a JSON tool if needed.
Authentication errors (401)
Symptoms
401 Unauthorized- Messages about invalid, expired, or missing token
Causes and fixes
Cause: The access token exceeded its lifetime (usually 30 minutes).
Fix:
- Get a new token at
/oauth/v1/access-token - Implement refresh before expiry
if (tokenAge > expiresIn * 0.9) {
const token = await refreshToken();
}
Cause: Missing Authorization header.
Fix: Every request must include:
curl -X GET https://api-sandbox.contasimples.com/statements/v1/credit-card \
-H "Authorization: Bearer {TOKEN}" \
-H "Content-Type: application/json" \
-H "User-Agent: {your-app-name}/{version}"
Wrong:
Authorization: {TOKEN}
Authorization: bearer {TOKEN}
Authorization:Bearer {TOKEN}
Right:
Authorization: Bearer {TOKEN}
(space after Bearer, capital B)
Cause: Wrong API key or secret when requesting a token.
Fix: Check your secret store, confirm environment (Sandbox vs Production), and use the credentials page if you need to rotate.
Retry pattern for 401
async function requestWithAuthRetry(
method: string,
url: string,
options: RequestInit & { headers: Record<string, string> },
): Promise<Response> {
let response = await fetch(url, { method, ...options });
if (response.status === 401) {
invalidateTokenCache();
const newToken = await getFreshToken();
options.headers["Authorization"] = `Bearer ${newToken}`;
response = await fetch(url, { method, ...options });
}
return response;
}
Permission errors (403)
Symptoms
403 Forbidden- “No permission”, “Access denied”, “Insufficient scope”
Causes and fixes
Cause: Your credentials are not allowed to use this resource.
Fix: Check which scopes you have. If you need more, open a case via support.
Cause: Mixing Sandbox credentials with Production URL (or the opposite).
Fix: Make sure the base URL and credentials are from the same environment.
Cause: The request was sent without a User-Agent. Traffic without a recognizable user agent can be treated differently and may return a challenge.
Fix: Send a valid, descriptive User-Agent on every request.
Not found (404)
Symptoms
404 Not Found- Resource not found
For GET /attachments/v1/content/{attachmentId}
Cause: The attachmentId does not exist or was removed.
Fix: Confirm the id from the transaction, and that the transaction and attachment still exist.
Wrong:
GET /attachments/v1/content/
GET /attachment/att_abc123
Right:
GET /attachments/v1/content/att_abc123
Server errors (5xx)
Symptoms
500 Internal Server Error(or other 5xx)
What to do
Wait and retry
5xx can be temporary. Wait a few seconds and try again.
Use backoff
Exponential backoff so you do not hammer the service.
Log the incident
Note the time and the parameters you sent.
Open a ticket if it continues
If it still fails after 3–5 attempts, contact support.
Retry pattern for 5xx
const RETRYABLE_STATUS = new Set([500, 502, 503, 504]);
async function requestWithRetry(
method: string,
url: string,
maxRetries = 3,
options?: RequestInit,
): Promise<Response> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30_000);
const response = await fetch(url, {
method,
...options,
signal: controller.signal,
});
clearTimeout(timeout);
if (!RETRYABLE_STATUS.has(response.status)) {
return response;
}
} catch (err) {
if (!(err instanceof DOMException && err.name === "AbortError"))
throw err;
}
if (attempt < maxRetries - 1) {
const waitTime = 2 ** attempt + Math.random();
await new Promise((resolve) => setTimeout(resolve, waitTime * 1000));
}
}
throw new Error("Max retries exceeded");
}
Diagnostic checklist
Before you contact support:
- Base URL matches the environment (Sandbox / Production)
- Token is still within
expires_in(about 30 minutes) AuthorizationisBearer {TOKEN}with a spaceContent-Typeisapplication/jsonwhen a body is sent- JSON is valid
- Dates use
YYYY-MM-DD - Range is at most 62 days
limitis between 5 and 100- You retried after a short wait (for 5xx)
What to include with support
When you contact support, always include:
| Item | Description | Example |
|---|---|---|
| Timestamp | Exact time (UTC) | 2025-01-15T14:30:00Z |
| Environment | Sandbox or Production | Sandbox |
| Endpoint | Method and path | GET /statements/v1/credit-card |
| Status | HTTP status | 400 |
| Request | Redacted body or query | See below |
| Response | API response | See below |
Example of redacted payload
{
"startDate": "2025-01-01",
"endDate": "2025-01-31",
"limit": 50
}
{
"error": "Bad Request",
"message": "startDate format is invalid"
}
Never put tokens, secrets, or personal data in your report.
Links
Last updated today
Built with Documentation.AI