Documentação da API

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

A API TechBull é uma API REST que retorna JSON. Todas as rotas estão sob o domínio do app principal e exigem autenticação por sessão (exceto onde indicado).

Introdução

Para integrar com o TechBull, o fluxo básico é:

  1. Fazer login com email e senha para obter um token de sessão.
  2. Enviar esse token em todas as próximas chamadas (via Cookie ou Authorization, conforme a rota).
  3. 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:

Base URL
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

Respostas em snake_case

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

A autenticação é baseada em token de sessão gerado no login (96 caracteres hexadecimais). O token tem validade de 30 dias.

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:

Rotas Mobile (/api/mobile/*)
Authorization: Bearer <token>
Demais rotas (vendas, clientes, etc.)
Cookie: session_id=<token>
Mesmo token, dois envios

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

POST/api/mobile/auth/login
Público

Autentica 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âmetroTipoObrig.Descrição
emailstringSimEmail do usuário cadastrado.
senhastringSimSenha do usuário.
timezonestringFuso horário IANA. Padrão America/Sao_Paulo.

Exemplo de requisição

cURL
curl -X POST https://app.techbullsistemas.com.br/api/mobile/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "voce@empresa.com",
"senha": "sua-senha",
"timezone": "America/Sao_Paulo"
}'

Resposta — 200 OK

response.json
{
"token": "a3f9c1e2b4d6...96-chars-hex...",
"sessionId": 42,
"expiresAt": "2026-05-19T12:00:00.000Z",
"user": {
"userId": 7,
"holdingId": 3,
"cdEmpresa": 1,
"nome": "Maria Silva",
"email": "voce@empresa.com",
"idAtivo": true
}
}
Guarde o token com segurança

O token tem validade de 30 dias. Trate-o como uma senha — não exponha em URLs nem em logs.

Obter usuário autenticado

GET/api/mobile/auth/me
Authorization: Bearer

Retorna informações do usuário associado ao token. Útil para validar se o token continua válido.

cURL
curl https://app.techbullsistemas.com.br/api/mobile/auth/me \
-H "Authorization: Bearer a3f9c1e2b4d6..."

Fazer logout

POST/api/mobile/auth/logout
Authorization: Bearer

Invalida o token de sessão atual no servidor.

cURL
curl -X POST https://app.techbullsistemas.com.br/api/mobile/auth/logout \
-H "Authorization: Bearer a3f9c1e2b4d6..."

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

GET/api/feature
Cookie session_idfeature:consultar

Lista todas as features disponíveis no sistema. Útil para que o admin saiba quais permissões pode conceder.

cURL
curl https://app.techbullsistemas.com.br/api/feature \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Vendas e Pré-vendas

Toda venda começa como pré-venda (em aberto). Após efetivar, vira uma venda concretizada com nota fiscal, títulos gerados, movimentação de caixa e estoque. Pode ser cancelada ou estornada.

Conceito e ciclo de vida

A entidade principal é a prevenda. O campo id_situacao identifica o estado:

AB

Aberta — pré-venda em rascunho, ainda editável.

EF

Efetivada — venda concretizada, com nota fiscal e títulos.

CA

Cancelada — 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

GET/api/venda
Cookie session_idvendas:consultar

Lista pré-vendas e vendas com filtros e paginação. Use idSituacao para filtrar por estado.

Query parameters

ParâmetroTipoObrig.Descrição
cdEmpresanumberFiltra por empresa.
idSituacaostringAB, EF ou CA.
dtInidate (YYYY-MM-DD)Data inicial.
dtFimdate (YYYY-MM-DD)Data final.
cdFuncionarionumberVendedor responsável.
cdTipoVendanumberTipo de venda.
cdFormaPagamentonumberForma de pagamento.
pagenumberPágina (default 1).
limitnumberItens por página (default 50).
cURL
curl "https://app.techbullsistemas.com.br/api/venda?cdEmpresa=1&idSituacao=EF&page=1&limit=10" \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Resposta — 200 OK

response.json
{
"results": [
{
"nr_prevenda": 12345,
"cd_empresa": 1,
"cd_cliente": 100,
"id_situacao": "EF",
"vl_total": 150.50,
"dt_emissao": "2026-04-19T10:30:00.000Z",
"nr_nota": 9876,
"serie_nota": "1",
"prevenda_item": [ /* ... */ ],
"prevenda_titulo": [ /* ... */ ],
"prevenda_forma_pagamento": [ /* ... */ ]
}
],
"has_more_pages": true
}

Criar pré-venda

POST/api/venda
Cookie session_idvendas:cadastrar

