01Autenticação e escopos
Toda chamada leva uma chave de API no cabeçalho Authorization: Bearer evk_.... As chaves são criadas por administradores e proprietários da empresa em Configuração > Integrações > API. O valor da chave aparece uma vez só, na criação; o evobits guarda apenas o hash dela.
Cada chave tem escopos: só as rotas dos escopos marcados respondem. Uma chave pode ter um recorte por grupo de usuários: ela enxerga exatamente os dispositivos que aquele grupo enxerga, e o que está fora responde 404, como se não existisse. Escrever com recorte (reconhecer alerta, agendar manutenção) exige acesso de escrita no grupo do alvo.
| Escopo | Tipo | O que libera |
|---|---|---|
| dispositivos.ler | lê | lista e detalhe de dispositivos, com estado. GET /dispositivos, GET /dispositivos/{id}, GET /grupos |
| dispositivos.criar | escreve | cria grupos, dispositivos e sensores; heartbeat revela o token uma única vez. POST /grupos, POST /dispositivos, POST /dispositivos/{id}/sensores |
| sensores.ler | lê | sensores de cada dispositivo, sem a configuração. GET /sensores, GET /sensores/{id}, GET /estado |
| medidas.ler | lê | séries de medidas por sensor e período, e o CSV de medidas. GET /sensores/{id}/medidas, GET /medidas.csv |
| eventos.ler | lê | mudanças de estado e eventos, e o CSV de eventos. GET /eventos, GET /eventos/{id}, GET /eventos.csv |
| alertas.ler | lê | alertas ativos e histórico. GET /alertas, GET /alertas/{id} |
| manutencoes.ler | lê | janelas de manutenção vigentes e futuras. GET /manutencoes |
| metricas.ler | lê | exportador Prometheus em /api/v1/metrics. GET /metrics |
| relatorios.ler | lê | disponibilidade por período. GET /disponibilidade |
| alertas.operar | escreve | reconhecer alertas. POST /alertas/{id}/reconhecer |
| manutencoes.escrever | escreve | agendar, alterar e apagar janelas de manutenção. POST /manutencoes, PATCH /manutencoes/{id}, DELETE /manutencoes/{id} |
Rotacionar cria uma chave nova com os mesmos escopos e recorte; a anterior pode seguir valendo por até 7 dias para dar tempo de trocar. Revogar é imediato. Toda escrita feita por chave entra na Auditoria da empresa com o nome da chave.
02Erros e limites
Erros vêm em JSON no formato {"error": "codigo", "message": "texto"}.
| HTTP | error | Quando |
|---|---|---|
| 400 | cursor_invalido, intervalo_invalido, escopo_invalido, periodo_longo, fuso_invalido | parâmetro fora do formato |
| 401 | chave_invalida | chave ausente, fora do formato, inexistente ou revogada |
| 401 | chave_expirada | a chave passou da validade |
| 403 | escopo_insuficiente | a chave não tem o escopo da rota (o campo escopo diz qual) |
| 403 | empresa_suspensa | a empresa está suspensa ou com a coleta parada |
| 404 | nao_encontrado | não existe ou está fora do recorte da chave |
| 422 | muitas_linhas | o CSV passaria de 200 mil linhas: reduza o período ou o escopo, ou use uma agregação maior |
| 429 | muitas_requisicoes | passou do limite por minuto da chave |
O limite de requisições por minuto vale por chave e é definido pelo plano da empresa. Toda resposta autenticada traz x-ratelimit-limit, x-ratelimit-remaining e x-ratelimit-reset; a resposta 429 traz retry-after em segundos.
03Paginação
Listas respondem {"itens": [...], "proximo": "..."}. Para a página seguinte, repita a chamada com cursor igual ao proximo recebido; na última página ele vem null. O cursor é opaco: não monte nem altere. limite vai de 1 a 200 (padrão 50); nas medidas, até 1000 pontos por página.
04Dispositivos
Dispositivos e grupos da empresa.
GET /dispositivos dispositivos.ler
Lista os dispositivos. Em ordem de nome. Uma chave com recorte só vê os dispositivos dos grupos que o grupo de usuários dela lê.
| Nome | Tipo | Descrição |
|---|---|---|
| grupo | id | só os dispositivos deste grupo |
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/dispositivos \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"endereco": "texto",
"tipo": "servidor",
"grupo": {
"id": "4821",
"nome": "Core 2960X"
},
"ativo": false,
"estado": "ok",
"em_manutencao": false,
"evento_aberto": {
"id": "4821",
"estado_pior": "texto",
"inicio": "2026-10-01T17:37:55.000Z"
}
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
POST /dispositivos dispositivos.criar
Cria um dispositivo. Uma chave com recorte precisa escolher um grupo gravável. Este primeiro corte não configura SNMP, sonda remota nem VPN.
| Nome | Tipo | Descrição |
|---|---|---|
| nome * | texto | até 120 caracteres |
| endereco | texto | |
| grupo_id | id | |
| tipo | texto | servidor, rede, servico, outro |
| intervalo_padrao_s | inteiro | 30 a 86400 |
| ativo | sim ou não | |
| latitude | número | -90 a 90 |
| longitude | número | -180 a 180 |
Exemplo:
curl -X POST https://app.evobits.com.br/api/v1/dispositivos \
-H "Authorization: Bearer evk_..." \
-H "Content-Type: application/json" \
-d '{"nome":"Core 2960X","endereco":"texto","grupo_id":"0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f","tipo":"servidor","intervalo_padrao_s":60,"ativo":false,"latitude":99.97,"longitude":99.97}'
Resposta 201:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"grupo_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"sensores_criados": 60
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /dispositivos/{id} dispositivos.ler
Detalhe de um dispositivo. Com os sensores, a disponibilidade do sensor ping por janela e a manutenção vigente.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | id |
Exemplo:
curl https://app.evobits.com.br/api/v1/dispositivos/0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"endereco": "texto",
"tipo": "servidor",
"grupo": {
"id": "4821",
"nome": "Core 2960X"
},
"ativo": false,
"estado": "ok",
"em_manutencao": false,
"evento_aberto": {
"id": "4821",
"estado_pior": "texto",
"inicio": "2026-10-01T17:37:55.000Z"
},
"manutencao_vigente": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"inicio": "2026-10-01T17:37:55.000Z",
"fim": "2026-10-01T17:37:55.000Z",
"motivo": "texto"
},
"pai": {
"id": "4821",
"nome": "Core 2960X"
},
"intervalo_padrao_s": 60,
"uptime_s": 99.97,
"ultima_coleta_em": null,
"disponibilidade": {
"24h": 99.97,
"7d": 99.97,
"30d": 99.97,
"1a": 99.97
},
"sensores": [
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"tipo": "texto",
"chave": "texto",
"ativo": false,
"intervalo_s": 60,
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"estado": "ok",
"valor": 99.97,
"valor2": 99.97,
"unidade": "texto",
"desde": null,
"coletado_em": null
}
]
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /grupos dispositivos.ler
Lista os grupos de dispositivos. A árvore vem pelo pai_id. Com recorte, os grupos lidos e os ancestrais deles (só o nome).
| Nome | Tipo | Descrição |
|---|---|---|
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/grupos \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"pai_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f"
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
POST /grupos dispositivos.criar
Cria um grupo de dispositivos. Uma chave com recorte precisa criar o grupo dentro de um grupo pai que possa gravar. Sem recorte, pai_id nulo cria um grupo raiz.
| Nome | Tipo | Descrição |
|---|---|---|
| nome * | texto | até 80 caracteres |
| pai_id | id | |
| ordem | inteiro |
Exemplo:
curl -X POST https://app.evobits.com.br/api/v1/grupos \
-H "Authorization: Bearer evk_..." \
-H "Content-Type: application/json" \
-d '{"nome":"Core 2960X","pai_id":"0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f","ordem":60}'
Resposta 201:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"pai_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f"
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 409 o alerta já está fechado
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
05Sensores e medidas
Sensores, estado atual e séries de medidas.
GET /sensores sensores.ler
Lista os sensores com o estado atual. Em ordem de dispositivo e nome. Sem a configuração do sensor (que pode ter credenciais).
| Nome | Tipo | Descrição |
|---|---|---|
| dispositivo | id | só os sensores deste dispositivo |
| tipo | texto | tipo do sensor (ex.: ping, snmp_porta); até 40 caracteres |
| estado | texto | ok, atencao, ruim, sem_dado, pausado |
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/sensores \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"tipo": "texto",
"chave": "texto",
"ativo": false,
"intervalo_s": 60,
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"estado": "ok",
"valor": 99.97,
"valor2": 99.97,
"unidade": "texto",
"desde": null,
"coletado_em": null
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /sensores/{id} sensores.ler
Detalhe de um sensor. Escopo exigido: sensores.ler.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | id |
Exemplo:
curl https://app.evobits.com.br/api/v1/sensores/0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X",
"tipo": "texto",
"chave": "texto",
"ativo": false,
"intervalo_s": 60,
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"estado": "ok",
"valor": 99.97,
"valor2": 99.97,
"unidade": "texto",
"desde": null,
"coletado_em": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /estado sensores.ler
Resumo do estado atual. Quantos dispositivos e sensores estão em cada estado agora.
Exemplo:
curl https://app.evobits.com.br/api/v1/estado \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"dispositivos": {
"total": 60,
"ok": 60,
"atencao": 60,
"ruim": 60,
"sem_dado": 60
},
"sensores": {
"total": 60,
"ok": 60,
"atencao": 60,
"ruim": 60,
"sem_dado": 60,
"pausado": 60
},
"gerado_em": "2026-10-01T17:37:55.000Z"
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /sensores/{id}/medidas medidas.ler
Medidas de um sensor num período. bruto traz cada leitura (guardadas por 7 dias); 5m, 1h e 1d trazem média, mínimo e máximo do balde. Sem de e ate, as últimas 24 horas. O histórico respeita o limite do plano. Até 1000 pontos por página.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | id |
| Nome | Tipo | Descrição |
|---|---|---|
| de | data | início, ISO 8601 |
| ate | data | fim (exclusivo), ISO 8601 |
| agregacao | texto | bruto, 5m, 1h, 1d; padrão 5m |
| limite | inteiro | 1 a 1000; padrão 500 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/sensores/0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f/medidas \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"sensor_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"agregacao": "bruto",
"de": "2026-10-01T17:37:55.000Z",
"ate": "2026-10-01T17:37:55.000Z",
"unidade": "texto",
"itens": [
{
"tempo": "2026-10-01T17:37:55.000Z",
"valor": 99.97,
"valor2": 99.97,
"min": 99.97,
"max": 99.97,
"min2": 99.97,
"max2": 99.97
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
06Eventos
Mudanças de estado dos dispositivos e dos itens da página de status.
GET /eventos eventos.ler
Lista os eventos (mudanças de estado). Mais recentes primeiro. desde e ate filtram por sobreposição: um evento ainda aberto aparece.
| Nome | Tipo | Descrição |
|---|---|---|
| desde | data | |
| ate | data | |
| dispositivo | id | |
| estado | texto | atencao, ruim |
| em_curso | sim ou não | false exclui os ainda abertos |
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/eventos \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "4821",
"dispositivo": {
"id": "4821",
"nome": "Core 2960X"
},
"item": {
"id": "4821",
"nome": "Core 2960X"
},
"inicio": "2026-10-01T17:37:55.000Z",
"fim": null,
"duracao_s": 60,
"estado_pior": "atencao",
"origem": "texto",
"em_curso": false,
"sensores_gatilho": [
"texto"
]
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /eventos/{id} eventos.ler
Detalhe de um evento. Escopo exigido: eventos.ler.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | texto |
Exemplo:
curl https://app.evobits.com.br/api/v1/eventos/4821 \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"id": "4821",
"dispositivo": {
"id": "4821",
"nome": "Core 2960X"
},
"item": {
"id": "4821",
"nome": "Core 2960X"
},
"inicio": "2026-10-01T17:37:55.000Z",
"fim": null,
"duracao_s": 60,
"estado_pior": "atencao",
"origem": "texto",
"em_curso": false,
"sensores_gatilho": [
"texto"
],
"estado_anterior": "texto",
"gatilho": [
{
"sensor_id": "texto",
"nome": "Core 2960X",
"tipo": "texto",
"estado": "texto",
"valor": 99.97,
"unidade": "texto"
}
]
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
07Alertas
Alertas abertos pelas regras da empresa.
GET /alertas alertas.ler
Lista os alertas. Ativos: o mais grave e mais antigo primeiro. Resolvidos e todos: o mais recente primeiro.
| Nome | Tipo | Descrição |
|---|---|---|
| estado | texto | ativo, resolvido, todos; padrão ativo |
| desde | data | abertos a partir de |
| dispositivo | id | |
| severidade | texto | atencao, ruim |
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/alertas \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "4821",
"severidade": "atencao",
"estado": "aberto",
"mensagem": "texto",
"regra": {
"id": "4821",
"nome": "Core 2960X"
},
"dispositivo": {
"id": "4821",
"nome": "Core 2960X"
},
"sensor": {
"id": "4821",
"nome": "Core 2960X"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido": false,
"reconhecido_em": null,
"reconhecido_origem": "painel",
"silenciado_ate": null,
"fechado_em": null,
"fechamento": "texto",
"duracao_s": 60
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /alertas/{id} alertas.ler
Detalhe de um alerta. Escopo exigido: alertas.ler.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | texto |
Exemplo:
curl https://app.evobits.com.br/api/v1/alertas/4821 \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"id": "4821",
"severidade": "atencao",
"estado": "aberto",
"mensagem": "texto",
"regra": {
"id": "4821",
"nome": "Core 2960X"
},
"dispositivo": {
"id": "4821",
"nome": "Core 2960X"
},
"sensor": {
"id": "4821",
"nome": "Core 2960X"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido": false,
"reconhecido_em": null,
"reconhecido_origem": "painel",
"silenciado_ate": null,
"fechado_em": null,
"fechamento": "texto",
"duracao_s": 60
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
POST /alertas/{id}/reconhecer alertas.operar
Reconhece um alerta. Para o escalonamento do alerta. Idempotente: reconhecer de novo devolve o mesmo alerta. Fica na Auditoria da empresa como feito pela chave. Uma chave com recorte só reconhece alerta de dispositivo em grupo com acesso de escrita.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | texto |
| Nome | Tipo | Descrição |
|---|---|---|
| comentario | texto | até 500 caracteres |
Exemplo:
curl -X POST https://app.evobits.com.br/api/v1/alertas/4821/reconhecer \
-H "Authorization: Bearer evk_..." \
-H "Content-Type: application/json" \
-d '{"comentario":"texto"}'
Resposta 200:
{
"id": "4821",
"severidade": "atencao",
"estado": "aberto",
"mensagem": "texto",
"regra": {
"id": "4821",
"nome": "Core 2960X"
},
"dispositivo": {
"id": "4821",
"nome": "Core 2960X"
},
"sensor": {
"id": "4821",
"nome": "Core 2960X"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido": false,
"reconhecido_em": null,
"reconhecido_origem": "painel",
"silenciado_ate": null,
"fechado_em": null,
"fechamento": "texto",
"duracao_s": 60
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 409 o alerta já está fechado
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
08Manutenções
Janelas de manutenção planejada.
GET /manutencoes manutencoes.ler
Lista as janelas de manutenção. Mais recentes primeiro (pelo início). vigentes=true só as que valem agora; futuras=true as vigentes e as que ainda vão começar.
| Nome | Tipo | Descrição |
|---|---|---|
| escopo_tipo | texto | grupo, dispositivo, sensor, item |
| escopo_id | id | |
| vigentes | sim ou não | |
| futuras | sim ou não | |
| limite | inteiro | itens por página (1 a 200); padrão 50 |
| cursor | texto | o proximo da página anterior; até 512 caracteres |
Exemplo:
curl https://app.evobits.com.br/api/v1/manutencoes \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"itens": [
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_tipo": "grupo",
"escopo_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_nome": "texto",
"inicio": "2026-10-01T17:37:55.000Z",
"fim": "2026-10-01T17:37:55.000Z",
"motivo": "texto",
"vigente": false,
"criado_em": "2026-10-01T17:37:55.000Z"
}
],
"proximo": null
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
POST /manutencoes manutencoes.escrever
Agenda uma janela de manutenção. Durante a janela, o alvo continua medido mas não abre evento nem alerta. Uma chave com recorte só agenda em alvo de grupo com acesso de escrita.
| Nome | Tipo | Descrição |
|---|---|---|
| escopo_tipo * | texto | grupo, dispositivo, sensor, item |
| escopo_id * | id | |
| inicio * | data | |
| fim * | data | |
| motivo | texto |
Exemplo:
curl -X POST https://app.evobits.com.br/api/v1/manutencoes \
-H "Authorization: Bearer evk_..." \
-H "Content-Type: application/json" \
-d '{"escopo_tipo":"grupo","escopo_id":"0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f","inicio":"2026-10-01T17:37:55.000Z","fim":"2026-10-01T17:37:55.000Z","motivo":"texto"}'
Resposta 201:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_tipo": "grupo",
"escopo_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_nome": "texto",
"inicio": "2026-10-01T17:37:55.000Z",
"fim": "2026-10-01T17:37:55.000Z",
"motivo": "texto",
"vigente": false,
"criado_em": "2026-10-01T17:37:55.000Z"
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
PATCH /manutencoes/{id} manutencoes.escrever
Altera início, fim ou motivo de uma janela. O alvo não muda: para outro alvo, apague e crie de novo.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | id |
| Nome | Tipo | Descrição |
|---|---|---|
| inicio | data | |
| fim | data | |
| motivo | texto |
Exemplo:
curl -X PATCH https://app.evobits.com.br/api/v1/manutencoes/0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f \
-H "Authorization: Bearer evk_..." \
-H "Content-Type: application/json" \
-d '{"inicio":"2026-10-01T17:37:55.000Z","fim":"2026-10-01T17:37:55.000Z","motivo":"texto"}'
Resposta 200:
{
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_tipo": "grupo",
"escopo_id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"escopo_nome": "texto",
"inicio": "2026-10-01T17:37:55.000Z",
"fim": "2026-10-01T17:37:55.000Z",
"motivo": "texto",
"vigente": false,
"criado_em": "2026-10-01T17:37:55.000Z"
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
DELETE /manutencoes/{id} manutencoes.escrever
Apaga uma janela de manutenção. Escopo exigido: manutencoes.escrever.
| Nome | Tipo | Descrição |
|---|---|---|
| id * | id |
Exemplo:
curl -X DELETE https://app.evobits.com.br/api/v1/manutencoes/0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f \
-H "Authorization: Bearer evk_..."
Resposta 204, sem corpo.
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
09Disponibilidade
Disponibilidade por período, na mesma conta dos relatórios do painel.
GET /disponibilidade relatorios.ler
Disponibilidade de um escopo num período. A mesma conta dos relatórios do painel: tempo em ok ou atenção do sensor de referência (o primeiro ping ativo do dispositivo) sobre o tempo considerado. Manutenção sempre sai da conta; o tempo sem dado fica fora do denominador e aparece como cobertura (ou conta como fora com sem_dado_conta_fora=true); antes do primeiro histórico do sensor não conta. Grupo e empresa são a média ponderada pelo tempo dos dispositivos ativos da subárvore. Período por mes (AAAA-MM) ou por de e ate (dias, até 400 dias), no fuso America/Fortaleza, dentro do histórico do plano.
| Nome | Tipo | Descrição |
|---|---|---|
| escopo | texto | empresa, grupo, dispositivo, sensor; padrão empresa |
| id | id | grupo, dispositivo ou sensor (obrigatório fora de empresa) |
| mes | texto | AAAA-MM |
| de | texto | primeiro dia (AAAA-MM-DD) |
| ate | texto | último dia, inclusive (AAAA-MM-DD) |
| sem_dado_conta_fora | sim ou não | padrão false |
Exemplo:
curl https://app.evobits.com.br/api/v1/disponibilidade \
-H "Authorization: Bearer evk_..."
Resposta 200:
{
"escopo": {
"tipo": "empresa",
"id": "4821",
"nome": "Core 2960X"
},
"periodo": {
"inicio": "2026-10-01T17:37:55.000Z",
"fim": "2026-10-01T17:37:55.000Z",
"inicio_efetivo": "2026-10-01T17:37:55.000Z",
"fim_efetivo": "2026-10-01T17:37:55.000Z",
"parcial": false,
"fuso": "texto"
},
"sem_dado_conta_fora": false,
"agregado": {
"disponibilidade_pct": 99.97,
"cobertura_pct": 99.97,
"considerado_s": 60,
"ok_s": 60,
"fora_s": 60,
"sem_dado_s": 60,
"manutencao_s": 60,
"dispositivos": 60,
"dispositivos_na_conta": 60,
"quedas": 60
},
"itens": [
{
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "4821",
"nome": "Core 2960X"
},
"sem_referencia": false,
"sem_historico": false,
"disponibilidade_pct": 99.97,
"cobertura_pct": 99.97,
"considerado_s": 60,
"ok_s": 60,
"fora_s": 60,
"sem_dado_s": 60,
"manutencao_s": 60,
"quedas": 60
}
],
"dias": [
{
"dia": "texto",
"disponibilidade_pct": 99.97,
"considerado_s": 60,
"fora_s": 60,
"sem_dado_s": 60,
"manutencao_s": 60
}
]
}
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
10Exportação
Medidas e eventos em CSV, por escopo e período.
GET /medidas.csv medidas.ler
Exporta medidas em CSV. Medidas de um sensor, de um dispositivo, de um grupo ou da empresa inteira (sem sensor, dispositivo nem grupo), no período e na agregação pedidos. Uma linha por canal: horario (ISO 8601 no fuso), dispositivo, grupo, sensor, tipo, canal, unidade, minimo, media, maximo (mínimo e máximo ficam vazios em bruto). Sem de e ate, as últimas 24 horas; ate é exclusivo. Até 200 mil linhas, em streaming; acima disso a resposta é 422 muitas_linhas: reduza o período, o escopo, ou use uma agregação maior. O histórico respeita o limite do plano e o recorte da chave; bruto existe só dos últimos 7 dias. Em 1d, o dia é o do fuso pedido (UTC sem ele).
| Nome | Tipo | Descrição |
|---|---|---|
| sensor | id | só as medidas deste sensor |
| dispositivo | id | só os sensores deste dispositivo |
| grupo | id | só os dispositivos deste grupo e dos subgrupos |
| de | data | início, ISO 8601 |
| ate | data | fim (exclusivo), ISO 8601 |
| agregacao | texto | bruto, 5m, 1h, 1d; padrão 5m |
| fuso | texto | nome IANA do fuso dos horários do arquivo (ex.: America/Fortaleza); padrão UTC; até 100 caracteres |
Exemplo:
curl "https://app.evobits.com.br/api/v1/medidas.csv?agregacao=1h&fuso=America/Fortaleza" \
-H "Authorization: Bearer evk_..."
Resposta 200, em texto (text/csv):
horario,dispositivo,grupo,sensor,tipo,canal,unidade,minimo,media,maximo
2026-10-01T14:35:00-03:00,Core 2960X,Matriz,Te1/0/1,snmp_porta,Entrada,bps,38100000,41800000,45900000
2026-10-01T14:35:00-03:00,Core 2960X,Matriz,Te1/0/1,snmp_porta,Saída,bps,9800000,12400000,15100000
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 422 o recorte passa de 200 mil linhas: reduza o período ou o escopo
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
GET /eventos.csv eventos.ler
Exporta eventos em CSV. Eventos (mudanças de estado) de um dispositivo, de um grupo, que citam um sensor, ou da empresa inteira, que se sobrepõem ao período. Colunas: inicio, fim (vazio se em curso), duracao_s, dispositivo, grupo, item, estado, origem, em_curso, sensores; horários no fuso. Sem de e ate, as últimas 24 horas. Até 200 mil linhas; acima disso, 422 muitas_linhas.
| Nome | Tipo | Descrição |
|---|---|---|
| sensor | id | só os eventos cujo gatilho cita este sensor |
| dispositivo | id | só os sensores deste dispositivo |
| grupo | id | só os dispositivos deste grupo e dos subgrupos |
| de | data | início, ISO 8601 |
| ate | data | fim (exclusivo), ISO 8601 |
| fuso | texto | nome IANA do fuso dos horários do arquivo (ex.: America/Fortaleza); padrão UTC; até 100 caracteres |
Exemplo:
curl "https://app.evobits.com.br/api/v1/eventos.csv?fuso=America/Fortaleza" \
-H "Authorization: Bearer evk_..."
Resposta 200, em texto (text/csv):
inicio,fim,duracao_s,dispositivo,grupo,item,estado,origem,em_curso,sensores
2026-10-01T14:37:55-03:00,2026-10-01T14:52:10-03:00,855,Core 2960X,Matriz,,ruim,infra,nao,Ping
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 422 o recorte passa de 200 mil linhas: reduza o período ou o escopo
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
11Métricas
Exportador no formato de exposição do Prometheus.
No Prometheus, a chave evk_ com o escopo metricas.ler vai num arquivo e o scrape_config usa autenticação Bearer:
scrape_configs:
- job_name: evobits
scheme: https
metrics_path: /api/v1/metrics
scrape_interval: 60s
authorization:
type: Bearer
credentials_file: /etc/prometheus/evobits.key
static_configs:
- targets: [app.evobits.com.br]
GET /metrics metricas.ler
Métricas no formato do Prometheus. O estado atual da empresa no formato de exposição do Prometheus (text/plain; version=0.0.4), para o scrape_config com authorization do tipo Bearer. Séries: evobits_sensor_valor, evobits_sensor_valor2, evobits_sensor_estado (0 ok, 1 atenção, 2 ruim, 3 sem dado), evobits_sensor_coletado_timestamp_seconds, evobits_dispositivo_estado e evobits_alertas_abertos, com os rótulos dispositivo, grupo, sensor, tipo e unidade. Nunca sai endereço, IP nem configuração. Uma chave com recorte exporta só os dispositivos do recorte. Raspar a cada 60 s basta.
Exemplo:
curl https://app.evobits.com.br/api/v1/metrics \
-H "Authorization: Bearer evk_..."
Resposta 200, em texto (text/plain):
# HELP evobits_sensor_valor Último valor lido do sensor, na unidade do rótulo "unidade".
# TYPE evobits_sensor_valor gauge
evobits_sensor_valor{dispositivo="Core 2960X",grupo="Matriz",sensor="Te1/0/1",tipo="snmp_porta",unidade="bps"} 41800000
# HELP evobits_sensor_estado Estado do sensor: 0 ok, 1 atenção, 2 ruim, 3 sem dado.
# TYPE evobits_sensor_estado gauge
evobits_sensor_estado{dispositivo="Core 2960X",grupo="Matriz",sensor="Te1/0/1",tipo="snmp_porta",unidade="bps"} 0
# HELP evobits_dispositivo_estado Pior estado entre os sensores ativos do dispositivo: 0 ok, 1 atenção, 2 ruim, 3 sem dado.
# TYPE evobits_dispositivo_estado gauge
evobits_dispositivo_estado{dispositivo="Core 2960X",grupo="Matriz"} 0
# HELP evobits_alertas_abertos Alertas abertos (não fechados) por severidade.
# TYPE evobits_alertas_abertos gauge
evobits_alertas_abertos{severidade="atencao"} 0
evobits_alertas_abertos{severidade="ruim"} 1
- 400 parâmetro inválido (o corpo diz qual)
- 401 chave ausente, inválida, revogada ou vencida
- 402
- 403 chave sem o escopo exigido, ou empresa suspensa
- 404 não existe ou está fora do recorte da chave
- 429 passou do limite por minuto da chave; tente de novo depois do Retry-After
12Webhooks de saída
Em Configuração > Integrações > Webhooks, a empresa cadastra uma URL https e os eventos que ela quer receber. A cada evento, o evobits faz um POST JSON assinado para a URL. O corpo traz nomes, estados e ids, nunca endereço, credencial ou configuração de dispositivo.
| Evento | Quando |
|---|---|
| alerta.aberto | uma regra abriu um alerta |
| alerta.reconhecido | alguém reconheceu (pelo painel, e-mail ou API) |
| alerta.resolvido | o problema acabou |
| dispositivo.fora | o sensor de referência caiu |
| dispositivo.voltou | o sensor de referência voltou |
| sensor.estado | qualquer sensor mudou de estado (pode ser muita coisa) |
| manutencao.iniciada | uma janela de manutenção começou |
| manutencao.encerrada | a janela terminou |
| relatorio.pronto | um relatório ou exportação ficou pronto, com o link de 7 dias |
Todo corpo tem o mesmo envelope; dados muda por evento:
{
"id": "9b1e6f3c-5a2d-4c8e-b7f1-3d2a1c0e9f8b",
"evento": "alerta.aberto",
"criado_em": "2026-10-01T17:37:56.000Z",
"empresa": {
"id": "2c4e6a8b-0d1f-4a3b-8c5d-7e9f1a2b3c4d",
"nome": "Sua empresa"
},
"dados": {
"alerta": {
"id": "4821",
"severidade": "ruim",
"mensagem": "Ping de Core 2960X está ruim há 3 min",
"regra": {
"id": "7b0c1d52-3f1e-4c7a-9a40-2f0f6f3b8e11",
"nome": "Dispositivo fora"
},
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido_em": null,
"reconhecido_origem": null,
"fechado_em": null,
"fechamento": null
}
}
}
Cabeçalhos: X-Evobits-Evento (o evento), X-Evobits-Entrega (id da entrega, igual em todas as tentativas dela: use para não processar duas vezes), X-Evobits-Timestamp (segundos) e X-Evobits-Assinatura (sha256= seguido do HMAC-SHA256, em hexadecimal, de timestamp.corpo com o segredo do webhook). O id do envelope é o do evento: um Reenviar pelo painel repete o mesmo id numa entrega nova.
// Node: confere a assinatura sobre o corpo BRUTO, em tempo constante
const { createHmac, timingSafeEqual } = require('node:crypto');
function assinaturaValida(segredo, timestamp, corpoBruto, cabecalho) {
const esperado = 'sha256=' + createHmac('sha256', segredo).update(timestamp + '.' + corpoBruto).digest('hex');
const a = Buffer.from(esperado), b = Buffer.from(cabecalho || '');
return a.length === b.length && timingSafeEqual(a, b) && Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
}
Responda 2xx em até 10 segundos (redirecionamento não é seguido). Sem 2xx, a entrega é tentada de novo 1 min, 5 min, 15 min e 40 min depois da primeira, 5 tentativas no total. Depois de 20 entregas seguidas sem sucesso, o webhook é desligado e os administradores recebem um aviso no painel; "Religar" volta a entregar. O histórico de entregas fica 7 dias.
O dados de cada evento:
alerta.aberto
{
"alerta": {
"id": "4821",
"severidade": "ruim",
"mensagem": "Ping de Core 2960X está ruim há 3 min",
"regra": {
"id": "7b0c1d52-3f1e-4c7a-9a40-2f0f6f3b8e11",
"nome": "Dispositivo fora"
},
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido_em": null,
"reconhecido_origem": null,
"fechado_em": null,
"fechamento": null
}
}
alerta.reconhecido
{
"alerta": {
"id": "4821",
"severidade": "ruim",
"mensagem": "Ping de Core 2960X está ruim há 3 min",
"regra": {
"id": "7b0c1d52-3f1e-4c7a-9a40-2f0f6f3b8e11",
"nome": "Dispositivo fora"
},
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido_em": "2026-10-01T17:41:02.000Z",
"reconhecido_origem": "api",
"fechado_em": null,
"fechamento": null
}
}
alerta.resolvido
{
"alerta": {
"id": "4821",
"severidade": "ruim",
"mensagem": "Ping de Core 2960X está ruim há 3 min",
"regra": {
"id": "7b0c1d52-3f1e-4c7a-9a40-2f0f6f3b8e11",
"nome": "Dispositivo fora"
},
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping"
},
"aberto_em": "2026-10-01T17:37:55.000Z",
"reconhecido_em": "2026-10-01T17:41:02.000Z",
"reconhecido_origem": "painel",
"fechado_em": "2026-10-01T17:44:47.000Z",
"fechamento": "resolvido"
}
}
dispositivo.fora
{
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping",
"tipo": "ping"
},
"estado": "ruim",
"estado_anterior": "ok",
"em_manutencao": false
}
dispositivo.voltou
{
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping",
"tipo": "ping"
},
"estado": "ok",
"estado_anterior": "ruim",
"em_manutencao": false
}
sensor.estado
{
"dispositivo": {
"id": "0f5e2a7c-91d4-4f0b-8b6e-6a1d2c3b4e5f",
"nome": "Core 2960X"
},
"sensor": {
"id": "5d1c9e0a-2b7f-4e3a-a1c8-9f0e7d6c5b4a",
"nome": "Ping",
"tipo": "ping"
},
"estado": "atencao",
"estado_anterior": "ok",
"valor": 182.4,
"unidade": "ms",
"em_manutencao": false
}
manutencao.iniciada
{
"manutencao": {
"id": "3a9b8c7d-6e5f-4a3b-9c2d-1e0f9a8b7c6d",
"escopo_tipo": "grupo",
"escopo_id": "8e7d6c5b-4a39-4281-9f0e-1d2c3b4a5968",
"escopo_nome": "Núcleo",
"inicio": "2026-10-02T03:00:00.000Z",
"fim": "2026-10-02T05:00:00.000Z",
"motivo": "Troca de firmware"
}
}
manutencao.encerrada
{
"manutencao": {
"id": "3a9b8c7d-6e5f-4a3b-9c2d-1e0f9a8b7c6d",
"escopo_tipo": "grupo",
"escopo_id": "8e7d6c5b-4a39-4281-9f0e-1d2c3b4a5968",
"escopo_nome": "Núcleo",
"inicio": "2026-10-02T03:00:00.000Z",
"fim": "2026-10-02T05:00:00.000Z",
"motivo": "Troca de firmware"
}
}
relatorio.pronto
{
"relatorio": {
"id": "6c5b4a39-2817-4f6e-8d5c-4b3a29180716",
"tipo": "sla",
"formato": "pdf",
"nome_arquivo": "SLA setembro.pdf",
"link": "https://app.evobits.com.br/api/relatorios/arquivo/...",
"expira_em": "2026-10-08T12:00:00.000Z"
}
}