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: arquitetura/visao-completa.md.
Migração do front (user_profiles →public."user"): guias/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:
| Campo | Tipo | Descrição |
|---|---|---|
statusCode | number | Código HTTP (400, 401, 403, 404, 409, 500, …). |
timestamp | string | Data/hora ISO 8601. |
path | string | Caminho pedido (ex.: /api/v1/auth/login). |
message | string 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):
| Origem | Claims típicos | Uso |
|---|---|---|
POST /api/v1/auth/login | sub (+ opcional tenantId, role) | Auth, logout, GET/PATCH users, CRM admin (com role admin). |
| Outro emissor / script | sub + tenantId | /api/v1/companies — tenantId é 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
| Campo | Obrigatório | Regras |
|---|---|---|
email | Sim | E-mail válido. |
password | Sim | Não vazio. |
tenantId / tid | Não | UUID opcional no JWT emitido. |
200: { accessToken, tokenType, expiresIn, user } — user é o perfil completo.
Atualiza user.metadata.sessoesAtivas e user.metadata.ultimoAcesso.
| HTTP | message |
|---|---|
| 401 | Credenciais inválidas. |
| 403 | Conta 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 }
| HTTP | message |
|---|---|
| 401 | JWT ausente ou inválido. |
| 404 | Utilizador não encontrado. |
A.3 POST /api/v1/auth/register
| Campo | Obrigatório | Regras |
|---|---|---|
nome | Sim | Máx. 255. |
email | Sim | E-mail válido. |
password | Sim | 8–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/jsonAuthorization: Bearer <token_com_tenantId>
Body (JSON)
| Campo | Obrigatório | Tipo | Regras |
|---|---|---|---|
razaoSocial | Sim | string | Não vazio; máx. 255. |
nomeFantasia | Não | string | Máx. 255. |
cnpj | Não | string | Máx. 18. |
email | Não | string | E-mail válido; máx. 255. |
telefone | Não | string | Máx. 20. |
status | Não | string | ativo | inativo | suspenso (enum). Omite → ativo. |
metadata | Não | object | Objeto JSON. Omite → {}. |
Sucesso — 201 Created
Objeto com id, tenantId, razaoSocial, nomeFantasia, cnpj, email, telefone, status, metadata, createdAt, updatedAt (datas em ISO 8601).
Erros
| HTTP | Situação | message |
|---|---|---|
| 400 | Validação DTO | Ex.: "razaoSocial should not be empty", "email must be an email", enum inválido para status. |
| 401 | Sem Bearer / JWT inválido / token só com sub sem tenantId ao usar rotas que exigem tenant | Token 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). |
| 409 | Violaçã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 (
subno token). Não exigetenantIdno JWT nem cabeçalhoX-Tenant-Id. - Lista todas as companies na base, ordenadas por
createdAtdescendente.
Query (opcional)
| Parâmetro | Padrão | Regras |
|---|---|---|
pageNumber | 1 | Inteiro ≥ 1. |
pageSize | 20 | Inteiro entre 1 e 100. |
Erros
| HTTP | Situação |
|---|---|
| 401 | Sem 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
tenantna cláusula).
Erros
| HTTP | message |
|---|---|
| 404 | Company não encontrada para o identificador informado. |
| 401 | Token inválido ou ausente (rota continua protegida por JWT). |
3. Rotas públicas (sem Bearer)
| Método | Rota |
|---|---|
GET | /api |
GET | /api/health |
POST | /api/v1/auth/login |
POST | /api/v1/auth/register |
4. Sugestões para o frontend
- Tratar
messagecomostring | string[]nos erros 400. - 401 no login: mostrar mensagem genérica (“Credenciais inválidas”) — não distinguir email vs senha.
- Companies (listagem): basta JWT com
sub; não é necessáriotenantIdnemX-Tenant-Id. Para criar company, o fluxo de tenant noPOSTcontinua como documentado acima. - 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.