Ejemplos de uso de API

Recetas listas para usar en curl, Python y JavaScript para consultar datos públicos, sincronizar su base de datos y enviar lecturas de ovitrampas y visitas de manzanas.

/es-pe/apiVolver a la referencia

Pinitos

Todas las llamadas provienen de la misma base de datos y devuelven JSON. Los puntos finales públicos no requieren autenticación; los privados requieren su clave de acceso.

dirección base

/es-pe/api

El prefijo de idioma es parte de la URL (es-pe), pero no cambia los datos devueltos: los registros provienen del banco exactamente como fueron registrados en el campo.

prueba rápida
curl -G -d "municipality=Ponta Pora" --data-urlencode "country=Brasil" \
  /es-pe/api/lastcountingpublic

Si la respuesta es una lista JSON, la integración ya está funcionando.

La clave va en la URL. En todos los puntos finales privados, incluido POST, el key se lee de la cadena de consulta (?key=SUA_CHAVE). Enviándolo solo en el cuerpo del formulario devuelve 404 "Wrong key". Los demás campos siguen apareciendo en el cuerpo de la solicitud.

Consultar datos públicos

El punto final /api/lastcountingpublic devuelve los últimos recuentos de huevos con latitud, longitud, semana y año epidemiológicos. Es el punto de partida de mapas, paneles y estudios.

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" \
  /es-pe/api/lastcountingpublic
Python
import requests

BASE = "/es-pe/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 = "/es-pe/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");

Los mismos parámetros de ubicación. (country, state, municipality) Se aplican a otros puntos finales públicos: ovitrampas, manzanas, EDL, mantenimiento de EDL y puntos estratégicos. Simplemente cambiar la ruta del punto final ya cambia el conjunto de datos.

Sin ningún parámetro de ubicación, el punto final devuelve datos para todo Brasil. Filtrar por municipio o estado hace que la respuesta sea mucho más rápida.

Explorar todas las páginas

Compatibilidad con puntos finales paginados page del 1 al 100. Por encima de eso, la API responde con el texto "Maximum pagination is 100" y estado 200, es decir, el cuerpo ya no es una lista. Siempre verifique el tipo antes de iterar.

Python
import requests

BASE = "/es-pe/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")
¿Llegaste a la página 100? Limite el filtro en lugar de intentar la página 101: busque condado por condado o utilice date_start e date_end dividir el período en intervalos más pequeños.

Sincronización incremental

Para mantener una base reflejada, no descargue todo nuevamente con cada ejecución. El punto final /api/lastcountingpublic aceptado id, que devuelve sólo los recuentos de ese identificador, y también date (fecha de inclusión) e date_collect (data de coleta).

Python
import json
import os
import requests

BASE = "/es-pe/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")

Mantenga siempre el más grande counting_id recibido, no la fecha de ejecución: un conteo ingresado en el campo hoy puede referirse a una semana anterior, y el filtro por id no deja escapar estos registros.

Exportar a CSV

Los recuentos públicos ya vienen con coordenadas, por lo que puedes generar una hoja de cálculo o alimentar un mapa sin ningún tipo de unión adicional.

Python
import csv
import requests

BASE = "/es-pe/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 datos

Los siguientes ejemplos utilizan la API privada y requieren una clave. El alcance geográfico de la clave define lo que puede registrar: una clave municipal solo registra en el propio municipio.

POST/api/postcountingPrivado

Enviar la lectura de una ovitrampa existente

Envía el recuento de huevos de una ovitrampa ya registrada. La ovitrampa está situada junto al ovitrap_group_id dentro del municipio del cayo, y la semana epidemiológica se calcula a partir del 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" \
  "/es-pe/api/postcounting?key=SUA_CHAVE"
Python
import requests

BASE = "/es-pe/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"
Atención: Si las coordenadas enviadas son diferentes a las registradas, la ovitrampa se actualiza con la nueva posición. Enviar siempre la coordenada real del punto, no la del agente en el momento de la lectura.
POST/api/postcountingPrivado

Instale una nueva ovitrampa al lado de la lectura.

si el ovitrap_group_id aún no existe en el municipio, en la misma solicitud se crea la ovitrampa. Enviar también la dirección y, en su caso, el tipo (ovitrap_type_id: 1 urbano, patrón; 2 rural).

Python
import requests

BASE = "/es-pe/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())
Respuestas específicas:
  • 400 — falta ovitrap_lat, ovitrap_lng ou ovitrap_group_id.
  • 400ovitrap_type_id diferente de 1 o 2.
  • 404 — Ya hay un recuento para esta ovitrampa, año y semana.
  • 500 — la fecha de envío cae en una semana epidemiológica futura o inválida.
POST/api/postactionPrivado

Registrar una visita de manzana

Usar block_id para registrar la visita en una manzana ya registrado. Si la manzana aún no existe, envíe block_group_id con los datos de la manzana y se crea automáticamente dentro del municipio clave.

Python — manzana existente
import requests

BASE = "/es-pe/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 — creando la manzana
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())

La lista completa de campos inmobiliarios y de depósitos. (a1, a2, b, c, d1, d2, e) esta en referencia de punto final. Los campos numéricos no enviados suponen cero, pero cualquier valor que no sea un número devuelve 400.

Eliminar registros

Las mudanzas son definitivas y siempre restringidas al municipio clave.

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

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

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

# o quarteirao inteiro
curl -X POST -d "block_group_id=97" \
  "/es-pe/api/postdeleteblock?key=SUA_CHAVE"
Para corregir un recuento publicado con el valor incorrecto, elimine la lectura con /api/postdeletecounting y enviarlo de nuevo con /api/postcounting — reenviarlo devuelve un error de duplicación.

Manejo de errores

El cuerpo de la respuesta es siempre una cadena JSON con el mensaje. Vale la pena analizar cada caso, porque no todos los errores merecen otro intento:

SituaciónCódigoque hacer
"Wrong key"404Compruebe que la clave esté en la cadena de consulta y no en el cuerpo.
Conteo duplicado404Ya hay lectura para la ovitrampa esta semana; quítelo antes de reenviarlo.
Visita duplicada409Ya hay visita a la manzana esta semana.
Fuera de alcance403La manzana no pertenece al municipio de Chave. No repitas.
Falta campo obligatorio400Corregir la presentación; repetir devuelve el mismo error.
Semana o año no válido500La fecha cae fuera de la semana epidemiológica aceptada. Corregir el 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

Buenas prácticas

  • Filtre por municipio o estado siempre que sea posible; sin filtrar, la consulta analiza todo el país.
  • Prefiere la sincronización incremental mediante id bajando toda la base todos los días.
  • Enviar solicitudes en serie. La API no está diseñada para decenas de llamadas simultáneas por cliente.
  • Verifique que la respuesta sea una lista antes de iterar: los mensajes de límite de paginación vienen con el estado 200.
  • guardar el counting_id y el block_id recibidos: son los que le permiten comparar los registros de Conta Ovos con los de su sistema.
  • Trate la semana epidemiológica como campo determinante: Conta Ovos solo acepta una lectura por ovitrampa por semana y una visita por manzana por semana.
  • sigue la pagina mudanças antes de actualizar su integración.