Exemplos de uso da API

Receitas prontas em curl, Python e JavaScript para consultar dados públicos, sincronizar a sua base e enviar leituras de ovitrampas e visitas de quarteirões.

/pt-pt/apiVoltar à referência

Primeiros passos

Todas as chamadas partem da mesma base e devolvem JSON. Os endpoints públicos não exigem autenticação; os privados exigem a sua chave de acesso.

Endereço base

/pt-pt/api

O prefixo de idioma faz parte da URL (pt-pt), mas não altera os dados retornados — os registros vêm do banco exatamente como foram cadastrados em campo.

Teste rápido
curl -G -d "municipality=Ponta Pora" --data-urlencode "country=Brasil" \
  /pt-pt/api/lastcountingpublic

Se a resposta for uma lista JSON, a integração já está funcionando.

A chave vai na URL. Em todos os endpoints privados — inclusive nos POST — a key é lida da query string (?key=SUA_CHAVE). Enviá-la apenas no corpo do formulário devolve 404 "Wrong key". Os demais campos continuam indo no corpo da requisição.

Consultar dados públicos

O endpoint /api/lastcountingpublic devolve as últimas contagens de ovos com latitude, longitude, semana e ano epidemiológicos. É o ponto de partida para mapas, painéis e estudos.

GET/api/lastcountingpublicPúblico
curl
curl -G \
  --data-urlencode "municipality=Ponta Pora" \
  --data-urlencode "date_start=2025-01-01" \
  --data-urlencode "date_end=2025-12-31" \
  /pt-pt/api/lastcountingpublic
Python
import requests

BASE = "/pt-pt/api"

resposta = requests.get(
    BASE + "/lastcountingpublic",
    params={
        "municipality": "Ponta Pora",
        "date_start": "2025-01-01",
        "date_end": "2025-12-31",
    },
    timeout=60,
)
resposta.raise_for_status()

for contagem in resposta.json():
    print(contagem["date"], contagem["ovitrap_id"], contagem["eggs"])
JavaScript
const BASE = "/pt-pt/api";

const params = new URLSearchParams({
    state: "MS",
    date_start: "2025-01-01",
});

const resposta = await fetch(BASE + "/lastcountingpublic?" + params);
const contagens = await resposta.json();

console.log(contagens.length, "contagens");

Os mesmos parâmetros de localização (country, state, municipality) valem para os demais endpoints públicos: ovitrampas, quarteirões, EDLs, manutenções de EDLs e pontos estratégicos. Trocar apenas o caminho do endpoint já muda o conjunto de dados.

Sem nenhum parâmetro de localização, o endpoint devolve os dados do Brasil inteiro. Filtrar por município ou estado deixa a resposta muito mais rápida.

Percorrer todas as páginas

Os endpoints paginados aceitam page de 1 a 100. Acima disso a API responde com o texto "Maximum pagination is 100" e status 200 — ou seja, o corpo deixa de ser uma lista. Sempre verifique o tipo antes de iterar.

Python
import requests

BASE = "/pt-pt/api"


def baixar_tudo(endpoint, **filtros):
    """Percorre as paginas ate a API devolver uma pagina vazia."""
    registros = []

    for pagina in range(1, 101):
        resposta = requests.get(
            BASE + endpoint,
            params=dict(filtros, page=pagina),
            timeout=60,
        )
        resposta.raise_for_status()
        dados = resposta.json()

        # limite de paginacao atingido: a API devolve uma string, nao uma lista
        if not isinstance(dados, list):
            print("Aviso:", dados)
            break

        if not dados:
            break

        registros.extend(dados)

    return registros


ovitrampas = baixar_tudo("/getmunicipalityovitrapspublic", municipality="Ponta Pora")
print(len(ovitrampas), "ovitrampas")
Chegou na página 100? Estreite o filtro em vez de tentar a página 101: consulte município por município, ou use date_start e date_end para dividir o período em intervalos menores.

Sincronização incremental

Para manter uma base espelhada, não baixe tudo de novo a cada execução. O endpoint /api/lastcountingpublic aceita id, que devolve apenas as contagens a partir daquele identificador, e também date (data de inclusão) e date_collect (data de coleta).

Python
import json
import os
import requests

BASE = "/pt-pt/api"
ESTADO = "ultimo_id.json"


def ultimo_id_lido():
    if os.path.exists(ESTADO):
        with open(ESTADO) as arquivo:
            return json.load(arquivo)["counting_id"]
    return 0


def sincronizar():
    ultimo = ultimo_id_lido()
    novas = []

    for pagina in range(1, 101):
        resposta = requests.get(
            BASE + "/lastcountingpublic",
            params={"municipality": "Ponta Pora", "id": ultimo, "page": pagina},
            timeout=60,
        )
        resposta.raise_for_status()
        dados = resposta.json()

        if not isinstance(dados, list) or not dados:
            break

        novas.extend(dados)

    if novas:
        maior = max(item["counting_id"] for item in novas)
        with open(ESTADO, "w") as arquivo:
            json.dump({"counting_id": maior}, arquivo)

    return novas


