Users
Endpoints da WebApiAlcance para a gestão de usuários - os operadores internos da Alcance Contabilidade (funcionários, responsáveis por carteiras, gestão). Cobrem listagem geral, detalhamento por ID, criação, atualização e exclusão. Para os dados do usuário autenticado, use GET /auth/me (ver Auth).
Todos os endpoints exigem autenticação. Veja Autenticação para o fluxo de API Key. O Swagger oficial está em api.contabilidadealcance.com.br/docs.
Domínio sensível - nunca exponha ao MCP
Gestão de usuários lida com credenciais e privilégios de acesso. As operações de escrita (criar, atualizar, excluir) têm um guard de perfil próprio, além do escopo (ver Notas). Esse domínio não deve ser exposto ao gateway MCP nem a clientes IA.
Base path
/api/v1/usersEscopos necessários
users:read- listagem e detalhamentousers:write- criação, atualização e exclusão
O escopo é derivado da rota: o prefixo /users vira o recurso users, e o método HTTP define a ação (read para GET, write para POST/PUT/DELETE).
Escopo não é suficiente para escrita
Ter users:write não basta para mutar usuários. As rotas POST, PUT e DELETE exigem adicionalmente que o usuário autenticado tenha perfil administrador ou diretoria (require_perfil). Perfil funcionario recebe 403 Forbidden ao tentar criar, editar ou excluir usuários.
Endpoints
GET /users/me foi removida
A rota GET /users/me foi removida da WebApiAlcance. A identidade do usuário autenticado no realm interno é servida exclusivamente por GET /auth/me (ver Auth), que devolve o mesmo tipo de dado (incluindo grupo, username, sub, exp e imagem_perfil) sem exigir o escopo users:read - use-a no lugar desta rota.
POST /users/
Cria um novo usuário no sistema. Além do escopo, exige perfil de gestão (administrador ou diretoria).
Parâmetros
Este endpoint não recebe parâmetros de rota ou query - os dados vão no corpo da requisição (UserCreate): nome, email, login, grupo, telefone e senha (obrigatórios), além de cargo, setor, ativo, role e perfil (opcionais).
Request
{
"nome": "João Lima",
"email": "joao.lima@alcancecontabilidade.com.br",
"login": "joao.lima",
"grupo": "Operações",
"telefone": "71988887777",
"cargo": "Assistente",
"setor": "Contábil",
"senha": "SenhaForte123"
}Response 201 Created
{
"success": true,
"message": "Usuário criado com sucesso",
"data": {
"id": 42,
"nome": "João Lima",
"email": "joao.lima@alcancecontabilidade.com.br",
"login": "joao.lima",
"grupo": "Operações",
"telefone": "71988887777",
"cargo": "Assistente",
"setor": "Contábil",
"ativo": "1",
"role": "user",
"perfil": "funcionario"
}
}Erros de validação de regra de negócio retornam o envelope de erro (success: false).
Escopo: users:write + perfil administrador ou diretoria
GET /users/
Lista todos os usuários cadastrados no sistema. Lista vazia é um estado válido - retorna 200 OK com data: [] e a mensagem "Nenhum usuário encontrado.".
Parâmetros
Este endpoint não recebe parâmetros de rota ou query.
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Lista de usuários recuperada com sucesso",
"data": [
{ "id": 1, "nome": "Administrador", "login": "admin", "perfil": "administrador" },
{ "id": 7, "nome": "Maria Souza", "login": "maria.souza", "perfil": "funcionario" }
]
}Escopo: users:read
GET /users/{user_id}
Detalha um usuário pelo ID inteiro. O data é um UserRead.
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
user_id | int | path | sim | ID interno do usuário |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Usuário encontrado com sucesso",
"data": {
"id": 7,
"nome": "Maria Souza",
"email": "maria.souza@alcancecontabilidade.com.br",
"login": "maria.souza",
"grupo": "Operações",
"telefone": "71999998888",
"cargo": "Analista Contábil",
"setor": "Fiscal",
"ativo": "1",
"role": "user",
"perfil": "funcionario"
}
}Quando não encontrado, retorna o envelope de erro com message: "Usuário não encontrado.".
Escopo: users:read
PUT /users/{user_id}
Atualiza um usuário existente. O body é um UserUpdate com campos parciais - somente o que vier preenchido é alterado. Além do escopo, exige perfil de gestão (administrador ou diretoria).
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
user_id | int | path | sim | ID do usuário |
Request (UserUpdate - todos os campos opcionais, incluindo senha, role e perfil)
{
"cargo": "Analista Sênior",
"setor": "Fiscal",
"ativo": "1"
}Response 200 OK
{
"success": true,
"message": "Usuário atualizado com sucesso",
"data": {
"id": 7,
"nome": "Maria Souza",
"email": "maria.souza@alcancecontabilidade.com.br",
"login": "maria.souza",
"grupo": "Operações",
"telefone": "71999998888",
"cargo": "Analista Sênior",
"setor": "Fiscal",
"ativo": "1",
"role": "user",
"perfil": "funcionario"
}
}Escopo: users:write + perfil administrador ou diretoria
DELETE /users/{user_id}
Remove um usuário do sistema. Operação sensível e destrutiva. Além do escopo, exige perfil de gestão (administrador ou diretoria).
Parâmetros
| Parâmetro | Tipo | Local | Obrigatório | Descrição |
|---|---|---|---|---|
user_id | int | path | sim | ID do usuário |
Request
Sem corpo de requisição.
Response 200 OK
{
"success": true,
"message": "Usuário deletado com sucesso"
}Guard de perfil na exclusão
Além do escopo users:write, este endpoint exige perfil administrador ou diretoria (require_perfil). Exclusão de usuário nunca deve ser exposta ao MCP nem a clientes IA.
Escopo: users:write + perfil administrador ou diretoria
Schemas
UserCreate
Estende UserBase acrescentando senha.
| Campo | Tipo | Obrigatório | Observações |
|---|---|---|---|
nome | str | sim | Nome completo do usuário. |
email | EmailStr | sim | E-mail válido (validação estrita na escrita). |
login | str | sim | Login de acesso. |
grupo | str | sim | Grupo/equipe do usuário. |
telefone | str | sim | Telefone de contato. |
senha | str | sim | Senha em texto. Nunca é retornada em respostas - ver Notas. |
cargo | str | não | Cargo. Opcional. |
setor | str | não | Setor. Opcional. |
ativo | str | não | Situação do usuário. Opcional. |
role | str | não | Papel legado. Default "user". Só concede acesso total quando vale exatamente "admin". |
perfil | PerfilUsuario | não | Primitiva RBAC (ex.: administrador, diretoria, funcionario). Default não-privilegiado. |
UserUpdate
Todos os campos são opcionais; apenas os enviados são atualizados.
| Campo | Tipo | Observações |
|---|---|---|
nome | str | Novo nome. |
email | EmailStr | Novo e-mail (validação estrita na escrita). |
senha | str | Nova senha. Nunca retornada em respostas. |
login | str | Novo login. |
grupo | str | Novo grupo. |
telefone | str | Novo telefone. |
cargo | str | Novo cargo. |
setor | str | Novo setor. |
ativo | str | Nova situação. |
role | str | Novo papel legado. |
perfil | PerfilUsuario | Novo perfil RBAC. |
UserRead
Estende UserBase acrescentando id. Não inclui senha - o campo simplesmente não existe no schema de leitura.
| Campo | Tipo | Notas |
|---|---|---|
id | int | Identificador do usuário. |
nome | str | Nome completo. |
email | str | E-mail. Na leitura é str (tolerante) e não EmailStr - ver Notas. |
login | str | Login de acesso. |
grupo | str | Grupo/equipe. |
telefone | str | Telefone de contato. |
cargo | str | null | Cargo, quando informado. |
setor | str | null | Setor, quando informado. |
ativo | str | null | Situação do usuário. |
role | str | null | Papel legado. |
perfil | PerfilUsuario | Perfil RBAC do usuário. |
Notas
Senha nunca é retornada
senha existe apenas nos schemas de escrita (UserCreate, UserUpdate). O schema de leitura UserRead não possui o campo - nenhum endpoint devolve senha, hash ou credencial em texto. Não há campo de credencial no envelope de resposta.
Escrita exige perfil de gestão
As rotas POST /users/, PUT /users/{user_id} e DELETE /users/{user_id} têm o guard require_perfil("administrador", "diretoria"). Perfil funcionario (ou qualquer não-gestão) recebe 403 Forbidden, mesmo com o escopo users:write. A leitura (GET) segue liberada para qualquer usuário autenticado com users:read.
Validação de e-mail assimétrica
Na escrita o email é EmailStr (validação estrita). Na leitura UserRead.email é apenas str: dados legados com domínios reservados (ex.: .local de usuários de QA) não derrubam a listagem inteira com 500. A validação rígida fica na fronteira de escrita, onde importa.
role vs. perfil (RBAC)
perfil é a primitiva RBAC atual (default não-privilegiado). role é legado e só concede acesso total quando vale exatamente "admin". O default de role é "user" justamente para evitar escalada silenciosa de privilégios em usuários criados sem role explícito.
- Toda resposta segue o envelope
{ success, message, data }(ou{ success: false, message, details }em erro). - Para os dados do usuário autenticado, use
GET /auth/me-GET /users/mefoi removida. Veja Auth.