Exemples d'utilisation d'API

Recettes prêtes à l'emploi en curl, Python et JavaScript pour interroger les données publiques, synchroniser votre base de données et envoyer des lectures d'ovitrap et des visites d'îlots.

/fr-lu/apiRetour à la référence

Premiers pas

Tous les appels proviennent de la même base de données et renvoient du JSON. Les points de terminaison publics ne nécessitent pas d'authentification ; les privés nécessitent votre clé d’accès.

Adresse de base

/fr-lu/api

Le préfixe de langue fait partie de l'URL (fr-lu), mais cela ne change pas les données renvoyées : les enregistrements proviennent de la banque exactement tels qu'ils ont été enregistrés sur le terrain.

Test rapide
curl -G -d "municipality=Ponta Pora" --data-urlencode "country=Brasil" \
  /fr-lu/api/lastcountingpublic

Si la réponse est une liste JSON, l'intégration fonctionne déjà.

La clé va dans l'URL. Sur tous les points de terminaison privés, y compris POST, le key est lu à partir de la chaîne de requête (?key=SUA_CHAVE). L'envoyer uniquement dans le corps du formulaire renvoie 404 "Wrong key". Les autres champs continuent d'apparaître dans le corps de la requête.

Consulter les données publiques

Le point final /api/lastcountingpublic renvoie le dernier nombre d’œufs avec la latitude épidémiologique, la longitude, la semaine et l’année. C'est le point de départ de cartes, panneaux et études.

GET/api/lastcountingpublicPublique
curl
curl -G \
  --data-urlencode "municipality=Ponta Pora" \
  --data-urlencode "date_start=2025-01-01" \
  --data-urlencode "date_end=2025-12-31" \
  /fr-lu/api/lastcountingpublic
Python
import requests

BASE = "/fr-lu/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 = "/fr-lu/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");

Les mêmes paramètres de localisation (country, state, municipality) Ils s'appliquent à d'autres points de terminaison publics : ovitraps, îlots, EDL, maintenance EDL et points stratégiques. Le simple fait de changer le chemin du point de terminaison modifie déjà l'ensemble de données.

Sans aucun paramètre de localisation, le point de terminaison renvoie des données pour l'ensemble du Brésil. Le filtrage par commune ou par état rend la réponse beaucoup plus rapide.

Parcourir toutes les pages

Prise en charge des points de terminaison paginés page de 1 à 100. Au-dessus, l'API répond avec le texte "Maximum pagination is 100" et le statut 200 — c'est-à-dire que le corps n'est plus une liste. Vérifiez toujours le type avant de répéter.

Python
import requests

BASE = "/fr-lu/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")
Êtes-vous arrivé à la page 100? Affinez le filtre au lieu d'essayer la page 101 : recherchez comté par comté ou utilisez date_start e date_end pour diviser la période en intervalles plus petits.

Synchronisation incrémentielle

Pour conserver une base en miroir, ne téléchargez pas tout à nouveau à chaque exécution. Le point final /api/lastcountingpublic accepté id, qui renvoie uniquement les décomptes de cet identifiant, et également date (date d'inclusion) e date_collect (data de coleta).

Python
import json
import os
import requests

BASE = "/fr-lu/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")

Gardez toujours le plus grand counting_id reçu, pas la date d'exécution : un décompte saisi dans le champ aujourd'hui peut faire référence à une semaine précédente, et le filtre par identifiant ne laisse pas échapper ces enregistrements.

Exporter au format CSV

Les décomptes publics sont déjà accompagnés de coordonnées, vous pouvez donc générer une feuille de calcul ou alimenter une carte sans aucune jointure supplémentaire.

Python
import csv
import requests

BASE = "/fr-lu/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")

Envoi de données

Les exemples suivants utilisent l'API privée et nécessitent une clé. La portée géographique de la clé définit ce qu'elle peut enregistrer : une clé municipale n'enregistre que dans la municipalité elle-même.

POST/api/postcountingPrivé

Envoyer la lecture d'un ovitrap existant

