API de Usuários
CRUD de usuários da empresa via API.
Gerencie os usuários da sua empresa no Bunto ERP. Este endpoint permite listar, consultar, criar, atualizar e desativar usuários de forma programática.
Segurança: Senhas não são expostas nem aceitas via API. A gestão de senhas é feita exclusivamente pelo painel administrativo do ERP.
Visão Geral
| Propriedade | Valor |
|---|---|
| Base URL (produção) | https://api-backend.bunto.com.br/v1/usuarios/ |
| Autenticação | Authorization: Bearer bnt_xxx |
| Formato | JSON |
| Escopo necessário (leitura) | usuarios: read |
| Escopo necessário (escrita) | usuarios: write |
| Escopo necessário (exclusão) | usuarios: delete |
Endpoints
| Método | Endpoint | Descrição | Escopo |
|---|---|---|---|
| GET | /v1/usuarios/ | Listar usuários | usuarios: read |
| GET | /v1/usuarios/{id}/ | Detalhar usuário | usuarios: read |
| POST | /v1/usuarios/ | Criar usuário | usuarios: write |
| PUT | /v1/usuarios/{id}/ | Atualizar usuário (completo) | usuarios: write |
| PATCH | /v1/usuarios/{id}/ | Atualizar usuário (parcial) | usuarios: write |
| DELETE | /v1/usuarios/{id}/ | Desativar usuário (soft delete) | usuarios: delete |
Nota: O endpoint DELETE não exclui o registro permanentemente. Ele define is_active como false, desativando o acesso do usuário. O usuário pode ser reativado posteriormente via PATCH.
Listar Usuários
GET /v1/usuarios/
Escopo necessário: usuarios: read
Retorna a lista paginada de usuários ativos da empresa. Por padrão, usuários inativos são excluídos da listagem.
Query Parameters
| Parâmetro | Tipo | Padrão | Descrição |
|---|---|---|---|
pagina | integer | 1 | Número da página |
por_pagina | integer | 25 | Registros por página (máximo: 100) |
busca | string | - | Busca por username, nome ou e-mail |
user_type | string | - | Filtrar por tipo: usuario, vendedor, funcionario, dono, superuser, representante |
incluir_inativos | string | - | Se true, inclui usuários inativos (padrão: somente ativos) |
ordenar | string | username | Campo de ordenação: username, first_name, email, date_joined |
direcao | string | asc | Direção da ordenação: asc ou desc |
Exemplo com cURL
bashcurl 'https://api-backend.bunto.com.br/v1/usuarios/?pagina=1&por_pagina=25&user_type=vendedor&ordenar=first_name&direcao=asc' \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } # Listar vendedores ativos resposta = requests.get( f"{BASE_URL}/usuarios/", headers=headers, params={ "pagina": 1, "por_pagina": 25, "user_type": "vendedor", "ordenar": "first_name", "direcao": "asc", }, ) dados = resposta.json() if dados["success"]: usuarios = dados["data"]["resultados"] paginacao = dados["data"]["paginacao"] print(f"Total de usuários: {paginacao['total_registros']}") for usuario in usuarios: print(f" - {usuario['first_name']} {usuario['last_name']} ({usuario['username']}) - {usuario['user_type']}") else: print(f"Erro: {resposta.status_code}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const params = new URLSearchParams({ pagina: "1", por_pagina: "25", user_type: "vendedor", ordenar: "first_name", direcao: "asc", }); const resposta = await fetch(`${BASE_URL}/usuarios/?${params}`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const usuarios = dados.data.resultados; const paginacao = dados.data.paginacao; console.log(`Total de usuários: ${paginacao.total_registros}`); usuarios.forEach((usuario) => { console.log( ` - ${usuario.first_name} ${usuario.last_name} (${usuario.username}) - ${usuario.user_type}` ); }); } else { console.error(`Erro: ${resposta.status}`); }
Resposta (200 OK)
json{ "success": true, "message": "8 registros encontrados", "data": { "resultados": [ { "id": 1, "username": "ana.silva", "first_name": "Ana", "last_name": "Silva", "email": "ana.silva@empresa.com.br", "user_type": "vendedor", "is_active": true, "date_joined": "2026-01-10T08:00:00-03:00" }, { "id": 2, "username": "carlos.santos", "first_name": "Carlos", "last_name": "Santos", "email": "carlos.santos@empresa.com.br", "user_type": "vendedor", "is_active": true, "date_joined": "2026-01-15T09:30:00-03:00" } ], "paginacao": { "pagina_atual": 1, "total_paginas": 1, "total_registros": 8, "por_pagina": 25, "proxima": null, "anterior": null } } }
Campos da Listagem
| Campo | Tipo | Descrição |
|---|---|---|
id | integer | Identificador único do usuário |
username | string | Nome de usuário (login) |
first_name | string | Primeiro nome |
last_name | string | Sobrenome |
email | string | Endereço de e-mail |
user_type | string | Tipo: usuario, vendedor, funcionario, dono, superuser, representante |
is_active | boolean | Se o usuário está ativo |
date_joined | datetime | Data e hora do cadastro |
Obter Usuário
GET /v1/usuarios/{id}/
Escopo necessário: usuarios: read
Retorna os dados completos de um usuário específico, incluindo informações adicionais como último login e empresa vinculada.
Exemplo com cURL
bashcurl https://api-backend.bunto.com.br/v1/usuarios/1/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } usuario_id = 1 resposta = requests.get(f"{BASE_URL}/usuarios/{usuario_id}/", headers=headers) dados = resposta.json() if dados["success"]: usuario = dados["data"] print(f"Usuário: {usuario['first_name']} {usuario['last_name']}") print(f"Username: {usuario['username']}") print(f"Tipo: {usuario['user_type']}") print(f"Último login: {usuario['last_login']}") else: print(f"Erro: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const usuarioId = 1; const resposta = await fetch(`${BASE_URL}/usuarios/${usuarioId}/`, { headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, }); const dados = await resposta.json(); if (dados.success) { const usuario = dados.data; console.log(`Usuário: ${usuario.first_name} ${usuario.last_name}`); console.log(`Username: ${usuario.username}`); console.log(`Tipo: ${usuario.user_type}`); console.log(`Último login: ${usuario.last_login}`); } else { console.error(`Erro: ${JSON.stringify(dados)}`); }
Resposta (200 OK)
json{ "success": true, "message": "Registro encontrado", "data": { "id": 1, "username": "ana.silva", "first_name": "Ana", "last_name": "Silva", "email": "ana.silva@empresa.com.br", "user_type": "vendedor", "is_active": true, "date_joined": "2026-01-10T08:00:00-03:00", "last_login": "2026-02-12T14:22:00-03:00", "empresa_id": 1 } }
Campos do Detalhe (adicionais à listagem)
| Campo | Tipo | Descrição |
|---|---|---|
last_login | datetime / null | Data e hora do último login (null se nunca fez login) |
empresa_id | integer | ID da empresa à qual o usuário pertence |
Criar Usuário
POST /v1/usuarios/
Escopo necessário: usuarios: write
Cria um novo usuário vinculado à empresa do token autenticado. O usuário criado receberá uma senha temporária gerada pelo sistema e deverá alterá-la no primeiro acesso pelo painel.
Campos do Request Body
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
first_name | string | Sim | Primeiro nome (máximo 150 caracteres) |
last_name | string | Sim | Sobrenome (máximo 150 caracteres) |
email | string | Sim | Endereço de e-mail válido |
username | string | Sim | Nome de usuário para login (máximo 150 caracteres) |
user_type | string | Não | Tipo: usuario (padrão), vendedor, funcionario, dono |
is_active | boolean | Não | Se o usuário está ativo (padrão: true) |
Nota sobre senhas: A API não aceita o campo senha. Uma senha temporária é gerada automaticamente pelo sistema. O usuário deverá definir sua própria senha pelo painel do ERP.
Exemplo com cURL
bashcurl -X POST https://api-backend.bunto.com.br/v1/usuarios/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "first_name": "Maria", "last_name": "Oliveira", "email": "maria.oliveira@empresa.com.br", "username": "maria.oliveira", "user_type": "vendedor", "is_active": true }'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } novo_usuario = { "first_name": "Maria", "last_name": "Oliveira", "email": "maria.oliveira@empresa.com.br", "username": "maria.oliveira", "user_type": "vendedor", "is_active": True, } resposta = requests.post(f"{BASE_URL}/usuarios/", headers=headers, json=novo_usuario) dados = resposta.json() if dados["success"]: usuario = dados["data"] print(f"Usuário criado com sucesso! ID: {usuario['id']}") print(f"Nome: {usuario['first_name']} {usuario['last_name']}") print(f"Username: {usuario['username']}") else: print(f"Erro ao criar usuário: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const novoUsuario = { first_name: "Maria", last_name: "Oliveira", email: "maria.oliveira@empresa.com.br", username: "maria.oliveira", user_type: "vendedor", is_active: true, }; const resposta = await fetch(`${BASE_URL}/usuarios/`, { method: "POST", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(novoUsuario), }); const dados = await resposta.json(); if (dados.success) { console.log(`Usuário criado com sucesso! ID: ${dados.data.id}`); console.log(`Nome: ${dados.data.first_name} ${dados.data.last_name}`); console.log(`Username: ${dados.data.username}`); } else { console.error(`Erro ao criar usuário:`, dados); }
Resposta (201 Created)
json{ "success": true, "message": "Usuário criado com sucesso", "data": { "id": 9, "username": "maria.oliveira", "first_name": "Maria", "last_name": "Oliveira", "email": "maria.oliveira@empresa.com.br", "user_type": "vendedor", "is_active": true, "date_joined": "2026-02-12T15:30:00-03:00", "last_login": null, "empresa_id": 1 } }
Atualizar Usuário
PUT /v1/usuarios/{id}/
PATCH /v1/usuarios/{id}/
Escopo necessário: usuarios: write
Atualiza um usuário existente. Use PUT para atualização completa ou PATCH para atualização parcial (apenas os campos enviados serão alterados).
Exemplo com cURL (PATCH - atualização parcial)
bashcurl -X PATCH https://api-backend.bunto.com.br/v1/usuarios/9/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{ "user_type": "funcionario", "email": "maria.oliveira.novo@empresa.com.br" }'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = { "Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json", } usuario_id = 9 # Atualizacao parcial (PATCH) - apenas os campos que mudaram atualizacao = { "user_type": "funcionario", "email": "maria.oliveira.novo@empresa.com.br", } resposta = requests.patch( f"{BASE_URL}/usuarios/{usuario_id}/", headers=headers, json=atualizacao, ) dados = resposta.json() if dados["success"]: usuario = dados["data"] print(f"Usuário atualizado! Tipo: {usuario['user_type']}") else: print(f"Erro ao atualizar: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const usuarioId = 9; const atualizacao = { user_type: "funcionario", email: "maria.oliveira.novo@empresa.com.br", }; const resposta = await fetch(`${BASE_URL}/usuarios/${usuarioId}/`, { method: "PATCH", headers: { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json", }, body: JSON.stringify(atualizacao), }); const dados = await resposta.json(); if (dados.success) { console.log(`Usuário atualizado! Tipo: ${dados.data.user_type}`); } else { console.error(`Erro ao atualizar:`, dados); }
Resposta (200 OK)
json{ "success": true, "message": "Usuário atualizado com sucesso", "data": { "id": 9, "username": "maria.oliveira", "first_name": "Maria", "last_name": "Oliveira", "email": "maria.oliveira.novo@empresa.com.br", "user_type": "funcionario", "is_active": true, "date_joined": "2026-02-12T15:30:00-03:00", "last_login": null, "empresa_id": 1 } }
Desativar Usuário (Soft Delete)
DELETE /v1/usuarios/{id}/
Escopo necessário: usuarios: delete
Desativa o usuário (soft delete). O registro não é removido permanentemente do banco de dados -- o campo is_active é definido como false, bloqueando o acesso ao painel.
Exemplo com cURL
bashcurl -X DELETE https://api-backend.bunto.com.br/v1/usuarios/9/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4'
Exemplo com Python
pythonimport requests BASE_URL = "https://api-backend.bunto.com.br/v1" TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4" headers = {"Authorization": f"Bearer {TOKEN}"} usuario_id = 9 resposta = requests.delete(f"{BASE_URL}/usuarios/{usuario_id}/", headers=headers) dados = resposta.json() if dados["success"]: print("Usuário desativado com sucesso!") else: print(f"Erro ao desativar: {dados}")
Exemplo com JavaScript
javascriptconst BASE_URL = "https://api-backend.bunto.com.br/v1"; const TOKEN = "bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4"; const usuarioId = 9; const resposta = await fetch(`${BASE_URL}/usuarios/${usuarioId}/`, { method: "DELETE", headers: { Authorization: `Bearer ${TOKEN}`, }, }); const dados = await resposta.json(); if (dados.success) { console.log("Usuário desativado com sucesso!"); } else { console.error(`Erro ao desativar:`, dados); }
Resposta (200 OK)
json{ "success": true, "message": "Usuário desativado com sucesso" }
Importante: Usuários desativados não aparecem nas listagens padrão. Para visualizá-los, use o parâmetro incluir_inativos=true. Para reativar um usuário, envie um PATCH com "is_active": true.
Reativar Usuário
bashcurl -X PATCH https://api-backend.bunto.com.br/v1/usuarios/9/ \ -H 'Authorization: Bearer bnt_A1b2C3d4E5f6G7h8I9j0K1l2M3n4O5p6Q7r8S9t0U1v2W3x4' \ -H 'Content-Type: application/json' \ -d '{"is_active": true}'
Erros Comuns
| Código | Erro | Causa | Solução |
|---|---|---|---|
| 400 | VALIDATION_ERROR | Dados enviados são inválidos (campo obrigatório ausente, e-mail inválido, etc.) | Verifique os campos obrigatórios e os tipos de dados |
| 401 | Token invalido | Token ausente, expirado, revogado ou mal formatado | Verifique se o header é Authorization: Bearer bnt_xxx |
| 403 | Token nao tem permissao | O token não possui o escopo usuarios ou a ação necessária (read, write, delete) | Verifique os escopos do token no painel |
| 404 | Nao encontrado | Usuário não existe ou pertence a outra empresa | Confirme o ID e se o usuário pertence à empresa do token |
| 429 | Limite de requisicoes excedido | Rate limit ultrapassado para o tipo de operação | Implemente retry com backoff exponencial |
Exemplo de Resposta de Erro (400)
json{ "success": false, "error": { "code": "VALIDATION_ERROR", "message": "Erro de validacao", "details": { "email": ["Insira um endereço de email valido."], "username": ["Um usuário com este nome de usuário ja existe."] } } }
Exemplo de Resposta de Erro (403)
json{ "detail": "Token nao tem permissao para este recurso" }
Rate Limiting
A API aplica limites de requisição por token (não por IP). Cada tipo de operação tem um limite diferente.
| Operação | Métodos HTTP | Limite |
|---|---|---|
| Leitura | GET, HEAD, OPTIONS | 120 requisições/minuto |
| Escrita | POST, PUT, PATCH | 30 requisições/minuto |
| Exclusão | DELETE | 10 requisições/minuto |
Ao exceder o limite, a API retorna 429 Too Many Requests:
json{ "detail": "Limite de requisicoes excedido. Tente novamente em 45 segundos." }
Boas práticas
- Use
por_pagina=100para reduzir o número de requisições ao listar usuários - Implemente retry com backoff exponencial ao receber
429 - Armazene dados em cache local quando possível
- Para atualizações em lote, use
PATCHapenas com os campos alterados para economizar requisições de escrita
Paginação
Todos os endpoints de listagem retornam dados paginados.
Parâmetros
| Parâmetro | Tipo | Padrão | Máximo | Descrição |
|---|---|---|---|---|
pagina | integer | 1 | - | Número da página |
por_pagina | integer | 25 | 100 | Registros por página |
Atenção: Os parâmetros são pagina e por_pagina (em português), não page e per_page.
Objeto paginacao na resposta
| Campo | Tipo | Descrição |
|---|---|---|
pagina_atual | integer | Número da página atual |
total_paginas | integer | Total de páginas disponíveis |
total_registros | integer | Total de registros encontrados |
por_pagina | integer | Registros por página |
proxima | string / null | URL da próxima página (null se for a última) |
anterior | string / null | URL da página anterior (null se for a primeira) |
Valores de Referência
Tipo de Usuário
| Valor | Descrição |
|---|---|
usuario | Usuário padrão com acesso ao painel |
vendedor | Vendedor com acesso ao PDV e vendas |
funcionario | Funcionário com permissões definidas por grupo |
dono | Proprietário da empresa (acesso completo) |
superuser | Super administrador do sistema |
representante | Representante comercial externo |