Convenções da API
Regras válidas para todos os endpoints sob /v1/*. Cada endpoint individual pode acrescentar regras específicas, mas nunca contradiz o que está aqui.
URL base e versionamento
https://api.sacador.com.br/v1/<recurso>
A versão (v1) está no path. Quebras de contrato → nova versão (v2); adições retrocompatíveis (novos campos, novos endpoints) entram na v1 sem aviso.
Autenticação
Todas as requisições exigem header:
Authorization: Bearer sct_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Accept: application/json
Detalhes do token, criação e revogação: ver authentication.md.
Content type
- Requisições com corpo (
POST/PATCH/PUT): envieContent-Type: application/jsonouapplication/x-www-form-urlencoded. Os dois são aceitos. - Respostas: sempre
application/json; charset=utf-8.
Status codes
| Code | Quando |
|---|---|
200 OK | GET, PATCH, POST/cancel e POST/pay_off bem-sucedidos. Também o POST repetido com a mesma reference nos endpoints idempotentes, ver Idempotência |
201 Created | POST que criou o recurso |
204 No Content | DELETE bem-sucedido — corpo vazio |
400 Bad Request | JSON malformado |
401 Unauthorized | Header Authorization ausente, mal-formado ou com token desconhecido/revogado |
403 Forbidden | Token válido, mas a conta dona do token está com status diferente de active (overdue, locked, canceled) ou ainda não teve a verificação de cadastro (KYC) aprovada. Nos endpoints do PDV (vendas, créditos do cliente, baixa por repasse), também quando a conta não ativou o módulo PDV |
404 Not Found | Recurso inexistente ou pertencente a outra conta — o Sacador não diferencia os dois casos, para não vazar a existência de registros de outras contas |
409 Conflict | reference já usada com dados diferentes, nos endpoints idempotentes |
422 Unprocessable Content | Falha de validação, parâmetro obrigatório ausente ou regra de negócio recusada |
429 Too Many Requests | Limite de requisições excedido — ver seção Rate limit |
500 Internal Server Error | Erro inesperado no Sacador. Retentar com backoff |
Formato de erro
Toda resposta 4xx retorna JSON em um destes formatos:
Erros de validação ou autorização lógica (422):
{
"status": 422,
"errors": [
"Descrição não pode ficar em branco",
"CPF inválido"
]
}
errors é sempre um array de strings (já localizadas em português). Cada string é uma mensagem independente e exibível ao usuário final.
Erros de autenticação, autorização e roteamento (401, 403, 404):
{
"status": 401,
"message": "Unauthorized"
}
Recusas de regra de negócio (409 e alguns 422): o mesmo corpo { status, message }, às vezes com um terceiro campo, code:
{
"status": 422,
"message": "Contato não encontrado nesta conta.",
"code": "contact_not_found"
}
message é texto em português para exibir ou registrar em log e pode mudar de redação. code é um identificador estável, para o seu sistema decidir o que fazer sem interpretar texto. Ele só aparece nos casos que o integrador precisa distinguir dos demais erros do mesmo status; quando não vier, trate o erro pelo status. Os valores de hoje:
code | Status | Endpoint | Significado |
|---|---|---|---|
contact_not_found | 422 | POST/v1/store_credits | O contato informado não existe nesta conta. Cadastre ou vincule o contato e reenvie |
settlement_contact_missing | 422 | POST/v1/receivable_settlements | A loja não configurou o contato pagador da baixa. Retentar não resolve até a loja ajustar a configuração |
Novos valores de code podem surgir sem mudança de versão. Trate um code desconhecido como um erro comum daquele status.
Rate limit (429):
{
"error": "Excedido o limite de requisições. Por favor, tente novamente mais tarde."
}
Acompanhado do header Retry-After: .
Paginação
Todos os endpoints GET /v1/ (listagens) são paginados. Os parâmetros de paginação são query params — não use headers.
Query params
| Param | Default | Valor aceito | Comportamento fora da faixa |
|---|---|---|---|
page | 1 | Inteiro ≥ 1 | Valores menores que 1 ou inválidos são tratados como página 1 |
per_page | 25 | Inteiro entre 1 e 100 | Valores > 100 são limitados a 100; 0, negativo ou não-numérico cai para o default 25 |
Exemplo:
GET /v1/contacts?page=2&per_page=50
Response headers
Toda listagem retorna os mesmos quatro headers:
| Header | Significado |
|---|---|
X-Total-Count | Total de registros (já considerando os filtros aplicados) |
X-Page | Página retornada nesta resposta |
X-Per-Page | Tamanho efetivo da página (já clampado para [1, 100]) |
X-Total-Pages | Número total de páginas |
Os totais consideram apenas os registros da sua conta — o isolamento é aplicado antes da contagem.
Estratégia recomendada
1. Inicialize page = 1
2. Faça GET com page atual
3. Processe os items
4. Se page >= X-Total-Pages → fim
5. Senão page += 1 e volte a 2
Para sincronizações periódicas, prefira combinar paginação com os filtros de data (start_created_at / end_created_at quando disponíveis) para limitar a varredura ao intervalo novo.
Rate limit
Duas contagens rodam ao mesmo tempo sobre todas as rotas /v1/*. A requisição é barrada quando qualquer uma das duas estoura:
| Contador | Limite | Chave |
|---|---|---|
| Por origem | 300 requisições por minuto | IP de onde a requisição partiu |
| Por credencial | 600 requisições por minuto | Token usado no Authorization |
- O contador por credencial existe para que um token replicado em várias máquinas não escape do limite por IP.
- Quando excedido:
429com headerRetry-Afterem segundos. Espere e retente — não há janela deslizante, o contador zera no início do próximo minuto-cheio. - Se múltiplos sistemas integrados saem do mesmo IP, o limite por origem é compartilhado entre eles. Para volumes maiores, distribua a integração em IPs distintos ou abra um canal com o Sacador.
Conta ainda não verificada
A API só responde a contas com a verificação de cadastro (KYC) aprovada. Enquanto a aprovação não
sai, toda requisição — em qualquer rota /v1/*, com token válido — recebe 403:
{
"status": 403,
"message": "Esta funcionalidade fica disponível depois que a documentação da conta for enviada e aprovada."
}
Não há limite reduzido, modo restrito nem sandbox: ou a conta está aprovada e a API funciona
inteira, ou não está e nada funciona. O Sacador aplica limites menores a contas não verificadas
(quantidade de contatos, de tags e de cobranças, e teto de valor por cobrança), mas eles valem para o
uso pela tela — uma integração nunca chega a esbarrar neles, porque não passa do 403.
Verifique a conta antes de começar a integrar: o envio dos documentos e o status ficam em /account_verification.
Filtros e busca
Endpoints de listagem que aceitam s (search) interpretam a string como LIKE substring do lado do servidor. Não há sintaxe especial — s=joão retorna registros contendo "joão" no campo indexado para busca daquele recurso. Veja cada endpoint para saber em qual campo a busca é aplicada.
Multi-tenancy
Toda requisição é automaticamente restrita à conta dona do token. Você não consegue:
- Ler, criar, atualizar ou apagar registros de outra conta.
- Atribuir
account_idemPOST/PATCH— esse parâmetro é silenciosamente ignorado e sempre forçado para a conta autenticada. - Referenciar IDs de outra conta em FKs (
contact_id,tag_id,bank_rule_id,bank_account_id). Tentativas retornam422com erro de associação.
Recursos de outra conta acessados por ID direto retornam 404, idêntico ao caso de ID inexistente.
Idempotência
Dois endpoints aceitam uma chave de idempotência no corpo, o campo reference, única por conta:
- POST
/v1/store_credits: mesmareferencecom o mesmo contato e valor devolve200com o registro original; com outros dados,409. - POST
/v1/receivable_settlements: mesmareferencecom o mesmocutoff_atdevolve200com o estado da baixa original (ou202, retomando uma baixa que falhou); com outro corte,409.
Nesses dois, retentar depois de um timeout é seguro: reenvie o mesmo corpo com a mesma reference.
Os demais endpoints não implementam chave de idempotência. Em caso de timeout, antes de retentar um POST, consulte o GET correspondente (busque pelo your_code que você gerou, por exemplo) para detectar criação duplicada.
Boas práticas
- Idempotência: ver a seção própria.
- Backoff em 5xx e 429: use exponencial com jitter. Em
429, respeite oRetry-After. - Não dependa de campos não documentados. Campos não listados na referência podem mudar formato ou ser removidos sem aviso.
- Versione seus payloads. O Sacador pode adicionar campos nas respostas. Faça parsing tolerante a chaves desconhecidas.
- Use
your_codecomo chave de correlação com o seu sistema, e busque por ele depois — é um campo livre indexável (até 20 chars).