eumonitoro API v1.0.0
Índice

API EuMonitoro

Os mesmos dados que você vê na plataforma, disponíveis para o seu BI, ERP ou portal.

Baixar a especificação OpenAPI 3.1 — para gerar SDK ou importar no Postman.

Início rápido

Do zero ao primeiro dado em três passos.

1. Crie um token

No painel, abra Integrações e API e clique em Novo Token. O segredo aparece uma única vez — copie na hora.

2. Faça a primeira chamada

curl -H "Authorization: Bearer SEU_TOKEN" \
     https://eumonitoro.eco.br/api/v1/projetos

3. Puxe as coletas de um projeto

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/coletas?limite=50"

Autenticação

Envie o token no cabeçalho Authorization. Ele pertence à organização, não a uma pessoa — continua funcionando quando alguém sai da empresa.

Authorization: Bearer 12|aBcDeF...
Rotação sem parada. Ao rotacionar um token no painel, o anterior continua válido por 30 dias. Troque no seu sistema com calma, sem janela de manutenção.

Permissões

Cada token carrega apenas as permissões que você marcar:

PermissãoDá acesso aPlano mínimo
projetos.read Listar e detalhar projetos, ver cotas Integração
coletas.read Coletas, cobertura, espécies e observações Integração
coletas.write Incluir/excluir coletas dos cálculos, reprocessar, sincronizar Automação
Toda escrita fica registrada. Quem alterou, o que mudou, de qual token e a partir de qual IP — visível para o gestor no painel. Alterar o que entra nos indicadores muda o número que vai para o órgão ambiental, então a trilha é permanente e não pode ser apagada.

Como o dado nasce

Entender o caminho evita integrar errado. Uma coleta é um formulário preenchido em campo por um técnico:

  1. O coletor preenche o formulário no celular, offline se preciso.
  2. Ao sincronizar, a coleta chega ao EuMonitoro como JSON bruto.
  3. Um processador específico da normativa (SMA 32, INEA, CONAMA 392…) extrai cobertura, espécies e medições.
  4. As espécies passam por enriquecimento taxonômico: nome científico, família, grupo funcional e síndrome de dispersão.
  5. A coleta fica processado e passa a alimentar os indicadores.

Vocabulário

TermoO que é
Normativa A regra ambiental que define o que medir e como. Determina o formato do formulário e o cálculo dos indicadores.
Parcela A unidade amostral em campo — um trecho delimitado da área monitorada.
Cota Coletas contratadas para um projeto. Acima dela, a coleta entra como retido e não é processada até haver alocação.
Coleta ativa O gestor pode excluir uma coleta dos cálculos sem apagá-la. Só as ativas entram nos indicadores.
Segmento Trecho da linha de amostragem classificado como nativa, clareira ou exótica. Medido em metros lineares.

Envelope estável

Cada normativa produz campos diferentes. Para você não escrever um if por normativa, a resposta tem sempre as mesmas chaves e os mesmos tipos:

Só dados_normativa pode mudar sem aviso. É o espaço deliberado para evolução: o restante do envelope é contrato versionado.

Dado pessoal

Um único campo do envelope contém dado pessoal: coletor.rotulo, o nome do técnico que fez a coleta. Ele permanece porque é conteúdo obrigatório do relatório entregue ao órgão ambiental — omiti-lo inviabilizaria o uso principal da API.

Ao levar esse dado para o seu sistema, você passa a tratá-lo: aplique a mesma proteção que aplicaria a qualquer cadastro de pessoa. Nenhum outro identificador pessoal é exposto — em particular, o identificador interno do coletor no ODK Central não sai na API, justamente para não permitir correlacionar a mesma pessoa entre sistemas.

Paginação

Usamos cursor, não offset: sob escrita concorrente, offset repete e pula registros.

{
  "data": [ ... ],
  "proxima_pagina": "eyJpZCI6MTMzNH0",
  "tem_mais": true
}

Enquanto tem_mais for true, repita passando ?cursor=:

import requests

url = "https://eumonitoro.eco.br/api/v1/projetos/12/coletas"
headers = {"Authorization": "Bearer SEU_TOKEN"}
cursor, todas = None, []

while True:
    params = {"limite": 100}
    if cursor:
        params["cursor"] = cursor
    r = requests.get(url, headers=headers, params=params).json()
    todas += r["data"]
    if not r["tem_mais"]:
        break
    cursor = r["proxima_pagina"]

Referência

Projetos

Projetos de monitoramento e suas cotas de coleta.

GET /projetos projetos.read

Lista os projetos da organização

Parâmetros

NomeEmTipoDescrição
status query string Filtra pelo status do projeto.
limite query integer Itens por página. Valores acima do teto são reduzidos ao teto, sem erro.
cursor query string Cursor da próxima página, devolvido em `proxima_pagina`.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos"
GET /projetos/{projeto} projetos.read

Detalha um projeto, com a cota de coletas

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12"

Coletas

Coletas de campo já processadas e normalizadas.

GET /projetos/{projeto}/coletas coletas.read