Cria 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âmetroTipoObrig.Descrição
cd_empresanumberSimCódigo da empresa.
cd_clientenumberSimCódigo do cliente.
cd_funcionarionumberSimVendedor.
id_situacaostringSimUse "AB" para criar em aberto.
vl_totalnumberSimValor total da venda.
vl_brutonumberSimValor bruto antes de descontos.
cd_forma_pagamentonumberSimForma de pagamento principal.
cd_tipo_vendanumberSimTipo da venda.
prevenda_itemarraySimItens da venda (produtos, quantidade, valores).
prevenda_tituloarraySimTítulos a receber gerados.
prevenda_forma_pagamentoarraySimDetalhamento das formas de pagamento.
efetivar_vendabooleanSe true, efetiva já na criação.

Exemplo de requisição

request body
{
"cd_empresa": 1,
"cd_cliente": 100,
"cd_funcionario": 5,
"id_situacao": "AB",
"pr_desconto": 0,
"vl_desconto_total": 0,
"pr_acrescimo": 0,
"vl_acrescimo_total": 0,
"vl_acrescimo_total_item": 0,
"vl_bruto": 150.50,
"vl_total": 150.50,
"cd_forma_pagamento": 1,
"id_utiliza_credito_devolucao": "N",
"cd_tipo_venda": 1,
"prevenda_item": [
{
"cd_produto": 200,
"qt_produto": 1,
"vl_unitario": 150.50,
"vl_custo": 80,
"vl_desconto": 0,
"vl_acrescimo": 0,
"pr_comissao": 0,
"cd_funcionario": 5,
"qt_entrega_separacao": 0,
"qt_entrega_conferido": 0,
"id_produto_promocao": "N",
"qt_devolvido": 0,
"vl_promocao": 0
}
],
"prevenda_titulo": [
{
"dt_vencto": "2026-05-19T00:00:00.000Z",
"vl_titulo": 150.50,
"nr_forma": 1
}
],
"prevenda_forma_pagamento": [
{
"id_forma_pagamento": 1,
"nr_parcela": 1,
"vl_parcela": 150.50,
"vl_total": 150.50,
"vl_forma_original": 150.50
}
],
"prevenda_funcionario_auxiliar": []
}

Resposta — 200 OK

response.json
{
"prevenda_efetivada": {
"nr_prevenda": 12346,
"cd_empresa": 1,
"id_situacao": "AB",
"vl_total": 150.50
},
"nfe": null
}

Atualizar pré-venda

PUT/api/venda
Cookie session_idvendas:editar

Atualiza 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

DELETE/api/venda
Cookie session_idvendas:excluir

Cancela uma pré-venda em aberto. Não funciona em vendas já efetivadas (use /api/venda/estornar).

request body
{
"cd_empresa": 1,
"nr_prevenda": 12345,
"motivo_cancela": "Cliente desistiu"
}

Efetivar venda

POST/api/venda/efetivar
Cookie session_idvendas:efetivar

Efetiva 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.

cURL
curl -X POST https://app.techbullsistemas.com.br/api/venda/efetivar \
-H "Content-Type: application/json" \
-H "Cookie: session_id=a3f9c1e2b4d6..." \
-d '{ "cd_empresa": 1, "nr_prevenda": 12345 }'

Resposta — 200 OK

response.json
{
"prevenda_efetivada": {
"nr_prevenda": 12345,
"id_situacao": "EF",
"nr_nota": 9876,
"serie_nota": "1",
"dt_efetivacao": "2026-04-19T14:32:11.000Z"
},
"nfe": {
"success": true,
"data": { /* dados do retorno da NFC-e/NF-e */ }
}
}

Pré-requisito: o caixa da empresa deve estar aberto. Caso contrário a API retorna "Caixa não encontrado".

Estornar venda

POST/api/venda/estornar
Cookie session_idvendas:estornar

Estorna 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.

request body
{
"cd_empresa": 1,
"nr_prevenda": 12345
}

Editar venda efetivada

PUT/api/venda/update-efetivada
Cookie session_idvendas:editar

Ajusta dados não-financeiros de uma venda já efetivada (tipo de venda, observação, vendedor, vendedores auxiliares), espelhando na nota fiscal quando existir.

request body
{
"cd_empresa": 1,
"nr_prevenda": 12345,
"cd_tipo_venda": 2,
"obs": "Cliente preferencial",
"cd_funcionario": 5,
"prevenda_funcionario_auxiliar": [
{ "cd_funcionario": 8, "pr_comissao": 1.5 }
]
}

Atualizar formas de pagamento

POST/api/venda/updateFormaPagamento
Cookie session_idvendas:editar

Atualiza as formas de pagamento, títulos e totais de uma venda (ex.: cliente decide parcelar diferente).