print(len(sincronizar()), "contagens novas")

Guarde sempre o maior counting_id recebido, e não a data da execução: uma contagem lançada em campo hoje pode se referir a uma semana anterior, e o filtro por id não deixa esses registros escaparem.

Exportar para CSV

As contagens públicas já vêm com coordenadas, então dá para gerar uma planilha ou alimentar um mapa sem nenhuma junção adicional.

Python
import csv
import requests

BASE = "/pt-pt/api"

COLUNAS = [
    "counting_id",
    "municipality",
    "state_code",
    "ovitrap_id",
    "latitude",
    "longitude",
    "week",
    "year",
    "eggs",
    "date",
    "date_collect",
]

resposta = requests.get(
    BASE + "/lastcountingpublic",
    params={"state": "MS", "date_start": "2025-01-01"},
    timeout=60,
)
contagens = resposta.json()

with open("contagens.csv", "w", newline="", encoding="utf-8") as arquivo:
    escritor = csv.DictWriter(arquivo, fieldnames=COLUNAS, extrasaction="ignore")
    escritor.writeheader()
    escritor.writerows(contagens)

print("Arquivo contagens.csv gerado com", len(contagens), "linhas")

Enviando dados

Os exemplos a seguir usam a API privada e exigem uma chave. O escopo geográfico da chave define o que ela pode gravar — uma chave municipal só grava no próprio município.

POST/api/postcountingPrivado

Enviar a leitura de uma ovitrampa existente

Envia a contagem de ovos de uma ovitrampa já cadastrada. A ovitrampa é localizada pelo ovitrap_group_id dentro do município da chave, e a semana epidemiológica é calculada a partir do campo date.

curl
curl -X POST \
  -d "ovitrap_group_id=97" \
  -d "ovitrap_lat=-7.000000" \
  -d "ovitrap_lng=-8.000000" \
  -d "date=2025-01-20" \
  -d "counting_observation_id=1" \
  -d "counting_eggs=5" \
  "/pt-pt/api/postcounting?key=SUA_CHAVE"
Python
import requests

BASE = "/pt-pt/api"
CHAVE = "SUA_CHAVE"

resposta = requests.post(
    BASE + "/postcounting",
    params={"key": CHAVE},          # a chave vai na URL
    data={                          # os dados vao no corpo
        "ovitrap_group_id": 97,
        "ovitrap_lat": -7.000000,
        "ovitrap_lng": -8.000000,
        "date": "2025-01-20",
        "counting_observation_id": 1,
        "counting_eggs": 5,
    },
    timeout=60,
)

print(resposta.status_code, resposta.json())
# 200 "Contagem registrada"
Atenção: se as coordenadas enviadas forem diferentes das cadastradas, a ovitrampa é atualizada com a nova posição. Envie sempre a coordenada real do ponto, não a do agente no momento da leitura.
POST/api/postcountingPrivado

Instalar uma ovitrampa nova junto da leitura

Se o ovitrap_group_id ainda não existir no município, a ovitrampa é criada na mesma requisição. Envie também o endereço e, se for o caso, o tipo (ovitrap_type_id: 1 urbana, padrão; 2 rural).

Python
import requests

BASE = "/pt-pt/api"
CHAVE = "SUA_CHAVE"

resposta = requests.post(
    BASE + "/postcounting",
    params={"key": CHAVE},
    data={
        "ovitrap_group_id": 96,
        "ovitrap_address_district": "Centro",
        "ovitrap_address_street": "Rua das Flores",
        "ovitrap_address_number": "123",
        "ovitrap_address_complement": "",
        "ovitrap_address_sector": "Setor 04",
        "ovitrap_responsable": "Maria Souza",
        "ovitrap_block_id": "12",
        "ovitrap_type_id": 2,          # 1 = urbana (padrao), 2 = rural
        "ovitrap_lat": -7.000000,
        "ovitrap_lng": -8.000000,
        "date": "2025-01-20",
        "counting_date_collect": "2025-01-27",
        "counting_observation_id": 1,
        "counting_eggs": 5,
    },
    timeout=60,
)

print(resposta.status_code, resposta.json())
Respostas específicas:
  • 400 — falta ovitrap_lat, ovitrap_lng ou ovitrap_group_id.
  • 400ovitrap_type_id diferente de 1 ou 2.
  • 404 — já existe contagem para essa ovitrampa, ano e semana.
  • 500 — a data enviada cai em uma semana epidemiológica futura ou inválida.
POST/api/postactionPrivado

Registrar uma visita em quarteirão

Use block_id para lançar a visita em um quarteirão já cadastrado. Se o quarteirão ainda não existir, envie block_group_id com os dados do quarteirão e ele é criado automaticamente dentro do município da chave.

Python — quarteirão existente
import requests

BASE = "/pt-pt/api"
CHAVE = "SUA_CHAVE"

