Autenticação
A LightHouse API usa JWT Bearer para autenticar requisições. Os tokens são emitidos pelo AuthCenter — o provedor de identidade central do Leankeep — e validados pela API a cada chamada.
Visão geral do fluxo
┌──────────┐ 1. credenciais ┌──────────────┐
│ Cliente │ ──────────────────► │ AuthCenter │
│ │ ◄────────────────── │ (identidade)│
└──────────┘ 2. JWT (access) └──────────────┘
│
│ 3. Authorization: Bearer <JWT>
▼
┌──────────────────┐ 4. valida assinatura via JWKS
│ LightHouse API │ ──────────────────────────────► AuthCenter /jwks
│ │ ◄────────────────────────────── chaves públicas
└──────────────────┘ 5. extrai claims (empresa, usuário) e responde
- O cliente autentica no AuthCenter e recebe um
access_token(JWT). - O cliente envia o token em toda requisição à LightHouse API.
- A API valida a assinatura do token usando as chaves públicas do JWKS do AuthCenter.
- A API extrai os claims de contexto (empresa, usuário) e aplica as regras de autorização.
Ambientes
| Ambiente | AuthCenter (emissão de token) | LightHouse API (dados) |
|---|---|---|
| Produção | https://auth.lkp.app.br | https://lighthousev2.lkp.app.br |
| Sandbox | https://auth.lkp.dev.br | https://lighthouse.lkp.dev.br |
Obtendo o token (AuthCenter)
O token é emitido pelo AuthCenter via POST com corpo multipart/form-data.
| Ambiente | Endpoint |
|---|---|
| Produção | POST https://auth.lkp.app.br/v1/auth/ |
| Sandbox | POST https://auth.lkp.dev.br/v1/auth/ |
Campos do formulário
| Campo | Tipo | Descrição |
|---|---|---|
login | string | Usuário (e-mail ou login configurado) |
Password | string | Senha |
Plataform | int | Origem da requisição. Mesmo enum EPlataforma usado no campo plataforma dos corpos da LightHouse API (ver Glossário → plataforma) — testado: 6 (API) funciona em ambos. Para integrações via API, use 6. |
ExpireCurrentSession | bool | True encerra sessão ativa anterior |
StayConnected | bool | True mantém sessão prolongada |
Exemplo cURL — produção
curl --location 'https://auth.lkp.app.br/v1/auth/' \
--form 'login=SEU_USUARIO' \
--form 'Password=SUA_SENHA' \
--form 'Plataform=6' \
--form 'ExpireCurrentSession=True' \
--form 'StayConnected=True'
curl --form campo=valor já delimita o valor pela sintaxe do próprio --form. Escrever --form 'login="SEU_USUARIO"' (aspas duplas dentro das aspas simples) envia as aspas como parte literal do valor — testado: o AuthCenter espera o valor sem aspas internas.
Exemplo cURL — sandbox
curl --location 'https://auth.lkp.dev.br/v1/auth/' \
--form 'login=SEU_USUARIO' \
--form 'Password=SUA_SENHA' \
--form 'Plataform=6' \
--form 'ExpireCurrentSession=True' \
--form 'StayConnected=False'
Resposta
{
"success": true,
"message": null,
"hasActiveSession": false,
"authToken": {
"jti": "c1d5914709eb4ca19e67dd71e417ed20",
"token": "<JWT>",
"refreshToken": "<refresh>",
"expiresIn": "2026-07-01T20:40:14.449893Z",
"refreshExpiresIn": "2026-07-08T18:40:14.4551852Z"
}
}
| Campo | Descrição |
|---|---|
success | true se a autenticação foi bem-sucedida. |
message | Mensagem de erro/aviso, quando houver (null em caso de sucesso). |
hasActiveSession | true se já havia uma sessão ativa para o usuário (ver ExpireCurrentSession acima). |
authToken.jti | ID único do token (JWT ID) — útil para rastreio/revogação. |
authToken.token | O JWT a ser usado nas chamadas. Vai em Authorization: Bearer <authToken.token>. |
authToken.expiresIn | Data/hora (UTC) de expiração do token. Vale por ~2 horas a partir da emissão. |
authToken.refreshToken | Token de renovação — usado apenas no endpoint de refresh (abaixo), nunca na LightHouse API. |
authToken.refreshExpiresIn | Data/hora (UTC) de expiração do refreshToken. Vale por ~7 dias. |
O token não vem no topo da resposta — está em authToken.token. Um erro comum é tentar usar response.token diretamente; o campo correto é response.authToken.token.
Renovando o token (refresh)
Antes que o token expire (authToken.expiresIn, ~2h), renove-o usando o authToken.refreshToken — sem precisar reautenticar com usuário e senha.
| Ambiente | Endpoint |
|---|---|
| Produção | POST https://auth.lkp.app.br/v1/auth/refresh |
| Sandbox | POST https://auth.lkp.dev.br/v1/auth/refresh |
O login (POST /v1/auth/) usa multipart/form-data. O refresh usa application/x-www-form-urlencoded — é intencional, não confunda os dois formatos. Enviar o refresh como multipart (ou o login como urlencoded) resulta em erro de parsing no AuthCenter.
Campos do formulário
| Campo | Tipo | Descrição |
|---|---|---|
Token | string | O JWT atual (authToken.token), mesmo que já esteja perto de expirar. |
RefreshToken | string | O authToken.refreshToken recebido no login (ou no refresh anterior). |
Exemplo cURL
curl --location 'https://auth.lkp.app.br/v1/auth/refresh' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'Token=SEU_JWT' \
--data-urlencode 'RefreshToken=SEU_REFRESH_TOKEN'
A resposta tem a mesma estrutura do login — success, authToken.token, authToken.refreshToken, authToken.expiresIn, authToken.refreshExpiresIn — só que com a expiração renovada. Substitua o token e o refresh token armazenados pelos novos valores retornados.
Padrão de uso recomendado
- Autentique uma vez (
POST /v1/auth/) e guardeauthToken.tokeneauthToken.refreshToken. - Use
authToken.tokenem todas as chamadas até perto deauthToken.expiresIn. - Antes de expirar (~2h), chame
POST /v1/auth/refreshcom oTokeneRefreshTokenatuais. - Substitua os valores armazenados pelos novos
authToken.token/authToken.refreshTokenda resposta. - Se o
refreshTokentambém expirar (~7 dias sem uso), reautentique com usuário e senha — não há como renovar depois desse prazo.
Enviando o token
Inclua o header em todas as chamadas, usando o valor de authToken.token obtido no login (ou no refresh):
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6...
curl "https://lighthousev2.lkp.app.br/v1/empresas/ativas" \
-H "Authorization: Bearer SEU_TOKEN"
Contexto de empresa
Não existe um padrão único: dependendo do endpoint, a API espera o empresaId de uma forma diferente. Confira sempre os parâmetros do endpoint específico na Referência de API antes de montar a chamada — nunca assuma o padrão por analogia com outro endpoint.
Tabela canônica — contexto de empresa por endpoint
| Padrão | Onde vai o empresaId | Endpoints (exemplos) |
|---|---|---|
| Header HTTP obrigatório | EmpresaId como header — não é query param | GET /v1|v2|v3/ocorrencias, GET /v1|v3/ocorrencias/count, os 4 GET /v1/reports/* |
| Header HTTP (kit de discovery, validado 07/2026) | EmpresaId como header — não é query param | GET /v1/unidades/ativas, GET /v1/sistemas, GET /v1/areas, GET /v1/equipamentos, GET /v1/usuarios — ver Primeiros passos → Descobrindo seu EmpresaId |
| Path param | {empresaId} na própria URL | GET /v3/ocorrencias/config/{empresaId}, GET /v3/ocorrencias/tipicas/{empresaId} |
| Campo obrigatório no corpo | empresaId no JSON do POST/PUT | POST /v3/ocorrencias (SaveOcorrenciaCommand) |
| ⚠️ Indefinido | spec declara EmpresaId como query param opcional, mas o comportamento real não foi confirmado — um 500 de sintaxe nesse endpoint mascarou o teste isolado (ver Dar baixa em lote → Passo 1) | GET /v1/atividades |
Fora esses padrões, não existe um formato de EmpresaId como query param nos endpoints de ocorrências — se você ver esse formato em algum exemplo desta documentação, é erro do exemplo, não um padrão válido da API. Para /v1/atividades, o formato indefinido acima é a exceção conhecida.
As regras de autorização dependem do escopo resolvido: um usuário só enxerga dados das empresas a que tem acesso. Veja a matriz de acesso por tipo de usuário em Conceitos de domínio.
Endpoints sem autenticação
Poucos endpoints dispensam token:
| Endpoint | Uso |
|---|---|
GET /v{N}/qrcode/public | Leitura de QR Code público (área/equipamento sem login). |
Todos os demais exigem Authorization: Bearer.
Erros de autenticação
| Código | Significado | Ação |
|---|---|---|
401 Unauthorized | Token ausente, expirado ou assinatura inválida. | Reautentique no AuthCenter e obtenha um novo token. |
403 Forbidden | Autenticado, mas sem permissão para o recurso/empresa. | Verifique o escopo do usuário. |
Boas práticas
- Cache do token respeitando a expiração; não reautentique a cada chamada.
- Renove com antecedência — chame o refresh antes de
authToken.expiresIn(~2h) para evitar401no meio de uma operação. - Relógio sincronizado — claims de expiração são sensíveis a clock skew.
- Nunca exponha o token, o refresh token ou o
jtiem logs, URLs ou no front-end público.