request body
{
"cd_empresa": 1,
"nr_prevenda": 12345,
"vl_acrescimo_total": 0,
"vl_total": 200.00,
"prevenda_forma_pagamento": [
{
"id_forma_pagamento": 1,
"nr_parcela": 1,
"vl_parcela": 200.00,
"vl_total": 200.00,
"vl_forma_original": 200.00
}
],
"prevenda_titulo": [
{
"dt_vencto": "2026-05-19T00:00:00.000Z",
"vl_titulo": 200.00,
"nr_forma": 1
}
]
}

Clientes

CRUD de clientes da holding, com filtros avançados (aniversário, crédito, datas de cadastro, ordenação) e suporte a formulários dinâmicos.

Listar clientes

GET/api/cliente
Cookie session_id

Apenas autenticação é exigida (sem permissão específica).

Query parameters

ParâmetroTipoObrig.Descrição
idstringIDs separados por vírgula.
namestringBusca por nome.
cpfstringCPF/CNPJ.
fonestringTelefone.
cdCidadenumberCódigo da cidade.
periodoAniversarioInidateInício do período de aniversário.
periodoAniversarioFimdateFim do período de aniversário.
vlCreditoClienteMinnumberCrédito mínimo.
vlCreditoClienteMaxnumberCrédito máximo.
orderBy[field]stringCampo de ordenação.
orderBy[direction]asc | descDireção da ordenação.
pagenumberPágina.
limitnumberItens por página.
cURL
curl "https://app.techbullsistemas.com.br/api/cliente?name=Maria&page=1&limit=20" \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Criar cliente

POST/api/cliente
Cookie session_idclientes:cadastrar

Cria um novo cliente. Aceita endereço, dependentes (clienteDependente) e anexos (clienteAnexo) opcionais.

Campos obrigatórios

ParâmetroTipoObrig.Descrição
cdEmpresanumberSimEmpresa de origem do cadastro.
nmClientestringSimNome ou razão social.
tpPessoa"F" | "J"SimPessoa Física ou Jurídica.
cdCategorianumberSimCategoria do cliente.
cdSituacaoClientenumberSimSituação cadastral.
idTipoClientestringSimTipo de cliente.
vlLimiteCreditonumberSimLimite total de crédito.
vlLimiteDisponivelnumberSimLimite disponível atual.
vlCreditoDevolucaonumberSimCrédito por devoluções.
cpfstringCPF (PF) ou CNPJ (PJ), apenas dígitos. Valida o dígito verificador.
fonestringTelefone fixo (até 15 caracteres).
celularstringTelefone celular (até 15 caracteres).
emailstringE-mail (até 60 caracteres).
idSexo"M" | "F"Sexo. Use "M" ou "F" (e não sexo).
dtNascimentostring (ISO-8601)Data de nascimento como string ISO-8601, ex.: "1990-04-19T00:00:00.000Z".
endereco / bairro / cdCidade / cepstring / numberDados de endereço (todos opcionais).
clienteDependentearrayDependentes do cliente (opcional).
clienteAnexoarrayAnexos (opcional).
Convenções importantes
  • Use idSexo, não sexo.
  • dtNascimento precisa ser string ISO-8601 — não envie um objeto Date serializado 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).
request body
{
"cdEmpresa": 1,
"nmCliente": "João Souza",
"tpPessoa": "F",
"cpf": "12345678900",
"fone": "11999999999",
"celular": "11988888888",
"email": "joao@email.com",
"idSexo": "M",
"dtNascimento": "1990-04-19T00:00:00.000Z",
"cdCategoria": 1,
"cdSituacaoCliente": 1,
"idTipoCliente": "F",
"vlLimiteCredito": 5000,
"vlLimiteDisponivel": 1000,
"vlCreditoDevolucao": 0,
"clienteDependente": [],
"clienteAnexo": []
}

Atualizar cliente

PUT/api/cliente
Cookie session_idclientes:editar

Mesmo schema do POST, exigindo cdCliente.

request body (resumido)
{
"cdCliente": 100,
"cdEmpresa": 1,
"nmCliente": "João Souza Atualizado",
"tpPessoa": "F",
"cdCategoria": 1,
"cdSituacaoCliente": 1,
"idTipoCliente": "001",
"vlLimiteCredito": 7000,
"vlLimiteDisponivel": 2000,
"vlCreditoDevolucao": 0
}

Excluir cliente

DELETE/api/cliente
Cookie session_idclientes:excluir
request body
{ "cdCliente": 100 }

Salvar respostas de formulário

POST/api/cliente/formulario
Cookie session_idclientes:formulario

Persiste respostas de um formulário dinâmico vinculado ao cliente. Envie um array de respostas.

request body
[
{ "cdCliente": 10, "cdFormulario": 2, "cdPergunta": 5, "dsResposta": "Sim" },
{ "cdCliente": 10, "cdFormulario": 2, "cdPergunta": 6, "dsResposta": "" }
]

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).

