API TechBull Sistemas
Conecte seu ERP, e-commerce ou aplicativo próprio diretamente ao TechBull. Esta documentação cobre autenticação, vendas, clientes, produtos, títulos a receber e a pagar e entidades de apoio.
Começando
Introdução
Para integrar com o TechBull, o fluxo básico é:
- Fazer login com email e senha para obter um
tokende sessão. - Enviar esse token em todas as próximas chamadas (via
CookieouAuthorization, conforme a rota). - Consumir os endpoints aos quais o seu usuário tem permissão (configurada pelo admin da holding).
Base URL e formato
Todas as rotas estão sob o domínio do app principal:
https://app.techbullsistemas.com.br
Os exemplos abaixo usam paths relativos como /api/venda — basta concatenar com a base URL.
- Conteúdo enviado e recebido:
Content-Type: application/json. - Datas em ISO-8601 (UTC), por exemplo
2026-04-19T12:00:00.000Z. - Códigos HTTP padrão (200, 400, 401, 403, 404, 422, 500).
Convenções
Embora muitos exemplos no código TypeScript usem camelCase, a serialização final das respostas é feita em snake_case. Espere campos como cd_empresa, nr_prevenda, id_situacao, prevenda_item.
Para os parâmetros de entrada (body/query), ambas as convenções funcionam dependendo da rota — siga os exemplos desta documentação.
Códigos HTTP usados pela API:
200/201— sucesso.400— erro de validação (campos faltando ou inválidos).401— não autenticado (sessão ausente ou expirada).403— autenticado mas sem permissão para a ação.404— recurso não encontrado.409— conflito (ex.: violação de chave estrangeira).422— entidade não processável.500— erro interno.
Autenticação
Visão geral
Após o login você recebe um token que precisa ser enviado nas próximas requisições. Existem duas formas conforme o tipo da rota:
Authorization: Bearer <token>Cookie: session_id=<token>O valor é exatamente o mesmo. Você pode armazenar o token uma única vez e enviá-lo como Authorization: Bearer ao chamar /api/mobile/* e como cookie session_id ao chamar as demais rotas (vendas, produtos, clientes, títulos, etc.).
Fazer login
/api/mobile/auth/loginAutentica usuário com email e senha e retorna o token da sessão, o ID da sessão, a data de expiração e os dados básicos do usuário.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
email | string | Sim | Email do usuário cadastrado. |
senha | string | Sim | Senha do usuário. |
timezone | string | — | Fuso horário IANA. Padrão America/Sao_Paulo. |
Exemplo de requisição
Resposta — 200 OK
O token tem validade de 30 dias. Trate-o como uma senha — não exponha em URLs nem em logs.
Obter usuário autenticado
/api/mobile/auth/meRetorna informações do usuário associado ao token. Útil para validar se o token continua válido.
Fazer logout
/api/mobile/auth/logoutInvalida o token de sessão atual no servidor.
Permissões
Cada rota da API exige uma feature (string identificadora) que o usuário precisa ter habilitada. Por exemplo:
vendas:consultar— listar vendas.vendas:efetivar— efetivar pré-venda em venda.clientes:cadastrar— criar novos clientes.titulosReceber:consultar— listar títulos a receber.caixa:recebimentoTitulo— dar baixa em títulos.
O administrador da holding (usuário 1) tem todas as features e é responsável por habilitar permissões para os demais usuários através do painel administrativo. Cada endpoint nesta documentação indica a permissão necessária no badge laranja.
Se uma chamada retornar 403 ForbiddenError com "Usuário não autorizado a realizar esta ação", peça ao admin da holding para conceder a feature correspondente ao seu usuário.
Listar catálogo de features
/api/featureLista todas as features disponíveis no sistema. Útil para que o admin saiba quais permissões pode conceder.
Vendas e Pré-vendas
Conceito e ciclo de vida
A entidade principal é a prevenda. O campo id_situacao identifica o estado:
ABAberta — pré-venda em rascunho, ainda editável.
EFEfetivada — venda concretizada, com nota fiscal e títulos.
CACancelada — pré-venda cancelada ou venda estornada.
Fluxo típico: POST /api/venda (cria em AB) → POST /api/venda/efetivar (move para EF) → opcionalmente POST /api/venda/estornar (volta para CA).
Listar vendas
/api/vendaLista pré-vendas e vendas com filtros e paginação. Use idSituacao para filtrar por estado.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | — | Filtra por empresa. |
idSituacao | string | — | AB, EF ou CA. |
dtIni | date (YYYY-MM-DD) | — | Data inicial. |
dtFim | date (YYYY-MM-DD) | — | Data final. |
cdFuncionario | number | — | Vendedor responsável. |
cdTipoVenda | number | — | Tipo de venda. |
cdFormaPagamento | number | — | Forma de pagamento. |
page | number | — | Página (default 1). |
limit | number | — | Itens por página (default 50). |
Resposta — 200 OK
Criar pré-venda
/api/vendaCria uma pré-venda em situação AB. Se enviar efetivar_venda: true, a venda já é efetivada na mesma chamada (requer também a feature vendas:efetivar).
Body parameters principais
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cd_empresa | number | Sim | Código da empresa. |
cd_cliente | number | Sim | Código do cliente. |
cd_funcionario | number | Sim | Vendedor. |
id_situacao | string | Sim | Use "AB" para criar em aberto. |
vl_total | number | Sim | Valor total da venda. |
vl_bruto | number | Sim | Valor bruto antes de descontos. |
cd_forma_pagamento | number | Sim | Forma de pagamento principal. |
cd_tipo_venda | number | Sim | Tipo da venda. |
prevenda_item | array | Sim | Itens da venda (produtos, quantidade, valores). |
prevenda_titulo | array | Sim | Títulos a receber gerados. |
prevenda_forma_pagamento | array | Sim | Detalhamento das formas de pagamento. |
efetivar_venda | boolean | — | Se true, efetiva já na criação. |
Exemplo de requisição
Resposta — 200 OK
Atualizar pré-venda
/api/vendaAtualiza uma pré-venda existente. Substitui itens, títulos e formas quando enviados. Requer nr_prevenda.
O body é o mesmo do POST, com nr_prevenda obrigatório. Pode incluir efetivar_venda: true para atualizar e efetivar na mesma chamada.
Cancelar pré-venda
/api/vendaCancela uma pré-venda em aberto. Não funciona em vendas já efetivadas (use /api/venda/estornar).
Efetivar venda
/api/venda/efetivarEfetiva uma pré-venda em aberto: gera a nota fiscal de saída, títulos a receber, movimenta caixa, estoque e crédito do cliente. A pré-venda passa para EF e recebe nr_nota e serie_nota.
Resposta — 200 OK
Pré-requisito: o caixa da empresa deve estar aberto. Caso contrário a API retorna "Caixa não encontrado".
Estornar venda
/api/venda/estornarEstorna uma venda já efetivada (EF): cancela a nota fiscal, reverte estoque, títulos, caixa e crédito. A pré-venda passa para CA e nr_nota/serie_nota são limpos.
Editar venda efetivada
/api/venda/update-efetivadaAjusta dados não-financeiros de uma venda já efetivada (tipo de venda, observação, vendedor, vendedores auxiliares), espelhando na nota fiscal quando existir.
Atualizar formas de pagamento
/api/venda/updateFormaPagamentoAtualiza as formas de pagamento, títulos e totais de uma venda (ex.: cliente decide parcelar diferente).
Clientes
Listar clientes
/api/clienteApenas autenticação é exigida (sem permissão específica).
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | IDs separados por vírgula. |
name | string | — | Busca por nome. |
cpf | string | — | CPF/CNPJ. |
fone | string | — | Telefone. |
cdCidade | number | — | Código da cidade. |
periodoAniversarioIni | date | — | Início do período de aniversário. |
periodoAniversarioFim | date | — | Fim do período de aniversário. |
vlCreditoClienteMin | number | — | Crédito mínimo. |
vlCreditoClienteMax | number | — | Crédito máximo. |
orderBy[field] | string | — | Campo de ordenação. |
orderBy[direction] | asc | desc | — | Direção da ordenação. |
page | number | — | Página. |
limit | number | — | Itens por página. |
Criar cliente
/api/clienteCria um novo cliente. Aceita endereço, dependentes (clienteDependente) e anexos (clienteAnexo) opcionais.
Campos obrigatórios
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | Sim | Empresa de origem do cadastro. |
nmCliente | string | Sim | Nome ou razão social. |
tpPessoa | "F" | "J" | Sim | Pessoa Física ou Jurídica. |
cdCategoria | number | Sim | Categoria do cliente. |
cdSituacaoCliente | number | Sim | Situação cadastral. |
idTipoCliente | string | Sim | Tipo de cliente. |
vlLimiteCredito | number | Sim | Limite total de crédito. |
vlLimiteDisponivel | number | Sim | Limite disponível atual. |
vlCreditoDevolucao | number | Sim | Crédito por devoluções. |
cpf | string | — | CPF (PF) ou CNPJ (PJ), apenas dígitos. Valida o dígito verificador. |
fone | string | — | Telefone fixo (até 15 caracteres). |
celular | string | — | Telefone celular (até 15 caracteres). |
email | string | — | E-mail (até 60 caracteres). |
idSexo | "M" | "F" | — | Sexo. Use "M" ou "F" (e não sexo). |
dtNascimento | string (ISO-8601) | — | Data de nascimento como string ISO-8601, ex.: "1990-04-19T00:00:00.000Z". |
endereco / bairro / cdCidade / cep | string / number | — | Dados de endereço (todos opcionais). |
clienteDependente | array | — | Dependentes do cliente (opcional). |
clienteAnexo | array | — | Anexos (opcional). |
- Use
idSexo, nãosexo. dtNascimentoprecisa ser string ISO-8601 — não envie um objetoDateserializado pelo JavaScript sem antes chamar.toISOString().idTipoClienteé uma string (ex.:"F"para físico,"J"para jurídico ou um código próprio de até 3 caracteres).
Atualizar cliente
/api/clienteMesmo schema do POST, exigindo cdCliente.
Excluir cliente
/api/clienteSalvar respostas de formulário
/api/cliente/formularioPersiste respostas de um formulário dinâmico vinculado ao cliente. Envie um array de respostas.
Vendedores / acesso no app de força de venda
Um cliente pode ter múltiplos representantes (vendedores) associados a ele. O vínculo é feito via tabela auxiliar cliente_vendedor (modelo Prisma ClienteVendedor), que substitui o antigo campo cliente.cd_vendedor (removido).
Cliente.cdVendedorfoi removido. Qualquer integração que estivesse lendo/escrevendo esse campo precisa passar a usar a relaçãoClienteVendedor.- A coluna
cd_vendedoremclientedeixou de existir no banco; os vínculos existentes foram migrados paracliente_vendedorvia script SQL. - No model
Userfoi adicionado o flagidTodosClientesApp(mapeado paraid_todos_clientes_app), defaultfalse.
Tabela cliente_vendedor
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdHolding | number | Sim | Holding (parte da PK composta). |
cdCliente | number | Sim | Cliente vinculado (parte da PK composta). |
cdVendedor | number | Sim | userId do representante vinculado (parte da PK composta). |
Escopo de sincronização no app mobile
As rotas /api/mobile/sync/* que retornam dados relacionados a clientes (cliente, cidade, nota fiscal de saída e título a receber) passam a filtrar de acordo com o flag do usuário autenticado:
idTodosClientesApp = true: o usuário enxerga todos os clientes da holding (sem filtro por representante).idTodosClientesApp = false(default): o usuário só enxerga clientes onde ele está na tabelacliente_vendedorcomo vendedor. Rotas que derivam de cliente (cidade, nota-fiscal-saida, titulo-receber) usam o mesmo escopo.
Cadastro offline (upload)
Ao receber um cliente cadastrado pelo app (POST /api/mobile/upload/cliente), o backend agora registra automaticamente um vínculo em cliente_vendedor entre o novo cliente e o usuário que fez o upload. Isso garante que o representante que cadastrou o cliente consiga vê-lo de volta, mesmo que seu idTodosClientesApp esteja em false.
Gerenciando vínculos pelo endpoint /api/users
Os campos idTodosClientesApp e clientesVendedor[] agora fazem parte do payload de POST / PUT em /api/users. OGET /api/users inclui clientesVendedor no retorno (com cdCliente, nmCliente e cpf) para facilitar a renderização da lista no ERP.
Quando clientesVendedor é enviado no payload, o backend substitui a lista inteira: apaga todos os vínculos atuais do usuário e recria apenas os enviados. Para manter a lista intacta, omita o campo.
Produtos
Listar produtos
/api/produtoQuery parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | IDs separados por vírgula. |
name | string | — | Busca por nome do produto. |
cdProdutoBarra | string | — | Código de barras. |
cdMarca | number | — | Código da marca. |
cdGrupo | number | — | Código do grupo. |
cdFornecedor | number | — | Código do fornecedor. |
cdReferencia | string | — | Referência interna. |
somenteProdutosComSaldo | boolean | — | Apenas com saldo em estoque. |
idTipoProduto | string | — | Tipo do produto. |
dsAgregado | string | — | Busca agregada por nome, marca, grupo, referência, etc. |
page | number | — | Página (default 1). |
limit | number | — | Itens por página. |
Criar produto
/api/produtoCria um novo produto com código de barras, tabelas de preço e dados fiscais. Escopo: holding — não envie cdEmpresa no body (o saldo de estoque é criado automaticamente em todas as empresas da holding).
A API preenche automaticamente os campos fiscais e flags padrão quando você não os envia, então o payload mínimo abaixo já é suficiente. Você pode sobrescrever qualquer um deles passando o valor explicitamente.
Defaults aplicados: idSituacao: "A", idTipoProduto: "P", idSaldoNegativo: "N", idDecimal: "N", idLiberaQtd: "N", idEnviaLojaVirtual: "N", idComplemento: "N", cdFornecedor: 1, cdCor: 1, cdTamanho: 1, cdGrade: 1, nrItem: 1, cdSituacaoTributaria: "000", cdSituacaoPis/Cofins/Ipi: "01", prIcms / prComissao / prMargemSubstituicao: 0, fatorVenda: 1, qtMinimo / qtMaximo / pesoBruto / pesoLiquido / cubagem: 0. Se cdUnidadeEmbalagem não for enviado, recebe o mesmo valor de cdUnidade.
Os itens de tabelaPrecoItem também recebem defaults: os demais campos numéricos obrigatórios (prIpi, prFrete, prAcrescimoFinanceiro, prMargemExtra, prDesconto, prSubstituicao, vlPromocao, vlPromocaoAprazo, vlUltCompra, prJuros, vlParcela, vlCustoMedio, vlCustoReposicao, vlNegociacao, prSubstituicaoSolidaria, vlOutrasDespesas, vlParcelaPromocao, prJurosPromocao) são preenchidos com 0 quando omitidos.
Body parameters mínimos
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
dsProduto | string | Sim | Descrição do produto (até 200 caracteres). |
cdMarca | number | Sim | Código da marca (use /api/marca para listar). |
cdGrupo | number | Sim | Código do grupo (use /api/grupoProduto para listar). |
cdUnidade | number | Sim | Código da unidade (use /api/unidade para listar). |
produtoBarra | array | — | Lista de códigos de barras. Cada item: { cdBarra: string }. |
tabelaPrecoItem | array | — | Tabela de preços (custo e venda ficam aqui dentro, não no nível do produto). Item mínimo: { cdTabelaPreco, vlCompra, vlCusto, vlVenda, prMargemLucro }. |
vlCusto, vlCompra, vlVenda e prMargemLucro são campos de tabelaPrecoItem, e não do produto em si. Enviar vlCusto no nível do produto é silenciosamente ignorado pela API (compatibilidade), mas o correto é colocá-los dentro do array.
Exemplo — payload mínimo
Exemplo — sobrescrevendo defaults fiscais
Resposta — 200 OK
Atualizar produto
/api/produtoExcluir produto
/api/produtoAtualizar produtos em lote
/api/produto/bulk-updateAtualiza vários produtos em uma única chamada. Cada item retorna individualmente o resultado da operação.
Resposta — 200 OK
Fotos (Firebase Storage)
Visão geral
Existem duas formas de anexar uma imagem a um cliente/produto:
Envie o arquivo em base64 direto para POST /api/cliente/foto ou POST /api/produto/foto. A API sobe para o Firebase e já atualiza o registro no banco.
Seu app já usa o SDK do Firebase? Faça o upload direto ao bucket e informe apenas fotoCliente / nomeFotoCliente (ou os equivalentes de produto) na API.
- Cliente:
fotoCliente(token + extensão, ex."a1b2c3.jpg") enomeFotoCliente(nome do arquivo sem extensão). - Produto:
fotoProdutoenomeFotoProdutono mesmo formato. - Fotos extras (loja online): tabela dedicada com
fotoToken,fotoNomeeordem.
O limite por arquivo é de 5 MB. Formatos suportados: image/jpeg, image/png, image/webp e image/gif. O corpo da requisição (JSON com base64) pode ter até 10 MB.
Estrutura no storage
Todas as imagens ficam no bucket:
techbull-20bd5.appspot.com
Organizadas por holding e categoria, no caminho {holdingId}/images/{categoria}/{nome}.{ext}:
| Categoria | Usada por | Exemplo de caminho |
|---|---|---|
| cliente | Foto principal do cliente | 3/images/cliente/100.jpg |
| produto | Foto principal do produto | 3/images/produto/55.jpg |
| loja-online-produto | Fotos extras exibidas na loja online | 3/images/loja-online-produto/abc123.jpg |
Enviar foto do cliente
/api/cliente/fotoSubstitui a foto principal do cliente. Se fileBase64 for enviado, a API faz o upload para o Firebase Storage e grava fotoCliente / nomeFotoCliente no banco. Se você já subiu a imagem por conta própria, envie apenas fotoCliente + nomeFotoCliente.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdCliente | number | Sim | Código do cliente. |
fileBase64 | string | — | Arquivo em base64, com ou sem prefixo data:image/...;base64,. Obrigatório se fotoCliente não for enviado. |
contentType | string | — | Ex.: image/jpeg. Inferido automaticamente quando o base64 já vem como data URL. |
filename | string | — | Opcional. Usado para descobrir a extensão. |
fotoCliente | string | — | Alternativa ao fileBase64: token retornado pelo Firebase, no formato token.ext. |
nomeFotoCliente | string | — | Obrigatório quando fotoCliente é enviado. Nome do arquivo sem extensão. |
Exemplo — upload via API
Exemplo — já subiu para o Firebase
Resposta — 200 OK
Remover foto do cliente
/api/cliente/fotoZera os campos fotoCliente e nomeFotoCliente do cliente. O arquivo no Firebase continua no bucket, mas deixa de ser referenciado.
Enviar foto do produto
/api/produto/fotoMesma dinâmica do endpoint de cliente: envie fileBase64 para que a API faça o upload no Firebase, ou apenas fotoProduto + nomeFotoProduto se você já subiu o arquivo.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdProduto | number | Sim | Código do produto. |
fileBase64 | string | — | Arquivo em base64 (obrigatório se não enviar fotoProduto). |
contentType | string | — | Ex.: image/jpeg. |
filename | string | — | Usado para inferir a extensão. |
fotoProduto | string | — | Token retornado pelo Firebase (token.ext). |
nomeFotoProduto | string | — | Obrigatório quando fotoProduto é enviado. |
Resposta — 200 OK
Remover foto do produto
/api/produto/fotoLimpa fotoProduto e nomeFotoProduto do produto.
Listar fotos extras de um produto
/api/loja-online/produto-fotosRetorna a galeria de imagens do produto usada pela loja online. A foto principal exibida no card do produto segue sendo fotoProduto da entidade produto.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdProduto | number | Sim | Código do produto. |
Resposta — 200 OK
Adicionar foto extra
/api/loja-online/produto-fotosCadastra uma nova foto na galeria. O arquivo precisa estar no Firebase Storage na categoria loja-online-produto. Envie apenas o par fotoNome + fotoToken.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdProduto | number | Sim | Código do produto. |
fotoNome | string | Sim | Nome do arquivo (sem extensão). |
fotoToken | string | Sim | Token retornado pelo Firebase, no formato token.ext. |
ordem | number | — | Posição na galeria (o próximo valor livre é usado se omitido). |
Reordenar fotos extras
/api/loja-online/produto-fotosAtualiza a ordem de exibição das fotos. Envie os IDs na nova sequência desejada.
Excluir foto extra
/api/loja-online/produto-fotosRemove uma foto da galeria a partir do seu ID.
Definir foto principal
/api/loja-online/produto-foto-principalPromove uma das fotos extras a foto principal do produto (fotoProduto). Use extraId para promover uma foto existente da galeria (ela é copiada para a categoria produto e removida da galeria), ou envie fotoProduto + nomeFotoProduto caso já tenha subido uma imagem nova por conta própria.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdProduto | number | Sim | Código do produto. |
extraId | number | — | ID da foto extra a ser promovida (mutuamente exclusivo com fotoProduto). |
fotoProduto | string | — | Token da nova foto principal (token.ext). |
nomeFotoProduto | string | — | Nome do arquivo correspondente à foto principal. |
Montar URL de download
A API sempre retorna o par fotoToken + fotoNome (ou os equivalentes em fotoCliente/fotoProduto). Com esses valores você monta a URL pública de download com o seguinte template:
https://firebasestorage.googleapis.com/v0/b/techbull-20bd5.appspot.com/o/{holdingId}%2Fimages%2F{categoria}%2F{nome}.{ext}?alt=media&token={token}Onde {token} é o valor de fotoToken sem a extensão (tudo antes do último ponto) e {ext} é a extensão (depois do último ponto).
Exemplo (TypeScript)
function getPhotoUrl(
holdingId: number,
categoria: 'cliente' | 'produto' | 'loja-online-produto',
fotoNome: string,
fotoToken: string,
) {
const [token, ext = 'jpg'] = fotoToken.split('.');
const caminho = `${holdingId}/images/${categoria}/${fotoNome}.${ext}`;
return (
'https://firebasestorage.googleapis.com/v0/b/' +
'techbull-20bd5.appspot.com/o/' +
encodeURIComponent(caminho) +
`?alt=media&token=${token}`
);
}As URLs geradas são estáveis enquanto o token não for regenerado. Sinta-se livre para fazer cache no seu CDN ou na camada de aplicação.
Títulos a Receber e a Pagar
Listar títulos a receber
/api/tituloReceberQuery parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
tpPeriodo | "E" | "V" | "P" | Sim | Tipo de período: E emissão, V vencimento, P pagamento. |
cdEmpresa | number | — | Empresa. |
cdPessoa | number | — | Cliente. |
serie | string | — | Série do título. |
idSituacao | string | — | AB, PG, CA. |
dtIni | date | — | Data inicial. |
dtFim | date | — | Data final. |
vlIni | number | — | Valor mínimo. |
vlFim | number | — | Valor máximo. |
page | number | — | Página. |
limit | number | — | Itens por página. |
Criar/Atualizar/Excluir título a receber
/api/tituloReceberMétodos suportados: POST criar, PUT atualizar (com nrTitulo), DELETE remover (envia cdUnidade no body). Respectivamente exigem titulosReceber:editar e titulosReceber:excluir.
Receber títulos (baixa)
/api/recebimentoRealiza a baixa de um ou mais títulos a receber, registrando as formas de pagamento, troco e crédito de cliente quando aplicável.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | Sim | Empresa do recebimento. |
titulos | array | Sim | Lista de títulos a baixar (mínimo 1). |
formasPagamento | array | Sim | Formas de pagamento usadas (mínimo 1). |
vlTotal | number | Sim | Valor total recebido. |
vlDesconto | number | — | Desconto aplicado. |
vlAcrescimo | number | — | Acréscimo aplicado. |
cdCliente | number | — | Cliente (para registrar crédito do troco). |
Resposta — 200 OK
Listar títulos a pagar
/api/tituloPagarQuery parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
tpPeriodo | "E" | "V" | "P" | Sim | Tipo de período (emissão/vencimento/pagamento). |
cdEmpresa | number | — | Empresa. |
cdFornecedor | number | — | Fornecedor. |
cdConta | number | — | Conta bancária/caixa. |
cdTipoDespesa | number | — | Tipo de despesa. |
idSituacao | string | — | AB, PG, CA. |
dtIni | date | — | Data inicial. |
dtFim | date | — | Data final. |
page | number | — | Página. |
limit | number | — | Itens por página. |
Criar/Atualizar/Excluir título a pagar
/api/tituloPagarAceita POST PUT DELETE. Para excluir, envie nrTitulo no body. Permissões titulosPagar:editar e titulosPagar:excluir.
Pagar título
/api/tituloPagar/pagarMarca um título em aberto como pago e movimenta a conta correspondente.
Lembre-se de incluir serie no body — ela faz parte da chave composta do título junto com cdEmpresa, nrTitulo e nrParcela.
Cancelar título a pagar
/api/tituloPagar/cancelarCancela um título em aberto. Não funciona em títulos já pagos (use estornar primeiro).
Estornar pagamento
/api/tituloPagar/estornarReverte um título já pago, devolvendo-o para a situação aberta e estornando a movimentação na conta.
Entidades de Apoio
CRUD padrão
Todas as entidades abaixo aceitam os mesmos métodos:
- GET — lista/consulta com filtros (apenas autenticação).
- POST — criar (exige permissão de
cadastrar). - PUT — atualizar (exige permissão de
editar). - DELETE — excluir (exige permissão de
excluir).
Para descobrir os campos exatos do body, consulte os validations.ts da entidade no projeto principal ou faça um GET e use o retorno como referência.
Lista de endpoints
| Endpoint | Permissões base | Descrição |
|---|---|---|
| /api/grupoProduto | grupos:* | Grupos / categorias de produto. |
| /api/marca | marcas:* | Marcas dos produtos. |
| /api/cor | cor:* | Cores disponíveis. |
| /api/tamanho | tamanhos:* | Tamanhos / grade. |
| /api/fornecedor | fornecedores:* | Fornecedores dos produtos. |
| /api/categoria | categoria:* | Categorias de cliente. |
| /api/tabelaPreco | tabelaPreco:* | Tabelas de preço. |
| /api/unidade | unidades:* | Unidades de medida. |
| /api/cidade | — (público) | Cidades do IBGE. Não exige autenticação. |
Exceções do padrão
/api/formaPagamento— aceita apenas GET e PUT (não há criar/excluir isoladamente; o PUT funciona como upsert/atualização em lote). Permissão:formaPagamento:editar./api/cidade— público (não exige token).
Campos obrigatórios das principais entidades
Os bodies abaixo refletem o que a API valida no momento da criação (POST).
POST /api/marca
POST /api/grupoProduto
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
dsGrupo | string | Sim | Nome do grupo (até 60 caracteres). |
idTipo | "P" | "S" | Sim | Tipo do grupo: P = produto, S = serviço. |
prComissao | number | Sim | Percentual padrão de comissão para esse grupo. |
POST /api/unidade
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
dsUnidade | string | Sim | Sigla da unidade (ex.: UN, KG, MT). |
dsUnidadeFator | string | Sim | Sigla da unidade de fator (geralmente igual a dsUnidade). |
fator | number | Sim | Fator de conversão (1 quando não há conversão). |
Estoque
Conceito
Toda movimentação de estoque referencia uma operação previamente cadastrada (cdOperacaoEstoque) que define se ela soma (entrada) ou subtrai (saída) do saldo. Para popular o estoque inicial de um produto recém-criado, use uma operação de entrada (ex.: ajuste / inventário).
A efetivação de vendas (POST /api/venda/efetivar) consome estoque. Se o produto não tiver saldo suficiente e a configuração idSaldoNegativo dele for "N", a efetivação falha. Sempre dê entrada de estoque antes de vender.
Listar movimentações de estoque
/api/movimentoEstoqueQuery parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | — | Empresa. |
dtIni | date (YYYY-MM-DD) | — | Data inicial. |
dtFim | date (YYYY-MM-DD) | — | Data final. |
page | number | — | Página (default 1). |
limit | number | — | Itens por página. |
Lançar movimentação(ões)
/api/movimentoEstoqueO body é um array de movimentações — cada item afeta um produto. Indicado tanto para entradas (ajustes, compras) quanto para saídas (perdas, transferências).
Body (cada item do array)
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | Sim | Empresa. |
cdProduto | number | Sim | Produto a movimentar. |
cdOperacaoEstoque | number | Sim | Operação cadastrada (define se é entrada ou saída). |
qtd | number | Sim | Quantidade movimentada (sempre positiva — o sinal vem da operação). |
nrDocumento | number | — | Número do documento de origem (NF, ajuste, etc.). |
serie | string | — | Série do documento. |
cdPessoa | number | — | Cliente ou fornecedor envolvido. |
tpPessoa | "C" | "F" | — | Tipo da pessoa: C = cliente, F = fornecedor. |
obs | string | — | Observação livre. |
vlCusto, vlVenda e vlCompra não existem no model MovimentoEstoque — eles vivem em tabelaPrecoItem/notas fiscais. Para manter compatibilidade, a API descarta esses campos sem erro caso sejam enviados, mas eles não terão efeito no movimento.
Agendamentos
Listar agendamentos
/api/agendamentoQuery parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | — | Empresa. |
cdAgendamento | number | — | ID específico. |
dtAgendamentoIni | date | — | Início do período. |
dtAgendamentoFim | date | — | Fim do período. |
cdCliente | number | — | Cliente. |
cdFuncionario | number | — | Funcionário responsável. |
cdProduto | number | — | Produto/serviço agendado. |
idSituacao | number | — | Situação do agendamento. |
Criar agendamento
/api/agendamentoCria um agendamento. Os serviços/produtos vinculados vão dentro do array servicos; não envie objetos completos de cliente ou funcionário no body — apenas os códigos.
Body parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | Sim | Empresa. |
cdCliente | number | Sim | Cliente do agendamento. |
dtAgendamentoIni | date (ISO-8601) | Sim | Data/hora de início. |
dtAgendamentoFim | date (ISO-8601) | — | Data/hora de término. |
cdFuncionario | number | — | Funcionário responsável. |
idSituacao | string | — | Situação inicial (ex.: AB para aberto / agendado). |
observacao | string | — | Observação livre (use observacao, não obs). |
color | string | — | Cor para exibição na agenda (hex). |
servicos | array | — | Serviço/produto do agendamento. Cada item: { cdProduto: number }. Apenas o primeiro item é persistido (o model atual suporta um serviço por agendamento). |
O nome correto do campo de observação é observacao (não obs). Enviar obs faz o servidor responder com 422 Erro de validação do banco de dados: Unknown argument `obs`.
Historicamente a validação aceita uma lista de serviços, mas o model interno AgendamentoServicos é 1-1 com o agendamento. Por compatibilidade, a API aceita o array mas persiste apenas o primeiro item. O campo cdServico é aceito e ignorado silenciosamente (não existe no model).
Atualizar agendamento
/api/agendamentoMesmo schema do POST, com cdAgendamento obrigatório.
Excluir agendamento
/api/agendamentoErros
snake_case.Formato padrão
O campo request_id é útil para suporte: anote-o e informe ao time TechBull caso precise investigar uma falha específica.
Erros de validação do banco (422)
Quando o body bate na validação Joi mas falha no Prisma (campo obrigatório esquecido, argumento desconhecido, tipo errado), a API responde com 422 e a mensagem inclui o detalhe acionável extraído da resposta do Prisma:
Se o detalhe vier em inglês (porque é gerado pelo Prisma), os padrões mais comuns são:
Argument `xxx` is missing.→ faltou enviar o campoxxx.Unknown argument `xxx`.→ você enviou um campo que não existe nessa entidade.Invalid value for argument `xxx`→ o tipo/valor dexxxestá errado (ex.: passar string onde espera number).
Códigos de status
| Status | Quando acontece |
|---|---|
400 | ValidationError — body/query inválido (campo obrigatório, tipo errado, regra de negócio). |
401 | UnauthorizedError — sessão ausente, expirada ou credenciais incorretas no login. |
403 | ForbiddenError — autenticado, mas sem a feature/permissão necessária. |
404 | NotFoundError — recurso não encontrado. |
409 | Conflito — geralmente violação de chave estrangeira (Prisma P2003). |
422 | UnprocessableEntityError — dados não processáveis. |
500 | InternalServerError — erro inesperado no servidor (anote o request_id). |
Dúvidas ou sugestões? Entre em contato pelo formulário do site.