API — Branches
Todos os endpoints são prefixados com /api/t/:slug/admin/branches. Requerem JWT com role admin ou superadmin, ou role branch_manager com assignedBranchIds incluindo a filial alvo.
Filiais
Listar Filiais
GET /api/t/:slug/admin/branchesQuery params: active (boolean), page, limit
Response 200:
{
"data": [
{
"_id": "...",
"name": "Unidade Centro",
"slug": "centro",
"active": true,
"isHQ": true,
"cnpj": "12.345.678/0001-00",
"city": "São Paulo",
"state": "SP"
}
],
"total": 3,
"page": 1,
"totalPages": 1
}Criar Filial
POST /api/t/:slug/admin/branchesBody:
{
"name": "Unidade Pinheiros",
"slug": "pinheiros",
"cnpj": "12.345.678/0002-91",
"address": "Rua das Flores, 123",
"city": "São Paulo",
"state": "SP",
"cep": "01452-001",
"ibsCbsEnabled": false
}Response 201: Branch criada.
Comparativo Multi-Filial
GET /api/t/:slug/admin/branches/compare?from=2026-04-01&to=2026-04-25Retorna métricas agregadas lado a lado para todas as filiais no período.
Detalhe da Filial
GET /api/t/:slug/admin/branches/:idAtualizar Filial
PUT /api/t/:slug/admin/branches/:idBody: qualquer subconjunto dos campos da criação.
Remover Filial
DELETE /api/t/:slug/admin/branches/:idAtenção: rejeita se a filial tiver PDVs ou turnos ativos.
KPIs da Filial
GET /api/t/:slug/admin/branches/:id/statsResponse 200:
{
"totalRevenue": 84200.50,
"totalOrders": 1240,
"activeShifts": 2,
"activeOperators": 2,
"lowStockItems": 3
}PDVs da Filial
Listar PDVs
GET /api/t/:slug/admin/branches/:id/pdvsResponse 200:
[
{
"_id": "...",
"name": "Caixa 1",
"slug": "caixa-1",
"serviceMode": "balcao",
"active": true,
"branch": "...",
"activeShift": {
"_id": "...",
"user": { "name": "Ana Lima" },
"startedAt": "2026-04-25T08:00:00Z",
"openingFloat": 100.00
}
}
]Turnos via Filial
Turnos Ativos
GET /api/t/:slug/admin/branches/:id/shifts/activeRetorna todos os turnos status: open nos PDVs desta filial, populados com pdv.name e user.name.
Response 200:
[
{
"_id": "...",
"pdv": { "_id": "...", "name": "Caixa 1", "slug": "caixa-1" },
"user": { "name": "Ana Lima", "email": "ana@demo.com" },
"startedAt": "2026-04-25T08:00:00Z",
"openingFloat": 100.00,
"status": "open"
}
]Abrir Turno
POST /api/t/:slug/admin/branches/:id/shifts/openBody:
{
"pdvId": "...",
"openingFloat": 100.00,
"userId": "..."
}Validação server-side: pdv.branch === branchId — retorna 403 se o PDV não pertencer a esta filial.
Response 201: ShiftDocument com status: open.
Relatório Diário
GET /api/t/:slug/admin/branches/:id/daily-report?date=2026-04-25Query params:
date— formatoYYYY-MM-DD(default: hoje)
Response 200:
{
"totals": {
"revenue": 3420.50,
"cash": 980.00,
"card": 1840.50,
"pix": 600.00,
"orders": 47,
"shifts": 3
},
"byPdv": [
{
"pdvId": "abc123",
"pdvName": "Caixa 1",
"revenue": 1240.00,
"cash": 320.00,
"card": 720.00,
"pix": 200.00,
"orders": 18,
"shifts": 1
},
{
"pdvId": "def456",
"pdvName": "Caixa 2",
"revenue": 2180.50,
"cash": 660.00,
"card": 1120.50,
"pix": 400.00,
"orders": 29,
"shifts": 2
}
]
}Implementação: aggregation pipeline MongoDB O(shifts) — sem $lookup em Orders.
Erros Comuns
| Status | Situação |
|---|---|
401 | Token ausente ou expirado |
403 | Usuário não tem acesso a esta filial (assignedBranchIds) |
403 | PDV não pertence à filial (no endpoint shifts/open) |
404 | Filial não encontrada |
409 | Slug duplicado no tenant |