Mudança de schema
  • Cliente.cdVendedor foi removido. Qualquer integração que estivesse lendo/escrevendo esse campo precisa passar a usar a relação ClienteVendedor.
  • A coluna cd_vendedor em cliente deixou de existir no banco; os vínculos existentes foram migrados para cliente_vendedor via script SQL.
  • No model User foi adicionado o flag idTodosClientesApp (mapeado para id_todos_clientes_app), default false.

Tabela cliente_vendedor

ParâmetroTipoObrig.Descrição
cdHoldingnumberSimHolding (parte da PK composta).
cdClientenumberSimCliente vinculado (parte da PK composta).
cdVendedornumberSimuserId 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 tabela cliente_vendedor como 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.

PUT /api/users (trecho)
{
"userIdAlterar": 7,
"cdEmpresa": 1,
"nome": "Maria Silva",
"email": "maria@empresa.com",
"idTodosClientesApp": false,
"clientesVendedor": [
{ "cdCliente": 100 },
{ "cdCliente": 215 }
]
}
Comportamento do update

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

CRUD de produtos com filtros por marca, fornecedor, grupo, código de barras e busca agregada. Inclui endpoint de atualização em lote.

Listar produtos

GET/api/produto
Cookie session_id

Query parameters

ParâmetroTipoObrig.Descrição
idstringIDs separados por vírgula.
namestringBusca por nome do produto.
cdProdutoBarrastringCódigo de barras.
cdMarcanumberCódigo da marca.
cdGruponumberCódigo do grupo.
cdFornecedornumberCódigo do fornecedor.
cdReferenciastringReferência interna.
somenteProdutosComSaldobooleanApenas com saldo em estoque.
idTipoProdutostringTipo do produto.
dsAgregadostringBusca agregada por nome, marca, grupo, referência, etc.
pagenumberPágina (default 1).
limitnumberItens por página.
cURL
curl "https://app.techbullsistemas.com.br/api/produto?cdMarca=3&dsAgregado=camiseta&page=1&limit=50" \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Criar produto

POST/api/produto
Cookie session_idprodutos:cadastrar

Cria 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).

Defaults aplicados pela API

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âmetroTipoObrig.Descrição
dsProdutostringSimDescrição do produto (até 200 caracteres).
cdMarcanumberSimCódigo da marca (use /api/marca para listar).
cdGruponumberSimCódigo do grupo (use /api/grupoProduto para listar).
cdUnidadenumberSimCódigo da unidade (use /api/unidade para listar).
produtoBarraarrayLista de códigos de barras. Cada item: { cdBarra: string }.
tabelaPrecoItemarrayTabela de preços (custo e venda ficam aqui dentro, não no nível do produto). Item mínimo: { cdTabelaPreco, vlCompra, vlCusto, vlVenda, prMargemLucro }.
Onde ficam custo e venda?

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

request body
{
"dsProduto": "Camiseta Preta P",
"cdMarca": 3,
"cdGrupo": 1,
"cdUnidade": 1,
"produtoBarra": [
{ "cdBarra": "7891234567890" }
],
"tabelaPrecoItem": [
{
"cdTabelaPreco": 1,
"vlCompra": 25.00,
"vlCusto": 25.00,
"vlVenda": 79.90,
"prMargemLucro": 60
}
]
}

Exemplo — sobrescrevendo defaults fiscais

request body
{
"dsProduto": "Camiseta Preta P",
"cdMarca": 3,
"cdGrupo": 1,
"cdUnidade": 1,
"cdFornecedor": 7,
"prIcms": 18,
"cdSituacaoTributaria": "102",
"cdClassificacaoFiscal": "61091000",
"cdCest": "2810400",
"produtoBarra": [{ "cdBarra": "7891234567890" }],
"tabelaPrecoItem": [
{
"cdTabelaPreco": 1,
"vlCompra": 25.00,
"vlCusto": 25.00,
"vlVenda": 79.90,
"prMargemLucro": 60
}
]
}

Resposta — 200 OK

response.json
{
"cdProduto": 242,
"dsProduto": "Camiseta preta p",
"cd_holding": 3
}

Atualizar produto

PUT/api/produto
Cookie session_idprodutos:editar
request body (resumido)
{
"cdProduto": 100,
"dsProduto": "Camiseta Preta P (atualizada)",
"tabelaPrecoItem": [
{ "cdTabelaPreco": 1, "vlVenda": 89.90, "prMargemLucro": 65 }
]
}

Excluir produto

DELETE/api/produto
Cookie session_idprodutos:excluir
request body
{ "cdProduto": 100 }

Atualizar produtos em lote