visita = {
    "block_id": 97,
    "date": "2025-01-20",

    "block_land_residence": 10,
    "action_land_residence_out": 2,
    "action_land_residence_breedings": 1,
    "action_land_residence_treated": 1,

    "action_deposit_a1_quantity": 4,
    "action_deposit_a1_eliminated": 2,
    "action_deposit_a1_treated": 1,
    "action_deposit_a1_larvicid": 10,

    "action_observation": "Foco encontrado em pneus nos fundos do imovel.",
}

resposta = requests.post(
    BASE + "/postaction", params={"key": CHAVE}, data=visita, timeout=60
)

if resposta.status_code == 409:
    print("Ja existe visita para esse quarteirao nessa semana")
else:
    print(resposta.status_code, resposta.json())
Python — criando o quarteirão
visita = {
    "block_group_id": 97,
    "date": "2025-01-20",
    "block_address_district": "Centro Historico",
    "block_address_sector": "Setor 04 - Norte",
    "block_coordinates": "[[-7.123, -34.845], [-7.124, -34.846]]",
    "block_lat": -7.123456,
    "block_lng": -34.845678,
    "block_responsable": "Joao da Silva",

    "block_land_residence": 10,
    "action_land_residence_out": 2,
    "action_land_residence_breedings": 1,
    "action_land_residence_treated": 1,

    "action_observation": "Area com alta densidade de recipientes descartaveis.",
}

resposta = requests.post(
    BASE + "/postaction", params={"key": CHAVE}, data=visita, timeout=60
)
print(resposta.status_code, resposta.json())

A lista completa de campos de imóveis e de depósitos (a1, a2, b, c, d1, d2, e) está na referência do endpoint. Campos numéricos não enviados assumem zero, mas qualquer valor que não seja um número devolve 400.

Remover registros

As remoções são definitivas e sempre restritas ao município da chave.

curl
# leitura de uma ovitrampa (identificada pela ovitrampa + data)
curl -X POST -d "ovitrap_group_id=97" -d "date=2025-01-20" \
  "/pt-pt/api/postdeletecounting?key=SUA_CHAVE"

# a ovitrampa inteira
curl -X POST -d "ovitrap_group_id=97" \
  "/pt-pt/api/postdeleteovitrap?key=SUA_CHAVE"

# visita de um quarteirao (quarteirao + data)
curl -X POST -d "block_group_id=97" -d "date=2025-01-20" \
  "/pt-pt/api/postdeleteaction?key=SUA_CHAVE"

# o quarteirao inteiro
curl -X POST -d "block_group_id=97" \
  "/pt-pt/api/postdeleteblock?key=SUA_CHAVE"
Para corrigir uma contagem lançada com o valor errado, remova a leitura com /api/postdeletecounting e envie-a novamente com /api/postcounting — reenviar por cima devolve erro de duplicidade.

Tratamento de erros

O corpo da resposta é sempre uma string JSON com a mensagem. Vale tratar caso a caso, porque nem todo erro merece nova tentativa:

SituaçãoCódigoO que fazer
"Wrong key"404Confira se a chave está na query string e não no corpo.
Contagem duplicada404Já existe leitura para a ovitrampa nessa semana; remova antes de reenviar.
Visita duplicada409Já existe visita para o quarteirão nessa semana.
Fora do escopo403O quarteirão não pertence ao município da chave. Não repita.
Campo obrigatório ausente400Corrija o envio; repetir devolve o mesmo erro.
Semana ou ano inválidos500A data cai fora da semana epidemiológica aceita. Corrija o campo date.
Python
import time
import requests

NAO_REPETIR = {400, 403, 404, 409}


def enviar(url, chave, dados, tentativas=3):
    for tentativa in range(tentativas):
        try:
            resposta = requests.post(
                url, params={"key": chave}, data=dados, timeout=60
            )
        except requests.RequestException as erro:
            print("Falha de rede:", erro)
            time.sleep(5 * (tentativa + 1))
            continue

        if resposta.status_code in NAO_REPETIR:
            print("Erro definitivo:", resposta.status_code, resposta.json())
            return None

        if resposta.ok:
            return resposta.json()

        # 500 e demais erros de servidor: espera progressiva e tenta de novo
        time.sleep(5 * (tentativa + 1))

    return None

Boas práticas

  • Filtre por município ou estado sempre que possível — sem filtro a consulta varre o país inteiro.
  • Prefira sincronização incremental por id a rebaixar toda a base todos os dias.
  • Envie as requisições em série. A API não é feita para dezenas de chamadas simultâneas por cliente.
  • Verifique se a resposta é uma lista antes de iterar: as mensagens de limite de paginação vêm com status 200.
  • Guarde o counting_id e o block_id recebidos — são eles que permitem casar os registros do Conta Ovos com os do seu sistema.
  • Trate a semana epidemiológica como o campo determinante: o Conta Ovos aceita apenas uma leitura por ovitrampa por semana, e uma visita por quarteirão por semana.
  • Acompanhe a página de mudanças antes de atualizar a sua integração.