Pular para o conteúdo principal

Guia para o frontend — APIs CentralCRM (campos, sucesso e erros)

Documento único para integração: auth (public."user" na BD G_DB_POSTGRESS) e companies (DB_DEFAULT_PSTGS, multi-tenant).
Base URL: {BASE_URL}/api (ex.: http://localhost:3000/api).

Inventário de rotas: apis/catalogo-completo.md.
Visão de arquitetura (módulos, BDs, WebSocket): arquitetura/visao-completa.md.
Migração do front (user_profiles → public."user"): FRONTEND_MIGRACAO_AUTH_USERS.md.


1. Formato geral das respostas de erro

O backend usa um filtro global. Em caso de erro HTTP, o corpo JSON costuma seguir:

CampoTipoDescrição
statusCodenumberCódigo HTTP (400, 401, 403, 404, 409, 500, …).
timestampstringData/hora ISO 8601.
pathstringCaminho pedido (ex.: /api/v1/auth/login).
messagestring ou string[]Mensagem única ou lista (validação).

Nota: Em erros de validação (400), o Nest pode devolver message como array com várias frases (uma por campo). O frontend deve aceitar string | string[] e, se for array, juntar ou mostrar a primeira / todas.

Propriedades não permitidas no JSON: com whitelist + forbidNonWhitelisted, campos extra no body geram 400 com mensagem do tipo "property X should not exist".


2. Autenticação Bearer (rotas protegidas)

Rotas como /api/v1/companies exigem:

Authorization: Bearer <access_token>

Dois tipos de token (mesmo segredo JWT_SECRET):

OrigemClaims típicosUso
POST /api/v1/auth/loginsub (+ opcional tenantId, role)Auth, logout, GET/PATCH users, CRM admin (com role admin).
Outro emissor / scriptsub + tenantId/api/v1/companiestenantId é obrigatório no payload do JWT.

Sem token, inválido ou expirado → 401 (mensagem genérica do Passport/JWT).


Parte A — Auth (G_DB_POSTGRESS / public."user")

BD: G_DB_POSTGRESS (conexão userProfilesConnection).
Tabelas: user, user_addresses, user_branding, user_documents, user_permissoes, user_personal_data, permissoes.

Rotas públicas (sem Bearer): login e register.
Demais rotas exigem Authorization: Bearer <accessToken>.


A.1 POST /api/v1/auth/login

CampoObrigatórioRegras
emailSimE-mail válido.
passwordSimNão vazio.
tenantId / tidNãoUUID opcional no JWT emitido.

200: { accessToken, tokenType, expiresIn, user }user é o perfil completo.
Atualiza user.metadata.sessoesAtivas e user.metadata.ultimoAcesso.

HTTPmessage
401Credenciais inválidas.
403Conta não disponível para login. Verifique o estado do utilizador.

A.2 POST /api/v1/auth/logout

Requer Bearer. Decrementa metadata.sessoesAtivas (mínimo 0).

200: { success: true, sessoesAtivas: number }

HTTPmessage
401JWT ausente ou inválido.
404Utilizador não encontrado.

A.3 POST /api/v1/auth/register

CampoObrigatórioRegras
nomeSimMáx. 255.
emailSimE-mail válido.
passwordSim8–128 caracteres.

Campos opcionais: role, displayName, roleNumber, roleId, createdByUuid, status, campos legados (cep, rg, cpf, …) e arrays addresses, documents, permissoes, objetos branding, personalData.

201: UserFullResponseDto (perfil completo).
409: Email já registado.


A.4 GET /api/v1/auth/users/:userId

Requer Bearer. O próprio utilizador ou admin pode consultar.

200: UserFullResponseDto.
403: Sem permissão para ver outro utilizador.
404: Utilizador não encontrado.


A.5 PATCH /api/v1/auth/users/:userId

Patch parcial no user e tabelas relacionais. Arrays addresses, documents, permissoes substituem registos existentes quando enviados.

200: UserFullResponseDto.
403: Sem permissão para alterar outro utilizador.
409: Email já registado.


A.6 PATCH /api/v1/auth/users/:userId/permissions

Body: { grant?: string[], revoke?: string[], updatedBy?: uuid }.
IDs aceites: permissao_id numérico (string) ou chave da tabela permissoes.

200: { userId, granted, revoked, active, updatedAt, updatedBy }.


A.7 GET /api/v1/crm-admin/users

Requer Bearer com role admin. Lista todos os registos de public."user".

200: array de perfis resumidos (UserProfileResponseDto).
403: Apenas administradores podem listar utilizadores do painel CRM de gestão.


A.8 Resposta completa do utilizador (UserFullResponseDto)

Campos principais: id, nomeCompleto, displayName, email, role, roleNumber, roleId, status, metadata, jwtRole, addresses, branding, documents, permissoes, personalData, createdAt, updatedAt, dataCadastro.

Detalhe em FRONTEND_LOGIN.md e FRONTEND_REGISTER_BASE.md.


Parte B — Companies (banco cronospay, multi-tenant)

Todas as rotas abaixo exigem Bearer com JWT que inclua tenantId (além de sub), salvo indicação em contrário.


B.1 POST /api/v1/companies — criar company

Headers

  • Content-Type: application/json
  • Authorization: Bearer <token_com_tenantId>

Body (JSON)

CampoObrigatórioTipoRegras
razaoSocialSimstringNão vazio; máx. 255.
nomeFantasiaNãostringMáx. 255.
cnpjNãostringMáx. 18.
emailNãostringE-mail válido; máx. 255.
telefoneNãostringMáx. 20.
statusNãostringativo | inativo | suspenso (enum). Omite → ativo.
metadataNãoobjectObjeto JSON. Omite → {}.

Sucesso — 201 Created

Objeto com id, tenantId, razaoSocial, nomeFantasia, cnpj, email, telefone, status, metadata, createdAt, updatedAt (datas em ISO 8601).

Erros

HTTPSituaçãomessage
400Validação DTOEx.: "razaoSocial should not be empty", "email must be an email", enum inválido para status.
401Sem Bearer / JWT inválido / token só com sub sem tenantId ao usar rotas que exigem tenantToken inválido: claim obrigatório ausente (sub). ou Contexto de tenant indisponível. Envie um Bearer token válido. (quando falta tenantId no token para rotas que usam tenant).
409Violação de unicidade (ex.: CNPJ repetido no mesmo tenant)Não foi possível criar a company: violação de unicidade (ex.: CNPJ já cadastrado para este tenant).

B.2 GET /api/v1/companies — listar todas (paginação)

  • Autenticação: apenas Bearer JWT válido (sub no token). Não exige tenantId no JWT nem cabeçalho X-Tenant-Id.
  • Lista todas as companies na base, ordenadas por createdAt descendente.

Query (opcional)

ParâmetroPadrãoRegras
pageNumber1Inteiro ≥ 1.
pageSize20Inteiro entre 1 e 100.

Erros

HTTPSituação
401Sem Bearer ou JWT inválido/expirado.

B.3 GET /api/v1/companies/directories/:companyId — obter por id

  • companyId = UUID (v4).
  • A consulta é apenas pelo id da company na base (não usa tenant na cláusula).

Erros

HTTPmessage
404Company não encontrada para o identificador informado.
401Token inválido ou ausente (rota continua protegida por JWT).

3. Rotas públicas (sem Bearer)

MétodoRota
GET/api
GET/api/health
POST/api/v1/auth/login
POST/api/v1/auth/register

4. Sugestões para o frontend

  1. Tratar message como string | string[] nos erros 400.
  2. 401 no login: mostrar mensagem genérica (“Credenciais inválidas”) — não distinguir email vs senha.
  3. Companies (listagem): basta JWT com sub; não é necessário tenantId nem X-Tenant-Id. Para criar company, o fluxo de tenant no POST continua como documentado acima.
  4. 409: mostrar texto devolvido ou mensagem amigável de “já existe / em uso”.

Documento alinhado ao código atual (DTOs, serviços e filtro HTTP). Se o filtro for alterado para devolver sempre message: string[], atualize a secção 1.