PUT/api/produto/bulk-update
Cookie session_idprodutos:editar

Atualiza vários produtos em uma única chamada. Cada item retorna individualmente o resultado da operação.

request body
{
"items": [
{
"cdProduto": 10,
"dsProduto": "Nome novo",
"tabelaPrecoItem": [
{ "cdTabelaPreco": 1, "vlVenda": 99.90, "prMargemLucro": 30 }
]
},
{ "cdProduto": 11, "vlCusto": 18.50 }
]
}

Resposta — 200 OK

response.json
{
"results": [
{ "cdProduto": 10, "success": true },
{ "cdProduto": 11, "success": false, "message": "Custo inválido" }
]
}

Fotos (Firebase Storage)

As imagens de clientes, produtos e fotos extras da loja online são armazenadas no Firebase Cloud Storage. A API TechBull oferece endpoints dedicados para upload, troca e remoção dessas imagens sem que você precise integrar o SDK do Firebase no seu cliente.

Visão geral

Existem duas formas de anexar uma imagem a um cliente/produto:

Recomendado — via API

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.

Avançado — upload direto

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.

Campos persistidos
  • Cliente: fotoCliente (token + extensão, ex. "a1b2c3.jpg") e nomeFotoCliente (nome do arquivo sem extensão).
  • Produto: fotoProduto e nomeFotoProduto no mesmo formato.
  • Fotos extras (loja online): tabela dedicada com fotoToken, fotoNome e ordem.
Tamanho e formatos

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:

bucket
techbull-20bd5.appspot.com

Organizadas por holding e categoria, no caminho {holdingId}/images/{categoria}/{nome}.{ext}:

CategoriaUsada porExemplo de caminho
clienteFoto principal do cliente3/images/cliente/100.jpg
produtoFoto principal do produto3/images/produto/55.jpg
loja-online-produtoFotos extras exibidas na loja online3/images/loja-online-produto/abc123.jpg

Enviar foto do cliente

POST/api/cliente/foto
Cookie session_idclientes:editar

Substitui 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âmetroTipoObrig.Descrição
cdClientenumberSimCódigo do cliente.
fileBase64stringArquivo em base64, com ou sem prefixo data:image/...;base64,. Obrigatório se fotoCliente não for enviado.
contentTypestringEx.: image/jpeg. Inferido automaticamente quando o base64 já vem como data URL.
filenamestringOpcional. Usado para descobrir a extensão.
fotoClientestringAlternativa ao fileBase64: token retornado pelo Firebase, no formato token.ext.
nomeFotoClientestringObrigatório quando fotoCliente é enviado. Nome do arquivo sem extensão.

Exemplo — upload via API

cURL
# 1) gere o base64 a partir do arquivo local
BASE64=$(base64 -w 0 cliente.jpg)
curl -X POST https://app.techbullsistemas.com.br/api/cliente/foto \
-H "Content-Type: application/json" \
-H "Cookie: session_id=a3f9c1e2b4d6..." \
-d "{
\"cdCliente\": 100,
\"contentType\": \"image/jpeg\",
\"filename\": \"cliente.jpg\",
\"fileBase64\": \"$BASE64\"
}"

Exemplo — já subiu para o Firebase

request body
{
"cdCliente": 100,
"fotoCliente": "a3f9c1e2b4d6e7.jpg",
"nomeFotoCliente": "100"
}

Resposta — 200 OK

response.json
{
"ok": true,
"fotoCliente": "a3f9c1e2b4d6e7.jpg",
"nomeFotoCliente": "100"
}

Remover foto do cliente

DELETE/api/cliente/foto
Cookie session_idclientes:editar

Zera os campos fotoCliente e nomeFotoCliente do cliente. O arquivo no Firebase continua no bucket, mas deixa de ser referenciado.

request body
{ "cdCliente": 100 }

Enviar foto do produto

POST/api/produto/foto
Cookie session_idprodutos:editar

Mesma 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âmetroTipoObrig.Descrição
cdProdutonumberSimCódigo do produto.
fileBase64stringArquivo em base64 (obrigatório se não enviar fotoProduto).
contentTypestringEx.: image/jpeg.
filenamestringUsado para inferir a extensão.
fotoProdutostringToken retornado pelo Firebase (token.ext).
nomeFotoProdutostringObrigatório quando fotoProduto é enviado.
cURL
BASE64=$(base64 -w 0 produto.jpg)
curl -X POST https://app.techbullsistemas.com.br/api/produto/foto \
-H "Content-Type: application/json" \
-H "Cookie: session_id=a3f9c1e2b4d6..." \
-d "{
\"cdProduto\": 55,
\"contentType\": \"image/jpeg\",
\"filename\": \"produto.jpg\",
\"fileBase64\": \"$BASE64\"
}"

