Skip to content

Error Structure

Default Format

All API errors Pontotel follow a format JSON consistent:

JSON
1
2
3
4
5
6
7
8
{
  "error": "validation_error",
  "message": "Dados inválidos na requisição",
  "details": {
    "email": ["Este campo é obrigatório."],
    "cpf": ["CPF inválido."]
  }
}
Field Type Description
error string Error code (snake case)
message string Readable message for humans
details object Details per field (where applicable)

HTTP Status Codes

Code Meaning When it occurs
200 OK Successful Request
201 Created Resource successfully created
204 In Content Successful deletion
400 Bad Request Invalid data or business rule
401 Unauthorized Missing, expired or invalid token
403 Forbidden No permission for the resource
404 Not Found Resource not found
409 Conflict Conflict (e.g. duplicate CPF)
429 Too Many Requests Rate limit exceeded
500 Internal Server Error Internal server error
503 Service Unavailable Scheduled maintenance

Errors by Category

400 — Validation

JSON
1
2
3
4
5
6
7
8
{
  "error": "validation_error",
  "message": "Um ou mais campos são inválidos",
  "details": {
    "cpf": ["CPF inválido. Verifique o formato."],
    "data_admissao": ["Este campo é obrigatório."]
  }
}

401 — Authentication

JSON
1
2
3
4
{
  "error": "authentication_failed",
  "message": "Token inválido ou expirado. Por favor, faça login novamente."
}

Solution: Log in again and get a new access_token.

403 — Authorisation

JSON
1
2
3
4
{
  "error": "permission_denied",
  "message": "Você não tem permissão para acessar este recurso."
}

Solution: Check if the user has the necessary permissions in the Pontotel portal.

404 — Not Found

JSON
1
2
3
4
{
  "error": "not_found",
  "message": "O recurso solicitado não foi encontrado."
}

409 — Conflict

JSON
1
2
3
4
5
6
7
{
  "error": "conflict",
  "message": "Já existe um empregado com este CPF neste empregador.",
  "details": {
    "cpf": ["CPF já cadastrado."]
  }
}

429 — Rate Limit

JSON
1
2
3
4
5
6
7
8
{
  "error": "rate_limit_exceeded",
  "message": "Você excedeu o limite de requisições",
  "limit": 500,
  "remaining": 0,
  "reset_at": "2025-02-09T15:00:00Z",
  "retry_after": 3600
}

Solution: Wait on retry_after (seconds) before you try again.

Code Treatment

Python
import requests

def fazer_requisicao(url, headers, payload=None):
    try:
        if payload:
            response = requests.post(url, json=payload, headers=headers)
        else:
            response = requests.get(url, headers=headers)

        if response.status_code == 401:
            # Token expirado — fazer login novamente
            raise TokenExpiredError("Refazer autenticação")

        elif response.status_code == 429:
            # Rate limit — aguardar
            retry_after = int(response.headers.get("Retry-After", 60))
            import time; time.sleep(retry_after)
            return fazer_requisicao(url, headers, payload)

        elif response.status_code >= 400:
            error = response.json()
            raise APIError(f"{error['error']}: {error['message']}")

        return response.json()

    except requests.exceptions.ConnectionError:
        raise APIError("Falha de conexão com a API")

==="JavaScript"

JavaScript
async function fazerRequisicao(url, options = {}) {
  const response = await fetch(url, options);

  if (response.status === 401) {
    throw new Error('Token expirado — refazer autenticação');
  }

  if (response.status === 429) {
    const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
    await new Promise(r => setTimeout(r, retryAfter * 1000));
    return fazerRequisicao(url, options);
  }

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`${error.error}: ${error.message}`);
  }

  return response.json();
}

Next Steps