Lista as coletas de um projeto

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.
status query string Estado da coleta no pipeline de processamento.
ativa query boolean Apenas coletas incluídas (ou excluídas) dos cálculos.
coletado_apos query string Data mínima de coleta (ISO 8601).
coletado_antes query string Data máxima de coleta (ISO 8601).
limite query integer Itens por página. Valores acima do teto são reduzidos ao teto, sem erro.
cursor query string Cursor da próxima página, devolvido em `proxima_pagina`.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/coletas"
GET /coletas/{coleta} coletas.read

Detalha uma coleta

Parâmetros

NomeEmTipoDescrição
coleta * path integer Identificador da coleta.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/coletas/1234"
GET /projetos/{projeto}/cobertura coletas.read

Segmentos de cobertura, um por linha

Achata os segmentos de todas as coletas do projeto. A paginação é por COLETA, não por linha — o cursor permanece estável.

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.
somente_ativas query boolean Considera apenas coletas incluídas nos cálculos.
limite query integer Itens por página. Valores acima do teto são reduzidos ao teto, sem erro.
cursor query string Cursor da próxima página, devolvido em `proxima_pagina`.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/cobertura"
GET /projetos/{projeto}/especies coletas.read

Espécies registradas, uma por linha

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.
somente_ativas query boolean Considera apenas coletas incluídas nos cálculos.
limite query integer Itens por página. Valores acima do teto são reduzidos ao teto, sem erro.
cursor query string Cursor da próxima página, devolvido em `proxima_pagina`.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/especies"
GET /projetos/{projeto}/observacoes coletas.read

Observações de campo, uma por linha

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.
somente_ativas query boolean Considera apenas coletas incluídas nos cálculos.
limite query integer Itens por página. Valores acima do teto são reduzidos ao teto, sem erro.
cursor query string Cursor da próxima página, devolvido em `proxima_pagina`.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/observacoes"

Indicadores

Números consolidados — os mesmos do relatório entregue ao órgão.

GET /projetos/{projeto}/indicadores projetos.read coletas.read

Indicadores consolidados do projeto

Os mesmos números que saem no relatório entregue ao órgão. Considera apenas coletas processadas e marcadas como ativas.

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.

Exemplo

curl -H "Authorization: Bearer SEU_TOKEN" \
     "https://eumonitoro.eco.br/api/v1/projetos/12/indicadores"

Escrita

Alterações de dado. Exigem nível Automação e ficam registradas na trilha de auditoria.

PATCH /projetos/{projeto}/coletas coletas.write

Inclui ou exclui em massa as coletas do projeto

As coletas retidas por cota ficam de fora: não foram processadas e não podem entrar em cálculo algum.

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.

Exemplo

curl -X PATCH "https://eumonitoro.eco.br/api/v1/projetos/12/coletas" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ativa":true}'
PATCH /coletas/{coleta} coletas.write

Inclui ou exclui a coleta dos cálculos

A coleta não é apagada: sai dos indicadores mas continua auditável. Coleta retida por cota não pode ser ativada.

Parâmetros

NomeEmTipoDescrição
coleta * path integer Identificador da coleta.

Exemplo

curl -X PATCH "https://eumonitoro.eco.br/api/v1/coletas/1234" \
  -H "Authorization: Bearer SEU_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"ativa":false}'
POST /coletas/{coleta}/reprocessar coletas.write

Reprocessa a coleta com o processador atual

Útil quando um processador é corrigido. Roda em fila: acompanhe pelo webhook `coleta.reprocessada`.

Parâmetros

NomeEmTipoDescrição
coleta * path integer Identificador da coleta.

Exemplo

curl -X POST "https://eumonitoro.eco.br/api/v1/coletas/1234/reprocessar" \
  -H "Authorization: Bearer SEU_TOKEN"
POST /projetos/{projeto}/sincronizar coletas.write

Dispara sincronização com o ODK Central

Há um bloqueio de 2 minutos por projeto: o ODK Central é infraestrutura compartilhada e não pode ser martelado.

Parâmetros

NomeEmTipoDescrição
projeto * path integer Identificador do projeto.

Exemplo

curl -X POST "https://eumonitoro.eco.br/api/v1/projetos/12/sincronizar" \
  -H "Authorization: Bearer SEU_TOKEN"

Webhooks

Em vez de consultar a API de tempos em tempos esperando dado novo, receba um POST assim que algo acontecer. Cadastre os endpoints em Integrações e API → Webhooks.

O que você recebe

POST https://seu-sistema.com.br/webhooks/eumonitoro
Content-Type: application/json
X-EuMonitoro-Event: coleta.processada
X-EuMonitoro-Delivery: 4821
X-EuMonitoro-Signature: t=1755624000,v1=5f2b...

{
  "id": "9f8e7d6c-...",
  "evento": "coleta.processada",
  "ocorrido_em": "2026-08-19T14:30:00-03:00",
  "dados": { ... a coleta completa, no mesmo formato de GET /coletas/{id} ... }
}

O evento coleta.processada já traz a coleta inteira — você não precisa de uma segunda chamada para saber o que mudou.