Resposta — 200 OK

response.json
{
"ok": true,
"fotoProduto": "a3f9c1e2b4d6e7.jpg",
"nomeFotoProduto": "55"
}

Remover foto do produto

DELETE/api/produto/foto
Cookie session_idprodutos:editar

Limpa fotoProduto e nomeFotoProduto do produto.

request body
{ "cdProduto": 55 }

Listar fotos extras de um produto

GET/api/loja-online/produto-fotos
Cookie session_id

Retorna 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âmetroTipoObrig.Descrição
cdProdutonumberSimCódigo do produto.
cURL
curl "https://app.techbullsistemas.com.br/api/loja-online/produto-fotos?cdProduto=55" \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Resposta — 200 OK

response.json
{
"results": [
{
"id": 12,
"cdProduto": 55,
"fotoNome": "abc123",
"fotoToken": "d4e5f6.jpg",
"ordem": 0
}
]
}

Adicionar foto extra

POST/api/loja-online/produto-fotos
Cookie session_id

Cadastra 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âmetroTipoObrig.Descrição
cdProdutonumberSimCódigo do produto.
fotoNomestringSimNome do arquivo (sem extensão).
fotoTokenstringSimToken retornado pelo Firebase, no formato token.ext.
ordemnumberPosição na galeria (o próximo valor livre é usado se omitido).
request body
{
"cdProduto": 55,
"fotoNome": "abc123",
"fotoToken": "d4e5f6.jpg",
"ordem": 0
}

Reordenar fotos extras

PUT/api/loja-online/produto-fotos
Cookie session_id

Atualiza a ordem de exibição das fotos. Envie os IDs na nova sequência desejada.

request body
{
"cdProduto": 55,
"ids": [12, 15, 14, 13]
}

Excluir foto extra

DELETE/api/loja-online/produto-fotos
Cookie session_id

Remove uma foto da galeria a partir do seu ID.

request body
{ "id": 12 }

Definir foto principal

PUT/api/loja-online/produto-foto-principal
Cookie session_id

Promove 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âmetroTipoObrig.Descrição
cdProdutonumberSimCódigo do produto.
extraIdnumberID da foto extra a ser promovida (mutuamente exclusivo com fotoProduto).
fotoProdutostringToken da nova foto principal (token.ext).
nomeFotoProdutostringNome do arquivo correspondente à foto principal.
promover foto extra
{
"cdProduto": 55,
"extraId": 12
}
definir diretamente
{
"cdProduto": 55,
"fotoProduto": "a3f9c1e2b4d6e7.jpg",
"nomeFotoProduto": "55"
}

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:

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)

