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, agendamentos (interno e público) 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
Os campos documentados para entrada e saída usam camelCase. Espere nomes como cdEmpresa, nrPrevenda, idSituacao e prevendaItem.
Algumas integrações legadas podem trabalhar internamente com nomes de colunas em snake_case, mas os contratos e exemplos públicos desta documentação usam camelCase.
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).
Relatórios
Relatório de notas fiscais
/api/notaFiscalRelatorioLista NF-e, NFC-e e recibos D1 emitidos no período. O retorno contém os dados resumidos de cada nota e os totais consolidados da consulta.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | Sim | Código da empresa. |
dtIni | date (YYYY-MM-DD) | Sim | Data inicial do período de emissão. |
dtFim | date (YYYY-MM-DD) | Sim | Data final do período de emissão. |
nrNota | number | — | Filtra pelo número da nota. |
nmCliente | string | — | Busca parcial pelo nome do cliente. |
idSerie | string | — | Tipo da nota: D1, NFC ou NFE. |
situacao | string | — | PR para autorizada, PE para pendente ou CA para cancelada. |
O valor do relatório considera somente itens de produto. Notas compostas apenas por serviços não aparecem na listagem.
Resposta — 200 OK
Notas fiscais com produtos
/api/notaFiscalRelatorio/detalhadoLista as notas fiscais e inclui todos os itens de cada nota no array produtos. O retorno é um array JSON direto, paginado pelos parâmetros page e limit.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresa | number | — | Código da empresa. Quando omitido, consulta todas as empresas permitidas da holding. |
nrNota | number | — | Número exato da nota. |
serie | string | — | Série exata da nota. Não pode ser combinada com idSerie. |
dtIni | date (YYYY-MM-DD) | — | Data inicial de emissão. Deve ser enviada junto com dtFim. |
dtFim | date (YYYY-MM-DD) | — | Data final de emissão, inclusive. Deve ser enviada junto com dtIni. |
cdCliente | number | — | Código exato do cliente. |
nmCliente | string | — | Busca parcial pelo nome do cliente. |
cpf | string | — | Busca parcial por CPF ou CNPJ do cliente. |
cdProduto | number | — | Código exato do produto presente na nota. |
nmProduto | string | — | Busca parcial pela descrição do produto. |
cdReferencia | string | — | Busca parcial pela referência do produto. |
cdGrupo | number | — | Código do grupo de produto. |
cdMarca | number | — | Código da marca do produto. |
cdFornecedor | number | — | Código do fornecedor do produto. |
idTipoProduto | string | — | P para produto ou S para serviço. |
cdFuncionario | number | — | Código do vendedor/funcionário da nota. |
cdNatureza | number | — | Código da natureza de operação. |
cdTipoVenda | number | — | Código do tipo de venda. |
idFormaPagamento | number | — | Código da forma de pagamento da nota. |
idSerie | string | — | Tipo da nota: D1, NFC ou NFE. Não pode ser combinado com serie. |
situacao | string | — | PR para autorizada, PE para pendente ou CA para cancelada. |
nrChaveAcesso | string | — | Busca parcial pela chave de acesso da nota. |
page | number | — | Página da consulta. Padrão: 1. |
limit | number | — | Quantidade de notas por página. Padrão: 100; máximo: 500. |
order | string | — | Ordenação pela data de emissão: desc (padrão) ou asc. |
Se uma nota possuir o produto filtrado, ela será incluída e o array produtos trará todos os itens dessa nota — não apenas o produto usado no filtro.
A resposta não possui envelope: ela é um json[]. Solicite as páginas seguintes até receber um array vazio.
Resposta — 200 OK
Relatório de produtos vendidos
/api/produtosVendidosConsolida produtos ou serviços vendidos no período, com quantidade, custo, valor de venda, preço médio e margem. É possível consultar várias empresas e agrupar o resultado por produto, grupo, marca ou fornecedor.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdEmpresas | number[] | Sim | Códigos das empresas separados por vírgula, por exemplo 1,2. |
dtIni | date (YYYY-MM-DD) | Sim | Data inicial do período de emissão. |
dtFim | date (YYYY-MM-DD) | Sim | Data final do período de emissão. |
idTipoProduto | string | — | TODOS (padrão), P para produtos ou S para serviços. |
idAgrupamento | string | — | PRODUTO (padrão), GRUPO, MARCA ou FORNECEDOR. |
cdGrupos | number[] | — | Códigos dos grupos separados por vírgula. |
cdMarca | number | — | Filtra por uma marca. |
cdFornecedor | number | — | Filtra por um fornecedor. |
busca | string | — | Busca por descrição ou referência do produto. |
São consideradas notas de saída normais, com natureza de faturamento. Notas avulsas são excluídas e as devoluções são descontadas da quantidade e dos valores.
A rota exige relatorio:produtosVendidos. Para exibir custo, valor de venda e margem, além de agrupar por grupo, marca ou fornecedor, o usuário também precisa de relatorios:vendas.
Resposta — 200 OK
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. |
Cada cliente pode retornar cdTelevendas, cdClienteGrupo e cdTabelaPrecoCondicao. Os três campos são opcionais e podem ser null.
O vendedor responsável é uma relação separada e deve ser consultado em GET /api/clienteVendedor. Já cdTelevendas identifica especificamente o televendas configurado no ERP de origem.
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". |
cdTelevendas | number | null | — | Código do televendas vinculado ao cliente. |
cdClienteGrupo | number | null | — | Código do grupo comercial. Consulte /api/clienteGrupo. |
cdTabelaPrecoCondicao | number | null | — | Código do vínculo entre tabela e condição de preço. Consulte /api/tabelaPrecoCondicao. |
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. |
cdAgrupador | number | — | Código do agrupador de preço. Consulte /api/produtoAgrupador. |
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. |
O campo cdAgrupador identifica o agrupador de preço associado ao produto e pode ser null. Consulte o cadastro correspondente em GET /api/produtoAgrupador.
Características e seus valores são consultados separadamente em GET /api/caracteristicaProduto e GET /api/produtoCaracteristicaProduto.
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). |
cdAgrupador | number | null | — | Agrupador de preço (use /api/produtoAgrupador 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
Cotações e Cadastros
Listar cotações de venda
/api/cotacaoVendaConsulta a tabela cotacao_venda. O parâmetro id é um atalho para nrCotacao.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
nrCotacao | number | — | Número da cotação. |
cdEmpresa | number | — | Código da empresa. |
idSituacao | string | — | Situação da cotação. |
dtIni | date (YYYY-MM-DD) | — | Emissão a partir desta data. |
dtFim | date (YYYY-MM-DD) | — | Emissão até esta data. |
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: nrCotacao, cdEmpresa, cdCliente, nmCliente, idSituacao, dtEmissao, vlCotacao. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar itens das cotações de venda
/api/cotacaoVendaItemConsulta a tabela cotacao_venda_item. Informe nrCotacao e cdEmpresa para recuperar os itens de uma cotação específica.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
nrCotacao | number | — | Número da cotação. |
nrItem | number | — | Número do item dentro da cotação. |
cdEmpresa | number | — | Código da empresa. |
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: nrCotacao, nrItem, cdEmpresa, cdProduto, dsProduto, qtCotada, vlUnitario. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar transportadoras
/api/transportadoraConsulta a tabela transportadora por código ou nome.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdTransportadora, razaoSocial, nmTransportadora, cnpj, fone, email. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar veículos
/api/veiculoConsulta a tabela veiculo por código, descrição, placa ou situação.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
placa | string | — | Busca parcial pela placa. |
idAtivo | string | — | Indicador de situação cadastrado no veículo. |
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdVeiculo, dsVeiculo, placa, qtPesoCapacidade, idAtivo. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar motoristas
/api/motoristaConsulta a tabela motorista por código, nome, CPF ou situação.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cpf | string | — | Busca parcial pelo CPF. |
idAtivo | string | — | Indicador de situação cadastrado no motorista. |
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdMotorista, nmMotorista, cpf, idComissao, idAtivo. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar fornecedores
/api/fornecedorConsulta a tabela fornecedor. Este endpoint já fazia parte da API e exige apenas autenticação.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 10; use -1 para listar todos). |
Campos de destaque no retorno: cdFornecedor, razaoSocial, nmFornecedor, cnpj, fone, email, cdGrupoFornecedor. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar grupos de fornecedor
/api/fornecedorGrupoConsulta a tabela fornecedor_grupo por código ou descrição.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdGrupoFornecedor, dsGrupoFornecedor, dtManutencao. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar grupos de produto
/api/grupoProdutoConsulta a tabela grupo_produto. Este endpoint já fazia parte da API e exige apenas autenticação.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
idAtivo | boolean | — | Filtra grupos ativos ou inativos. |
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 10; use -1 para listar todos). |
Campos de destaque no retorno: cdGrupo, dsGrupo, idTipo, prComissao, idAtivo. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar vendedores responsáveis dos clientes
/api/clienteVendedorConsulta a tabela cliente_vendedor. Cada registro vincula um cliente ao seu vendedor responsável; um cliente pode possuir mais de um vínculo. Este cadastro é diferente do campo cdTelevendas retornado pelo cliente.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdCliente | number | — | Código do cliente. |
cdVendedor | number | — | Código do vendedor responsável. |
id | string | — | Código(s) principal(is), separados por vírgula. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdCliente, cdVendedor. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar grupos de cliente
/api/clienteGrupoConsulta a tabela cliente_grupo, referenciada pelo campo cdClienteGrupo de cada cliente.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdGrupo, dsGrupo, prDesconto1, prDesconto2, idLimitePorGrupo, dtManutencao. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar condições das tabelas de preço
/api/tabelaPrecoCondicaoConsulta os vínculos entre tabela de preço e condição de preço. O código do vínculo é retornado no cliente como cdTabelaPrecoCondicao.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdTabelaPreco | number | — | Código da tabela de preço. |
cdCondicaoPreco | number | — | Código da condição de preço. |
id | string | — | Código(s) principal(is), separados por vírgula. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdTabelaPrecoCondicao, cdTabelaPreco, cdCondicaoPreco, nrOrdem. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar agrupadores de preço dos produtos
/api/produtoAgrupadorConsulta a tabela produto_agrupador, referenciada pelo campo cdAgrupador do produto.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdAgrupador, dsAgrupador, idAtualizaCusto, idAtualizaVenda, idControlaGrade, cdSite. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar características de produto
/api/caracteristicaProdutoConsulta o catálogo de características disponíveis para os produtos, como gramatura, composição, coleção ou qualquer outro atributo definido no ERP de origem.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
id | string | — | Código(s) principal(is), separados por vírgula. |
name | string | — | Busca parcial no campo de nome/descrição da entidade. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdCaracteristicaProduto, dsCaracteristicaProduto, ativo, tipoCampo, cdSite, dtUltAlteracao. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
Listar valores das características dos produtos
/api/produtoCaracteristicaProdutoConsulta os valores associados a cada produto e característica. Conforme o tipo da característica, o valor estará em valorDecimal, valorInteiro ou valorString.
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
cdProduto | number | — | Código do produto. |
cdCaracteristicaProduto | number | — | Código da característica. |
id | string | — | Código(s) principal(is), separados por vírgula. |
page | number | — | Página da consulta (padrão 1). |
limit | number | — | Registros por página (padrão 50, máximo 500). |
Campos de destaque no retorno: cdProduto, cdCaracteristicaProduto, valorDecimal, valorInteiro, valorString. A resposta usa o formato paginado padrão com results e hasMorePages; o identificador interno da holding não é exposto.
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/agendamentoAgendamento Público
/api/agendamento (uso interno autenticado). O {slug} é o identificador configurado no painel (Agenda → Configurar link público).Visão geral
Fluxo recomendado
GET .../info— dados da empresa, serviços e tipo de gradeGET .../disponibilidade— horários ou vagas livresPOST .../reservar— confirma a reserva com nome e CPF
O campo tipoGradePublica define o comportamento:
HORARIO— o cliente escolhe um slot de horário (slotStartISO).VAGAS— o cliente escolhe dia + serviço (diaYYYYMMDD+servicoPublicoId).
/api/agendamento-public/{slug}/...— reserva pelo cliente (público)/api/agendamento-publico— configuração interna no painel (requer login)/api/agendamento— agenda interna (requer login ecdCliente/cdFuncionario)
Página web do cliente: /agendamento-publico/{slug} (ou subdomínio customizado, se configurado). O servicoPublicoId usado na reserva é o campo id retornado em servicos[].
Info da página pública
/api/agendamento-public/{slug}/infoRetorna dados de exibição e a lista de serviços públicos ativos. Use para montar a tela de agendamento ou mapear servicoPublicoId pelo nome do serviço.
Path parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
slug | string | Sim | Identificador do link (case-insensitive). Ex.: salao-bella. |
Resposta — 200 OK
Consultar disponibilidade
/api/agendamento-public/{slug}/disponibilidadeLista serviços e, conforme o tipo de grade, retorna slots de horário (slotsPorDia) ou vagas por dia/serviço (vagasPorDia).
Path parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
slug | string | Sim | Identificador do link público. |
Query parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
desde | string (YYYY-MM-DD) | — | Primeiro dia da janela consultada. Padrão: hoje (fuso America/Sao_Paulo). |
dias | number | — | Quantidade de dias (1–31). Padrão: 7. |
Resposta — modo VAGAS (trecho)
Resposta — modo HORARIO (trecho)
Reservar horário
/api/agendamento-public/{slug}/reservarCria o agendamento. O backend resolve ou cadastra o cliente pelo CPF — não é necessário enviar cdCliente. Envie apenas um dos modos: horário fixo ou dia + serviço.
Path parameters
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
slug | string | Sim | Identificador do link público. |
Body parameters (comuns)
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
nmCliente | string | Sim | Nome do cliente (3–120 caracteres). |
cpf | string | Sim | CPF com 11 dígitos (com ou sem máscara). Validado no servidor. |
Body — modo HORARIO
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
slotStartISO | string (ISO-8601) | Sim | Início do slot escolhido (valor de inicioISO em disponibilidade). |
Body — modo VAGAS
| Parâmetro | Tipo | Obrig. | Descrição |
|---|---|---|---|
diaYYYYMMDD | string | Sim | Dia da reserva no formato YYYY-MM-DD. |
servicoPublicoId | number | Sim | ID do serviço (campo id em servicos[] de info ou disponibilidade). |
Não envie slotStartISO junto com diaYYYYMMDD / servicoPublicoId. A API retorna 400 se ambos os modos forem informados ou se nenhum for informado.
Exemplo — modo VAGAS
Exemplo — modo HORARIO
Resposta — 200 OK
Rotas públicas possuem limite de requisições por IP. Respostas 429 indicam excesso de tentativas — aguarde antes de tentar novamente.
Erros
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.