Ejemplos
Los mismos tres casos en curl, Python y JavaScript: probar la llave, listar sectores y bajar la humedad de suelo de una quincena con paginación.
En todos, reemplaza LLAVE por tu llave (mejor desde una variable de entorno) y los ids por los tuyos (los obtienes de /campos y /campos/{campoId}/sectores).
1. Probar la llave
curl -sS -H "X-Api-Key: $LLAVE" https://api.cdtecif.cl/v1/cuentaimport os, requests
BASE = "https://api.cdtecif.cl/v1"
H = {"X-Api-Key": os.environ["CDTEC_LLAVE"]}
r = requests.get(f"{BASE}/cuenta", headers=H, timeout=30)
r.raise_for_status()
print(r.json()["data"])const BASE = 'https://api.cdtecif.cl/v1';
const H = { 'X-Api-Key': process.env.CDTEC_LLAVE };
const r = await fetch(`${BASE}/cuenta`, { headers: H });
if (!r.ok) throw new Error(`HTTP ${r.status}: ${JSON.stringify(await r.json())}`);
console.log((await r.json()).data);2. Campos y sectores
CAMPO=$(curl -sS -H "X-Api-Key: $LLAVE" https://api.cdtecif.cl/v1/campos | jq -r '.data[0].id')
curl -sS -H "X-Api-Key: $LLAVE" "https://api.cdtecif.cl/v1/campos/$CAMPO/sectores" \
| jq '.data[] | {id, nombre, superficieTeorica, telemetria}'campos = requests.get(f"{BASE}/campos", headers=H, timeout=30).json()["data"]
for campo in campos:
sectores = requests.get(f"{BASE}/campos/{campo['id']}/sectores", headers=H, timeout=30).json()["data"]
print(campo["nombre"], [s["nombre"] for s in sectores])const pedir = async (ruta, params = {}) => {
const url = new URL(`${BASE}${ruta}`);
Object.entries(params).forEach(([k, v]) => v !== undefined && url.searchParams.set(k, v));
const r = await fetch(url, { headers: H });
const cuerpo = await r.json();
if (!r.ok) throw new Error(`${cuerpo.error.codigo}: ${cuerpo.error.mensaje}`);
return cuerpo;
};
const { data: campos } = await pedir('/campos');
for (const campo of campos) {
const { data: sectores } = await pedir(`/campos/${campo.id}/sectores`);
console.log(campo.nombre, sectores.map((s) => s.nombre));
}3. Humedad de suelo por día, con paginación
SECTOR=66f2c0a2b3d4e5f6a7b8c9d1
Q="sectorId=$SECTOR&tipoSensor=Soil%20Moisture&granularidad=dia"
Q="$Q&desde=2026-10-01T00:00:00-03:00&hasta=2026-10-16T00:00:00-03:00&limite=1000"
CURSOR=""
while :; do
R=$(curl -sS -H "X-Api-Key: $LLAVE" "https://api.cdtecif.cl/v1/lecturas?$Q${CURSOR:+&cursor=$CURSOR}")
echo "$R" | jq -r '.data[] | [.fecha, .profundidad, .promedio, .unidad] | @tsv'
CURSOR=$(echo "$R" | jq -r '.paginacion.siguienteCursor // empty')
[ -z "$CURSOR" ] && break
donedef lecturas(sector_id, tipo, desde, hasta, granularidad="dia"):
params = {
"sectorId": sector_id, "tipoSensor": tipo, "granularidad": granularidad,
"desde": desde, "hasta": hasta, "limite": 1000,
}
while True:
r = requests.get(f"{BASE}/lecturas", headers=H, params=params, timeout=30)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "5")))
continue
r.raise_for_status()
cuerpo = r.json()
yield from cuerpo["data"]
cursor = cuerpo.get("paginacion", {}).get("siguienteCursor")
if not cursor:
return
params["cursor"] = cursor
for fila in lecturas("66f2c0a2b3d4e5f6a7b8c9d1", "Soil Moisture",
"2026-10-01T00:00:00-03:00", "2026-10-16T00:00:00-03:00"):
print(fila["fecha"], fila["profundidad"], fila["promedio"], fila["unidad"])async function* lecturas(sectorId, tipoSensor, desde, hasta, granularidad = 'dia') {
const params = { sectorId, tipoSensor, granularidad, desde, hasta, limite: 1000 };
for (;;) {
const cuerpo = await pedir('/lecturas', params);
yield* cuerpo.data;
const cursor = cuerpo.paginacion?.siguienteCursor;
if (!cursor) return;
params.cursor = cursor;
}
}
for await (const fila of lecturas('66f2c0a2b3d4e5f6a7b8c9d1', 'Soil Moisture',
'2026-10-01T00:00:00-03:00', '2026-10-16T00:00:00-03:00')) {
console.log(fila.fecha, fila.profundidad, fila.promedio, fila.unidad);
}4. Clima de una estación y riegos de un campo
# Todas las variables de clima por hora, última semana
curl -sS -H "X-Api-Key: $LLAVE" \
"https://api.cdtecif.cl/v1/estaciones/$ESTACION/clima?granularidad=hora&desde=2026-10-07T00:00:00-03:00&hasta=2026-10-14T00:00:00-03:00"
# Solo la lluvia, por día (usa `suma`)
curl -sS -H "X-Api-Key: $LLAVE" \
"https://api.cdtecif.cl/v1/estaciones/$ESTACION/clima?tipoSensor=Rain&desde=2026-10-01T00:00:00-03:00&hasta=2026-11-01T00:00:00-03:00"
# Riegos de octubre de un sector
curl -sS -H "X-Api-Key: $LLAVE" \
"https://api.cdtecif.cl/v1/campos/$CAMPO/riegos?sectorId=$SECTOR&desde=2026-10-01T00:00:00-03:00&hasta=2026-11-01T00:00:00-03:00"
5. Sincronización incremental (patrón recomendado)
Para mantener una copia local al día sin gastar cuota:
- Una vez al día:
/campos, sus/sectoresy/equipos(cambian poco). - Cada hora, por sector:
/lecturaspor hora desde el últimoinicioguardado menos 3 horas (las últimas lecturas pueden completarse después) hasta ahora. Sobrescribe las filas por (inicio,tipoSensor,profundidad). - Cada hora, por campo:
/riegosdesde ayer hasta mañana (así entran los programados y se actualizan los que terminaron).
Con 20 sectores y 3 tipos de sensor son 60 peticiones por hora, muy por debajo del tope.