getPhotoUrl.ts
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}`
  );
}
Cache-friendly

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

Endpoints para CRUD de títulos financeiros e baixa (recebimento/pagamento) com formas de pagamento.

Listar títulos a receber

GET/api/tituloReceber
Cookie session_idtitulosReceber:consultar

Query parameters

ParâmetroTipoObrig.Descrição
tpPeriodo"E" | "V" | "P"SimTipo de período: E emissão, V vencimento, P pagamento.
cdEmpresanumberEmpresa.
cdPessoanumberCliente.
seriestringSérie do título.
idSituacaostringAB, PG, CA.
dtInidateData inicial.
dtFimdateData final.
vlIninumberValor mínimo.
vlFimnumberValor máximo.
pagenumberPágina.
limitnumberItens por página.
cURL
curl "https://app.techbullsistemas.com.br/api/tituloReceber?tpPeriodo=V&dtIni=2026-01-01&dtFim=2026-12-31" \
-H "Cookie: session_id=a3f9c1e2b4d6..."

Criar/Atualizar/Excluir título a receber

POST/api/tituloReceber
Cookie session_idtitulosReceber:cadastrar

Mé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)

POST/api/recebimento
Cookie session_idcaixa:recebimentoTitulo

Realiza 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âmetroTipoObrig.Descrição
cdEmpresanumberSimEmpresa do recebimento.
titulosarraySimLista de títulos a baixar (mínimo 1).
formasPagamentoarraySimFormas de pagamento usadas (mínimo 1).
vlTotalnumberSimValor total recebido.
vlDescontonumberDesconto aplicado.
vlAcrescimonumberAcréscimo aplicado.
cdClientenumberCliente (para registrar crédito do troco).
request body
{
"cdEmpresa": 1,
"cdCliente": 100,
"titulos": [
{
"cdEmpresa": 1,
"nrTitulo": 500,
"nrParcela": 1,
"serie": "A",
"vlPago": 150.50,
"dtPagto": "2026-04-19T12:00:00.000Z"
}
],
"formasPagamento": [
{ "cdFormaPagamento": 1, "vlBruto": 150.50, "vlTotal": 150.50 }
],
"vlTotal": 150.50,
"vlDesconto": 0,
"vlAcrescimo": 0
}

Resposta — 200 OK

response.json
{
"nrRecebimento": 9001,
"qtTitulos": 1,
"vlTotal": 150.50
}

Listar títulos a pagar

GET/api/tituloPagar
Cookie session_idtitulosPagar:consultar

Query parameters

ParâmetroTipoObrig.Descrição
tpPeriodo"E" | "V" | "P"SimTipo de período (emissão/vencimento/pagamento).
cdEmpresanumberEmpresa.
cdFornecedornumberFornecedor.
cdContanumberConta bancária/caixa.
cdTipoDespesanumberTipo de despesa.
idSituacaostringAB, PG, CA.
dtInidateData inicial.
dtFimdateData final.
pagenumberPágina.
limitnumberItens por página.

Criar/Atualizar/Excluir título a pagar

POST/api/tituloPagar
Cookie session_idtitulosPagar:cadastrar

Aceita POST PUT DELETE. Para excluir, envie nrTitulo no body. Permissões titulosPagar:editar e titulosPagar:excluir.

Pagar título

POST/api/tituloPagar/pagar
Cookie session_idtitulosPagar:pagar

Marca 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.

request body
{
"cdEmpresa": 1,
"nrTitulo": 800,
"nrParcela": 1,
"serie": "A",
"cdFornecedor": 50,
"vlPago": 230.00,
"dtPagto": "2026-04-19T15:00:00.000Z",
"cdConta": 1
}

Cancelar título a pagar

POST/api/tituloPagar/cancelar
Cookie session_idtitulosPagar:cancelar

Cancela um título em aberto. Não funciona em títulos já pagos (use estornar primeiro).

request body
{
"cdEmpresa": 1,
"nrTitulo": 800,
"nrParcela": 1,
"serie": "A",
"cdFornecedor": 50
}

Estornar pagamento

POST/api/tituloPagar/estornar
Cookie session_idtitulosPagar:estornar

Reverte um título já pago, devolvendo-o para a situação aberta e estornando a movimentação na conta.

request body
{
"cdEmpresa": 1,
"nrTitulo": 800,
"nrParcela": 1,
"serie": "A",
"cdFornecedor": 50
}

Entidades de Apoio

Catálogos auxiliares que alimentam o cadastro de produtos, clientes e vendas. A maioria segue o mesmo padrão CRUD.

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

EndpointPermissões baseDescrição
/api/grupoProdutogrupos:*Grupos / categorias de produto.
/api/marcamarcas:*Marcas dos produtos.
/api/corcor:*Cores disponíveis.
/api/tamanhotamanhos:*Tamanhos / grade.
/api/fornecedorfornecedores:*Fornecedores dos produtos.
/api/categoriacategoria:*Categorias de cliente.
/api/tabelaPrecotabelaPreco:*Tabelas de preço.
/api/unidadeunidades:*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

request body
{
"dsMarca": "Urban Wear",
"observacao": "Marca própria da loja"
}

POST /api/grupoProduto

ParâmetroTipoObrig.Descrição
dsGrupostringSimNome do grupo (até 60 caracteres).
idTipo"P" | "S"SimTipo do grupo: P = produto, S = serviço.
prComissaonumberSimPercentual padrão de comissão para esse grupo.
request body
{
"dsGrupo": "Vestuário",
"idTipo": "P",
"prComissao": 0
}

POST /api/unidade

ParâmetroTipoObrig.Descrição
dsUnidadestringSimSigla da unidade (ex.: UN, KG, MT).
dsUnidadeFatorstringSimSigla da unidade de fator (geralmente igual a dsUnidade).
fatornumberSimFator de conversão (1 quando não há conversão).
request body
{
"dsUnidade": "UN",
"dsUnidadeFator": "UN",
"fator": 1
}

Estoque

Movimentações de entrada e saída de estoque. A criação aceita um array para movimentar vários produtos numa mesma chamada.

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).

Pré-requisito para vendas

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

GET/api/movimentoEstoque
Cookie session_idestoque:consultar

Query parameters

ParâmetroTipoObrig.Descrição
cdEmpresanumberEmpresa.
dtInidate (YYYY-MM-DD)Data inicial.
dtFimdate (YYYY-MM-DD)Data final.
pagenumberPágina (default 1).
limitnumberItens por página.

Lançar movimentação(ões)

POST/api/movimentoEstoque
Cookie session_idestoque:cadastrar

O 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âmetroTipoObrig.Descrição
cdEmpresanumberSimEmpresa.
cdProdutonumberSimProduto a movimentar.
cdOperacaoEstoquenumberSimOperação cadastrada (define se é entrada ou saída).
qtdnumberSimQuantidade movimentada (sempre positiva — o sinal vem da operação).
nrDocumentonumberNúmero do documento de origem (NF, ajuste, etc.).
seriestringSérie do documento.
cdPessoanumberCliente ou fornecedor envolvido.
tpPessoa"C" | "F"Tipo da pessoa: C = cliente, F = fornecedor.
obsstringObservação livre.
Campos ignorados silenciosamente

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.

request body
[
{
"cdEmpresa": 1,
"cdProduto": 200,
"cdOperacaoEstoque": 1,
"qtd": 50,
"obs": "Estoque inicial"
},
{
"cdEmpresa": 1,
"cdProduto": 201,
"cdOperacaoEstoque": 1,
"qtd": 30
}
]

Agendamentos

Cadastro de horários para serviços vinculados a clientes, funcionários e produtos/serviços. Útil para nichos como salão de beleza, oficinas, clínicas e consultorias.

Listar agendamentos

GET/api/agendamento
Cookie session_idagendamentos:consultar

Query parameters

ParâmetroTipoObrig.Descrição
cdEmpresanumberEmpresa.
cdAgendamentonumberID específico.
dtAgendamentoInidateInício do período.
dtAgendamentoFimdateFim do período.
cdClientenumberCliente.
cdFuncionarionumberFuncionário responsável.
cdProdutonumberProduto/serviço agendado.
idSituacaonumberSituação do agendamento.

Criar agendamento

POST/api/agendamento
Cookie session_idagendamentos:cadastrar

Cria 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âmetroTipoObrig.Descrição
cdEmpresanumberSimEmpresa.
cdClientenumberSimCliente do agendamento.
dtAgendamentoInidate (ISO-8601)SimData/hora de início.
dtAgendamentoFimdate (ISO-8601)Data/hora de término.
cdFuncionarionumberFuncionário responsável.
idSituacaostringSituação inicial (ex.: AB para aberto / agendado).
observacaostringObservação livre (use observacao, não obs).
colorstringCor para exibição na agenda (hex).
servicosarrayServiç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`.