Envoie le nombre d’œufs d’un ovitrap déjà enregistré. L'ovitrap est localisé près du ovitrap_group_id au sein de la commune de la clé, et la semaine épidémiologique est calculée à partir du terrain 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" \
  "/fr-lu/api/postcounting?key=SUA_CHAVE"
Python
import requests

BASE = "/fr-lu/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"
Attention: Si les coordonnées envoyées sont différentes de celles enregistrées, l'ovitrap est mis à jour avec la nouvelle position. Envoyez toujours la coordonnée réelle du point, et non celle de l'agent au moment de la lecture.
POST/api/postcountingPrivé

Installez un nouvel ovitrap à côté de la lecture

Si le ovitrap_group_id n'existe pas encore sur la commune, l'ovitrap est créé dans la même demande. Envoyez également l'adresse et, le cas échéant, le type (ovitrap_type_id: 1 urbain, modèle; 2 rural).

Python
import requests

BASE = "/fr-lu/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())
Réponses spécifiques :
  • 400 — manque ovitrap_lat, ovitrap_lng ou ovitrap_group_id.
  • 400ovitrap_type_id différent de 1 ou 2.
  • 404 — Il existe déjà un décompte pour cet ovitrap, année et semaine.
  • 500 — la date d'envoi tombe dans une semaine épidémiologique future ou invalide.
POST/api/postactionPrivé

Enregistrez une visite en îlot

Utiliser block_id pour lancer la visite dans un îlot déjà enregistré. Si l'îlot n'existe pas encore, envoyez block_group_id avec les données de l'îlot et il est automatiquement créé au sein de la commune clé.

Python — îlot existant
import requests

BASE = "/fr-lu/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 — créer l'îlot
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 liste complète des domaines immobiliers et dépôts (a1, a2, b, c, d1, d2, e) est dans référence du point de terminaison. Les champs numériques non envoyés supposent zéro, mais toute valeur qui n'est pas un nombre renvoie 400.

Supprimer des enregistrements

Les déménagements sont définitifs et toujours limités à la commune clé.

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

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

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

# o quarteirao inteiro
curl -X POST -d "block_group_id=97" \
  "/fr-lu/api/postdeleteblock?key=SUA_CHAVE"
Pour corriger un comptage affiché avec une valeur erronée, supprimez la lecture avec /api/postdeletecounting et renvoyez-le à nouveau avec /api/postcounting — le renvoyer renvoie une erreur de duplication.

Gestion des erreurs

Le corps de la réponse est toujours une chaîne JSON avec le message. Cela vaut la peine de traiter chaque cas, car toutes les erreurs ne méritent pas une nouvelle tentative :

SituationCodeCe qu'il faut faire
"Wrong key"404Vérifiez que la clé est dans la chaîne de requête et non dans le corps.
Double comptage404Il y a déjà de la lecture pour l'ovitrap cette semaine ; veuillez le retirer avant de renvoyer.
Visite en double409Il y a déjà une visite à l'îlot cette semaine.
Hors de portée403L'îlot n'appartient pas à la commune de Chave. Ne répétez pas.
Champ obligatoire manquant400Corriger la soumission ; répéter renvoie la même erreur.
Semaine ou année invalide500La date tombe en dehors de la semaine épidémiologique acceptée. Corriger le champ 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

Bonnes pratiques

  • Filtrez par municipalité ou par État chaque fois que cela est possible : sans filtrage, la requête analyse l'ensemble du pays.
  • Préférez la synchronisation incrémentielle par id abaisser toute la base chaque jour.
  • Envoyez des demandes en série. L'API n'est pas conçue pour des dizaines d'appels simultanés par client.
  • Vérifiez que la réponse est une liste avant de procéder à une itération : les messages de limite de pagination ont le statut 200.
  • Enregistrez le counting_id et le block_id reçus — ce sont eux qui vous permettent de faire correspondre les enregistrements Conta Ovos avec ceux de votre système.
  • Considérez la semaine épidémiologique comme le champ déterminant : Conta Ovos n'accepte qu'une seule lecture par ovitrap par semaine, et une visite par îlot et par semaine.
  • Suivez la page mudanças avant de mettre à jour votre intégration.