Responda 2xx rápido. Consideramos entregue qualquer status entre 200 e 299. Timeout de 10 segundos: enfileire o processamento pesado do seu lado e responda logo, senão marcamos como falha e reenviamos.

Reentrega

Falhou? Tentamos de novo em 1 min, 5 min, 30 min, 2 h e 6 h. Depois de 5 tentativas desistimos daquela entrega — mas você pode reenviá-la manualmente pelo painel, que mostra a resposta exata do seu servidor em cada tentativa.

Após 10 entregas seguidas sem sucesso, o endpoint é pausado automaticamente. Conserte e clique em Reativar.

Deduplique pelo id. Se o seu servidor responder devagar e nós considerarmos timeout, a mesma entrega chega duas vezes — do seu lado, isso é indistinguível de uma falha real. O campo id do envelope é estável entre retentativas.

Validar a assinatura

Toda entrega vem assinada com HMAC-SHA256 usando o segredo mostrado na criação do endpoint. Sempre valide antes de confiar no payload — qualquer um pode enviar um POST para a sua URL.

import hmac, hashlib, time

def valida(corpo_bruto: bytes, cabecalho: str, segredo: str) -> bool:
    partes = dict(p.split("=", 1) for p in cabecalho.split(","))
    timestamp, assinatura = partes["t"], partes["v1"]

    # Rejeita entrega antiga: sem isso, um payload capturado pode ser
    # reenviado contra você indefinidamente.
    if abs(time.time() - int(timestamp)) > 300:
        return False

    esperada = hmac.new(
        segredo.encode(),
        f"{timestamp}.".encode() + corpo_bruto,
        hashlib.sha256,
    ).hexdigest()

    return hmac.compare_digest(esperada, assinatura)

Use o corpo bruto da requisição, não o JSON reserializado: qualquer diferença de espaçamento ou ordem de chaves invalida a assinatura.

Eventos disponíveis

EventoQuando dispara
coleta.recebida Uma coleta chegou do campo e entrou na fila de processamento.
coleta.processada A coleta foi normalizada e já alimenta os indicadores. É o evento mais usado.
coleta.erro O processamento falhou. Contém a mensagem do erro.
coleta.retida_por_cota A coleta chegou mas ficou retida por falta de cota — não entra nos cálculos até haver alocação.
coleta.reprocessada Uma coleta já entregue foi reprocessada; os indicadores podem ter mudado.
cota.esgotada O projeto consumiu toda a cota. O formulário foi fechado no ODK.
projeto.erro_sync A sincronização com o ODK Central falhou.

Antes de ir para produção, use o botão Testar no painel: ele envia uma entrega de exemplo para você validar assinatura e parsing sem depender de uma coleta real chegar do campo.

Catálogo de erros

Todo erro segue o RFC 7807. Trate a falha pelo campo type, que é estável — nunca pelo title, cuja redação pode mudar.

{
  "type": "https://eumonitoro.com/errors/limite-excedido",
  "title": "Limite de requisições excedido",
  "status": 429,
  "detail": "Too Many Attempts.",
  "request_id": "3ddc3a09-f13d-4658-a7c3-1db59e41b497"
}
typeStatusQuando aconteceO que fazer
nao-autenticado 401 Token ausente, inválido, expirado ou revogado. Confira o cabeçalho `Authorization`. Se o token foi revogado, crie outro no painel.
escopo-insuficiente 403 O token não tem a permissão exigida pelo endpoint. Crie um token com as permissões necessárias em Integrações e API.
plano-inativo 403 A organização não tem plano de API contratado. O token está correto — o que falta é o contrato. Fale com o comercial.
nao-encontrado 404 O recurso não existe ou pertence a outra organização. Confira o identificador. Devolvemos 404 também para recurso de outro tenant, de propósito.
payload-invalido 422 Parâmetro fora do formato esperado. Leia o campo `errors`, que aponta exatamente qual parâmetro recusou.
idempotencia-conflito 409 A mesma `Idempotency-Key` foi usada com um corpo diferente. Gere uma chave nova para cada envio distinto. Reutilizar com outro corpo esconderia um bug do seu lado.
limite-excedido 429 A organização passou do teto de requisições por hora. Respeite o `Retry-After`. Se acontece com frequência, considere upgrade de plano.
erro-interno 500 Falha do nosso lado. Reporte ao suporte informando o `request_id` da resposta.

O request_id também vem no cabeçalho X-Request-Id de toda resposta. Guarde-o no seu log: com ele, o suporte localiza exatamente a sua requisição.

Limites e planos

O limite é aplicado por organização, não por token — criar credenciais novas não aumenta a cota.

PlanoRequisiçõesTokens Projetos integradosBanda
Sandbox 60 / hora 1 1 1 GB/mês
Integração 1.000 / hora 5 3 25 GB/mês
Automação 5.000 / hora 20 15 100 GB/mês
Engine 20.000 / hora 50 negociado negociado

Toda resposta traz X-RateLimit-Limit e X-RateLimit-Remaining. Ao estourar, respeite o Retry-After do 429.

Versionamento