Sobre o array `servicos`

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).

request body
{
"cdEmpresa": 1,
"cdCliente": 100,
"cdFuncionario": 5,
"dtAgendamentoIni": "2026-04-25T14:00:00.000Z",
"dtAgendamentoFim": "2026-04-25T15:00:00.000Z",
"idSituacao": "AB",
"observacao": "Cliente alérgico a corante",
"color": "#f97316",
"servicos": [
{ "cdProduto": 200 }
]
}

Atualizar agendamento

PUT/api/agendamento
Cookie session_idagendamentos:editar

Mesmo schema do POST, com cdAgendamento obrigatório.

Excluir agendamento

DELETE/api/agendamento
Cookie session_idagendamentos:excluir
request body
{ "cdEmpresa": 1, "cdAgendamento": 42 }

Erros

Todos os erros seguem um formato JSON consistente, com campos em snake_case.

Formato padrão

exemplo de erro
{
"name": "ValidationError",
"message": "O campo \"cdEmpresa\" é obrigatório.",
"action": "Ajuste os dados enviados e tente novamente.",
"status_code": 400,
"error_id": "f3a4...",
"request_id": "9b2c...",
"error_location_code": "MODEL:VALIDATOR:FINAL_SCHEMA",
"key": "cdEmpresa",
"type": "any.required"
}

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:

exemplo (422)
{
"message": "Erro de validação do banco de dados: Argument `prIcms` is missing.",
"action": "Verifique se o campo informado está correto e se todos os campos obrigatórios foram enviados.",
"request_id": "9b2c..."
}
exemplo — argumento desconhecido
{
"message": "Erro de validação do banco de dados: Unknown argument `obs`.",
"action": "Verifique se o campo informado está correto e se todos os campos obrigatórios foram enviados.",
"request_id": "f3a4..."
}

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 campo xxx.
  • Unknown argument `xxx`. → você enviou um campo que não existe nessa entidade.
  • Invalid value for argument `xxx` → o tipo/valor de xxx está errado (ex.: passar string onde espera number).

Códigos de status

StatusQuando acontece
400ValidationError — body/query inválido (campo obrigatório, tipo errado, regra de negócio).
401UnauthorizedError — sessão ausente, expirada ou credenciais incorretas no login.
403ForbiddenError — autenticado, mas sem a feature/permissão necessária.
404NotFoundError — recurso não encontrado.
409Conflito — geralmente violação de chave estrangeira (Prisma P2003).
422UnprocessableEntityError — dados não processáveis.
500InternalServerError — erro inesperado no servidor (anote o request_id).

Dúvidas ou sugestões? Entre em contato pelo formulário do site.