Adueladocumentação

A API, endpoint a endpoint

Esta referência gera-se da árvore de rotas que serve os pedidos, e não se escreve à mão. Um gerador que montasse as rotas à sua maneira descreveria uma API parecida com a verdadeira, e a diferença entre as duas só apareceria no código de quem já pagou.

Como autenticar

Duas formas, e chega uma. O cabeçalho Authorization: Bearer <token>, para quem escreve código contra a API, e o cookie httpOnly que o login põe, que é o que o navegador usa sozinho. O token sai de POST /api/v1/auth/login, e renova-se em POST /api/v1/auth/refresh antes de expirar.

Qual é a empresa

Uma instalação pode ter mais do que uma empresa, e quase todos os pedidos precisam de saber de qual se trata. A empresa ativa vem no token; para trocar, use POST /api/v1/empresas/{id}/ativar e continue com o token que essa chamada devolve. Um pedido sem empresa resolvida responde EMPRESA_INVALIDA, e não uma lista vazia: uma lista vazia era pior, porque parecia uma resposta.

O envelope, e os erros

Toda a resposta vem em {success, data, error}. Quando success é falso, o error.code vem de um catálogo fechado, e é por ele que se decide o que fazer. Nunca decida pelo texto da mensagem: o texto muda para ficar mais claro, e o código não muda nunca.

CódigoHTTPO que fazer
VALIDACAO422Um campo está mal. O erro traz o campo e a razão
NAO_AUTENTICADO401Renovar o token, ou voltar a entrar
SEM_PERMISSAO403A conta não tem a permissão, ou a licença não a inclui
NAO_ENCONTRADO404Não existe, ou não é desta empresa
CONFLITO409Já existe, ou o estado mudou entretanto
EMPRESA_INVALIDA400Ativar uma empresa antes de repetir
DEMASIADOS_PEDIDOS429Esperar o que o Retry-After disser
INTERNO500Do nosso lado. Repetir mais tarde, e dizer-nos

Paginação

As listagens paginam por cursor, e nunca por offset. Peça com ?limite=50 e siga o proximo_cursor que a resposta devolve, até ele vir vazio. Um offset numa lista que cresce enquanto se percorre salta linhas e repete outras, e ninguém dá por isso até faltar uma venda no relatório.

Limites de pedidos

O servidor limita por conta e por endereço. Ao ultrapassar, responde 429 com Retry-After em segundos. Respeite esse cabeçalho em vez de repetir logo: repetir num ciclo apertado é a forma mais rápida de ser travado por mais tempo.

Para escritas que não podem acontecer duas vezes (uma receção, um pagamento), mande Idempotency-Key com um valor seu. Um segundo pedido com a mesma chave devolve o resultado do primeiro em vez de fazer outro, e é isso que torna seguro repetir quando a rede caiu sem dizer se chegou.

Dinheiro e datas

O dinheiro viaja em texto ("1250.75"), e não como número: um float de JSON perde cêntimos, e um cêntimo perdido por linha é um balancete que não fecha. As datas são ISO 8601 em UTC.

Versões, e o que muda sem avisar

A versão está no caminho: /api/v1. Dentro de uma versão, só se acrescenta: campos novos numa resposta, parâmetros novos opcionais, endpoints novos. Tirar um campo, mudar o tipo de um, ou tornar obrigatório um parâmetro que não era, são mudanças que obrigam a /api/v2.

Por isso: ignore os campos que não conhece em vez de recusar a resposta. Um cliente que rebenta quando aparece um campo novo é um cliente que rebenta na próxima versão menor, e a culpa vai parecer nossa.

Quando uma versão passar a estar a caminho de sair, dizemo-lo aqui e no cabeçalho Sunset das respostas dela, com pelo menos seis meses de aviso. Hoje não há nenhuma nesse estado: a v1 é a única, e é estável.

Um exemplo que corre

Contra uma instalação de balcão em localhost:8080, ou contra https://api.aduela.net na nuvem. Precisa de curl e de jq.

# 1. Entrar, e guardar o token
TOKEN=$(curl -s -X POST http://localhost:8080/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@exemplo.ao","password":"a-sua-palavra-passe"}' \
  | jq -r '.data.tokens.acesso')

# 2. Perguntar quem sou, e que empresa está ativa
curl -s http://localhost:8080/api/v1/auth/eu \
  -H "Authorization: Bearer $TOKEN" | jq '.data.utilizador.nome'

# 3. Listar os primeiros artigos do catálogo
curl -s 'http://localhost:8080/api/v1/armazem/produtos?limite=5' \
  -H "Authorization: Bearer $TOKEN" | jq '.data.itens[].nome'

A referência completa