Entenda a API
antes de chamar a API.
Este guia explica como o sistema pensa — as entidades, os fluxos de negócio, as convenções e a arquitetura por trás dos 148 endpoints. É documentação de verdade, não só uma lista de rotas: cobre o que cada domínio faz, por que existe, e o que observar ao integrar. Depois, entre para explorar e testar cada endpoint ao vivo.
Quickstart
O caminho mais curto entre não ter nada e fazer a primeira chamada autenticada com sucesso.
Autentique-se
Toda sessão de operador começa com POST /api/v1/auth, enviando username e password em JSON. A resposta traz um token JWT válido por 24 horas dentro de data.token.
Guarde e envie o token
Toda rota protegida por JWT espera o cabeçalho Authorization: Bearer <token>. Não existe refresh token — quando expirar, autentique-se novamente.
Leia a resposta padrão
Praticamente toda rota devolve o mesmo envelope: success (booleano), msg (mensagem legível) e data (o payload, ou null). Verifique sempre success antes de usar data — um 200 não garante success: true em todos os handlers mais antigos.
Explore com o playground
A partir daqui, a forma mais rápida de aprender um endpoint específico é entrar na Referência (topo da página) e testá-lo ao vivo — os campos de path, query e corpo já vêm preenchidos com valores de exemplo. Rotas GET chamam a API real, em modo só-leitura; POST/PUT/PATCH/DELETE ficam em modo simulação — o playground mostra exatamente o pedido que seria enviado, mas não grava nada na base de dados.
api-key, usada por integrações externas. A seção Autenticação detalha quando cada uma se aplica.Arquitetura
Toda escrita e leitura passa por uma única API Express em /api/v1. Quatro tipos de cliente consomem a mesma API; cada requisição atravessa autenticação, auditoria e cache antes de chegar à camada de domínio.
A camada de auditoria (aplicada por grupo de rotas — público, compartilhado, loja, restaurante, integrações) não é um registo de negócio: hoje ela apenas identifica a que domínio lógico a requisição pertence e escreve uma linha de log no formato [domain:restaurant] POST /pedidos/item/adicionar. É útil para observabilidade e para depurar o mapeamento de rotas entre módulos — não é um trilho de auditoria para compliance (não regista o utilizador, o corpo da requisição nem o resultado da operação).
A camada de cache tem duas implementações independentes que não se relacionam entre si: um cache em memória do próprio processo Node (usado exclusivamente pelas estatísticas públicas, com TTL de 1 hora) e uma infraestrutura genérica sobre Redis, pronta no código mas hoje não conectada a nenhuma rota. Se o Redis cair, o sistema degrada graciosamente e continua a funcionar sem cache — isso foi uma decisão de design explícita, não um efeito colateral.
Modelo de domínio
Entidade é o tenant raiz — um restaurante, uma loja, uma operação — do qual todos os outros domínios dependem. Usuários, catálogo, clientes, mesas, pedidos, caixa, faturação e relatórios existem sempre dentro do escopo de uma entidade.
Tabelas principais por domínio
Cada domínio da API corresponde a um pequeno conjunto de tabelas. Esta é a referência rápida para ler os exemplos de request/response com contexto:
| Domínio | Tabela(s) principal(is) | Chave de tenant | Observação |
|---|---|---|---|
| Entidade | entidade | — | Tenant raiz; restaurante, loja ou operação |
| Usuários & Login | glb_user, rest_utilizador | REST_ENTIDADE_ID | Duas tabelas de utilizador para dois módulos distintos (ver seção Catálogo & Clientes) |
| Produtos & Categorias | produto, pr_categoria, stock, pr_iva | Entidade_ID | Categoria é auto-relacionada via SELF_ID |
| Clientes | cliente | Entidade_ID | Cliente fiscal — não confundir com o perfil "online" |
| Mesas & Ambientes | rest_mesa, rest_ambiente | ENTIDADE_ID | Mesa pertence a um Ambiente |
| Pedidos | rest_pedido, rest_ites_pedido | ENTIDADE_ID | Item liga pedido + produto |
| Caixa | rest_fluxo_caixa, rest_auditoria_fluxo_caixa | usuario_id / ENTIDADE_ID | Sessão de operador, não gaveta física |
| Faturação & Vendas | venda, fatura_venda, rel_venda_produto, pagamento | Entidade_ID | Quatro caminhos de emissão convergem aqui |
| Delivery & Entregas | rest_pedido (TIPO=DELIVERY), rest_entregas, rest_tracking_motoboy | ENTIDADE_ID | Dois módulos (Entregas/Delivery) operam sobre o mesmo pedido |
| Relatórios & Estatísticas | views agregadas sobre as tabelas acima | entidadeId | Estatísticas públicas agregam todas as entidades |
Convenções
A API cresceu ao longo do tempo e nem todos os endpoints seguem exatamente o mesmo vocabulário. Em vez de esconder isso, aqui está o mapa das variações reais que você vai encontrar — para não confundir com erro de digitação.
Nomes de parâmetros
| Conceito | Variantes encontradas | Onde predomina |
|---|---|---|
| ID da entidade | entidadeId, entidadeID, Entidade_ID, entidade_id, entidade | entidadeId/entidadeID na maioria das rotas mais novas; entidade sozinho em rotas de mesas/produtos mais antigas |
| ID do usuário/operador | usuarioId, User_ID | usuarioId nas rotas de caixa; User_ID em cadastros mais antigos (produto, categoria) |
| Paginação | page + limit, ou pagina + limite | page/limit na maioria; pagina/limite só no marketplace |
Formato de resposta
O envelope padrão é { success, msg, data }, gerado por um helper único (respostaPadrao) usado na maioria dos handlers. Em rotas paginadas, data normalmente inclui total, page e totalPages ao lado da lista — mas confira sempre o exemplo de resposta de cada endpoint específico na Referência, já que o shape exato da paginação não é 100% uniforme entre domínios mais antigos e mais novos.
Datas
A maioria dos filtros de data aceita o formato DD-MM-AAAA (ex.: 01-06-2026), herdado do sistema original. Alguns endpoints mais recentes (relatórios, estatísticas de caixa) aceitam AAAA-MM-DD. O exemplo de valor preenchido em cada campo, na Referência, já usa o formato correto daquele endpoint específico.
Estados e situações usados nos exemplos
| Campo | Valores possíveis | Contexto |
|---|---|---|
SITUACAO (mesa) | LIVRE, OCUPADO, RESERVADO | Mesas |
SITUACAO (pedido) | RESGISTDO*, PROCESSANDO, PROCESSADO, EM ROTA, ENTREGUE, LIQUIDADO, CANCELADO | Pedidos, mesas, delivery |
STATUS_ENTREGA | ACEITA, COLETADO, A_CAMINHO_CLIENTE, ENTREGUE, CANCELADA | Delivery |
ESTADO (fatura/venda) | P (pendente/rascunho), A (ativo/concluído) | Faturação |
PAGO | 0 não pago · 1 parcial · 2 pago integral | Faturação |
TIPO (utilizador) | GARCOM, CAIXA, ONLINE, CHEFCOZINHA, MOTOBOY, GERENCIA | Utilizadores |
* RESGISTDO não é erro de digitação nesta página — é o valor literal gravado na base de dados em todo o sistema.
Autenticação
Existem dois mecanismos de autenticação, para dois públicos diferentes: um JWT para quem tem um utilizador humano por trás (POS de loja, POS de restaurante), e uma chave de API estática para integrações máquina-a-máquina.
O ciclo de vida do token
O login (POST /auth) valida username+password e devolve um JWT em data.token, assinado com validade fixa de 24 horas. O payload do token carrega apenas id, username e entidade — não carrega o tipo/papel do utilizador, então qualquer verificação de permissão precisa voltar a consultar a base de dados. Não existe refresh token: expirado o token, a única via é autenticar de novo.
Existe também um login de gerência (POST /auth/admin), que troca a password por um código de acesso curto (codigoAcesso) associado ao utilizador do tipo GERENCIA — pensado para autorizar operações sensíveis dentro do próprio restaurante (por exemplo, cancelar um item de pedido) sem exigir um segundo login completo.
O que cada código de erro significa aqui
| Status | Significado neste sistema |
|---|---|
| 400 | Faltam parâmetros obrigatórios no corpo/query — problema de payload, anterior a qualquer tentativa de autenticar. |
| 401 | Token ausente, mal formatado, expirado, ou credenciais de login incorretas. A mensagem distingue "Token expirado" de "Token inválido" para permitir ao cliente decidir se deve relogar. |
| 403 | Cabeçalho api-key ausente ou incorreto nas rotas que exigem chave de API. |
| 404 | O recurso referenciado (utilizador, entidade) não existe. |
Mesas & Pedidos
A operação de sala segue uma hierarquia de quatro níveis: Ambiente → Mesa → Pedido → Itens. Uma mesa passa por um ciclo previsível: livre → pedido → preparo → fatura → pagamento → caixa → livre novamente.
Duas formas de abrir um pedido
O fluxo direto é usado pelo garçom ou pelo caixa: cria o pedido diretamente informando quem é o responsável. O fluxo por QR code é pensado para o próprio cliente sentado à mesa: ele escaneia um código que expõe um PIN de 4 dígitos, gerado e persistido no momento em que a mesa é aberta para autoatendimento. O PIN não é de uso único — permanece válido por 60 minutos em produção (2 minutos em ambiente de desenvolvimento), permitindo que vários clientes na mesma mesa validem o mesmo código para lançar novos pedidos durante a refeição.
Estados de uma mesa
| Situação | Disparada por |
|---|---|
LIVRE | Estado inicial; também o destino quando não restam pedidos ativos após uma transferência |
OCUPADO | Criação de um pedido, ou validação bem-sucedida do PIN de QR code |
RESERVADO | Atribuição manual de reserva (responsável + data/hora) |
Um pedido nasce sempre no estado inicial da sua fila de preparo e percorre situações intermediárias até ser faturado ou cancelado. O cancelamento de um item específico (em vez do pedido inteiro) é tratado como uma operação sensível: exige o código de acesso de gerência antes de remover a linha.
Reserva e transferência de mesa
Uma reserva grava responsável, número de pessoas, evento (texto livre) e data/hora diretamente na mesa — não existe histórico de reservas, uma nova reserva substitui a anterior. A transferência de pedido move todos os pedidos ativos de uma mesa de origem para uma mesa de destino de uma só vez; não há seleção parcial de qual pedido transferir.
Caixa
Um "caixa", neste sistema, não é uma gaveta física — é a sessão de trabalho de um operador, com abertura, movimentações durante o turno e fechamento.
Abertura e operações do turno
A abertura exige um valor inicial e é protegida contra duas sessões simultâneas do mesmo operador. Durante o turno, três tipos de movimento podem ocorrer: venda (receita classificada por método de pagamento — dinheiro, cartão ou outros), suprimento (entrada de dinheiro que não é venda, tipicamente reforço de troco) e sangria (retirada de dinheiro do caixa, por exemplo para depósito).
Como o saldo teórico é calculado
saldoTeorico = valorInicial + totalSuprimentos − totalSangrias + totalDinheiroSó o dinheiro físico entra na conta — vendas em cartão ou outros métodos não afetam o saldo teórico da gaveta.
No fechamento, o operador informa o valor que contou fisicamente na gaveta; o sistema calcula a diferença entre esse valor e o saldo teórico e grava ambos no relatório de fechamento, junto com os eventos de auditoria da sessão (cada abertura, venda, suprimento, sangria e fecho gera uma linha própria num livro-razão append-only).
Relatórios disponíveis
| Endpoint | Para que serve |
|---|---|
GET /caixa/resumo | Visão para o momento do fecho — tempo aberto, faturas emitidas, últimas vendas e eventos |
GET /caixa/saldo | Saldo "ao vivo" do caixa aberto |
GET /caixa/dashboard | Duração da sessão, totais por método, eventos agregados |
GET /caixa/historico | Sessões passadas, filtráveis por status e data |
GET /caixa/relatorio-completo/:usuarioId | Visão de negócio de médio prazo — receita, ticket médio, produtos mais vendidos |
GET /caixa/operador/:usuarioId/relatorio | Relatório do último caixa (aberto ou fechado) de um operador específico |
GET /caixa/auditoria | Eventos brutos de uma sessão, sem agregação |
Auditoria de gerência (entidade inteira)
Os relatórios acima são sempre por operador ou por sessão específica. As duas rotas em /auditoria/caixa/* são diferentes: agregam todos os operadores e sessões de uma entidade de uma vez, e são a única forma de ver isso "de cima". Por isso têm um controlo de acesso próprio — não é só ter um JWT válido, o utilizador autenticado precisa de ser TIPO=GERENCIA (verificado na base de dados a cada pedido, não confiado ao token). A entidade consultada é sempre a do próprio gerente autenticado; não existe parâmetro entidadeId nestas rotas, propositadamente, para impedir consultar dados de outra entidade.
| Endpoint | Para que serve |
|---|---|
GET /auditoria/caixa/sessoes | Sessões de caixa (abertas e fechadas) de todos os operadores, paginado, filtrável por operador/status/data |
GET /auditoria/caixa/eventos | Livro-razão bruto (abertura/fecho/suprimento/sangria/venda) de todos os operadores, paginado, filtrável por operador/tipo de evento/data |
GERENCIA recebe 403 nestas duas rotas — o mesmo token que funciona em /caixa/* não é suficiente aqui.Faturação & Vendas
Não existe um único ponto de emissão de fatura — existem quatro, cada um com regras próprias, todos convergindo para as mesmas tabelas de venda, itens e pagamento.
De onde vem o preço cobrado
Em nenhum dos quatro caminhos o preço unitário gravado na fatura é obrigatoriamente o preço cadastrado do produto — na fatura de loja e na de restaurante, por exemplo, o preço e a taxa de imposto vêm do corpo da requisição, não de uma consulta ao cadastro. Isso dá flexibilidade (descontos pontuais, ajustes manuais) mas também significa que a validação de preço, se necessária, é responsabilidade de quem chama a API.
Pagamentos e estado da fatura
Um pagamento é sempre um array de { metodo_pagamento, valor_pagamento } (até 5 métodos por venda), e o estado PAGO é derivado automaticamente: 0 quando nada foi pago, 1 quando o valor pago é parcial, 2 quando cobre o total da fatura. Pagamentos no método especial de crédito são a exceção — não geram linha de pagamento nem tocam o caixa, servindo apenas para permitir uma venda a prazo.
O ciclo de vida de um rascunho
Um rascunho é uma venda em aberto: nasce com estado pendente, sem debitar stock, e pode ser editado (adicionar produto, ajustar quantidade, remover produto) enquanto permanece pendente. Existem duas formas de o concluir — registrar um pagamento real até zerar o valor em aberto, ou forçar o estado para concluído diretamente, sem exigir nem registar qualquer pagamento. Ambas promovem a venda ao estado final, mas apenas a primeira deixa rasto de pagamento.
Numeração e código fiscal
Cada fatura recebe um CODIGO_REFERENCIA composto pelo prefixo do tipo de fatura, o prefixo da série fiscal ativa da entidade, e um número sequencial — por exemplo FT-A-000123. A série fiscal e o tipo de fatura são configuráveis por entidade, o que permite que cada restaurante/loja tenha a sua própria numeração legal independente.
Delivery, Entregas & Marketplace
O marketplace calcula a cotação antes do pedido ser confirmado, despacha para um motoboy disponível, e expõe o rastreamento em tempo real por um código público — sem exigir login do cliente final.
Como a cotação é calculada
A distância entre o restaurante e o endereço de entrega é calculada por fórmula geográfica direta (Haversine), com um raio máximo de entrega de 20 km. A taxa cobrada é composta por uma taxa base (configurável por restaurante) mais um adicional apenas para a distância que exceder 5 km. O tempo estimado de entrega soma um tempo-base ao número de quilómetros — é uma heurística simples, sem considerar trânsito ou hora do dia.
Do checkout à entrega
O checkout público recalcula preço e imposto de cada item a partir do cadastro real do produto (ao contrário da faturação de loja, aqui o preço não é confiado ao payload) e gera um código de pedido público (formato DEL-AAAA-NNN), usado depois para rastreamento sem necessidade de login. A atribuição a um motoboy pode acontecer de duas formas: automaticamente, escolhendo o motoboy disponível com melhor avaliação média; ou manualmente, quando um operador escolhe explicitamente.
Ciclo de status da entrega
| Status | Significado |
|---|---|
ACEITA | Motoboy atribuído, ainda não coletou |
COLETADO | Pedido retirado do estabelecimento |
A_CAMINHO_CLIENTE | Em rota para o endereço de entrega |
ENTREGUE | Concluído |
CANCELADA | Entrega cancelada |
O rastreamento público expõe a última posição conhecida do motoboy e uma linha do tempo (atribuição → coleta → entrega) a partir apenas do código do pedido — pensado para que o cliente final acompanhe sem precisar de conta.
Catálogo, Clientes & Utilizadores
Produtos e categorias formam o cardápio; clientes e utilizadores respondem, cada um à sua maneira, à pergunta "quem está do outro lado".
Produtos e categorias
Um produto pode ser físico ou serviço — só produtos físicos geram uma linha correspondente na tabela de stock. O IVA nunca é um número solto: é sempre uma referência a uma taxa cadastrada, usada para calcular o preço com imposto em cada listagem. Categorias formam uma árvore de dois níveis (pai/filha) através de auto-relacionamento.
Dois modelos de cliente, não um
"Cliente" e "cliente online" são duas tabelas diferentes, não a mesma entidade vista de ângulos distintos. O cliente de faturação carrega dados fiscais (NIF, morada) e existe para efeitos de fatura. O "cliente online" é um perfil de consumidor de aplicativo (delivery/pedidos), sem dado fiscal, com histórico de pedidos e pontos de fidelidade. Não há, hoje, nenhuma chave que ligue automaticamente as duas — o mesmo consumidor real pode existir nos dois lugares sem relação entre si.
Tipos de utilizador
| Tipo | Papel |
|---|---|
GARCOM | Atende mesas, lança pedidos |
CAIXA | Processa pagamentos, opera sessões de caixa |
CHEFCOZINHA | Altera o estado do pedido na cozinha |
MOTOBOY | Entregador — único tipo com campos de geolocalização e disponibilidade |
GERENCIA | Autoriza operações sensíveis via código de acesso curto |
ONLINE | Perfil de cliente do aplicativo/marketplace |
Relatórios, Estatísticas & Integrações
Relatórios internos servem à gerência de cada entidade; estatísticas públicas alimentam o site institucional; a integração com o ERP externo Winoficinas mantém clientes, produtos e faturas sincronizados nos dois sentidos do negócio.
Relatórios internos vs. estatísticas públicas
Os relatórios internos (/relatorio/*) são sempre filtrados por entidade — cada restaurante/loja só enxerga o seu próprio recorte de vendas, funcionários e clientes. As estatísticas públicas (GET /stats) são o oposto: agregam todas as entidades e clientes do sistema, sem filtro e sem autenticação, pensadas para exibição institucional. Por serem cacheadas por 1 hora, os números podem estar levemente desatualizados — a resposta inclui um campo indicando se veio do cache, o que torna essa defasagem observável.
Integração com o ERP Winoficinas
Três rotas de sincronização (cliente, produto, fatura) existem em dois caminhos de URL simultaneamente: sob o prefixo normal do domínio e sob /winoficinas/* — não são duas implementações, é o mesmo handler exposto duas vezes, para deixar explícito no roteamento que aquele conjunto também serve à integração externa. Produtos e clientes referenciados pelo ERP que ainda não existem localmente são criados automaticamente durante a sincronização.
Erros & Status HTTP
A API não usa um único formato de erro em todos os lugares — a maioria segue o envelope padrão, mas vale conhecer a intenção geral de cada código de status.
| Status | Quando aparece |
|---|---|
| 400 | Parâmetro obrigatório ausente ou payload malformado |
| 401 | Token ausente, expirado ou inválido; credenciais de login incorretas |
| 403 | Chave de API (api-key) ausente ou incorreta |
| 404 | Recurso não encontrado (entidade, utilizador, pedido, fatura) |
| 500 | Erro não tratado no servidor — o envelope de resposta normalmente ainda traz success: false e uma mensagem |
error.message) em vez de uma mensagem genérica. Trate o campo msg/error como texto para exibir a um operador, não como um código estável para switch no seu código.Estatísticas da API
Uma leitura rápida da superfície da API: quantos endpoints cada domínio expõe, e como os métodos HTTP se distribuem entre eles.
Pronto para testar de verdade?
Entre com sua conta para acessar a referência completa dos 148 endpoints — playground de request/resposta ao vivo, e as notas de engenharia internas de cada domínio.
Documentação restrita do sistema demo