← Pasto

API de Pasto: guía de uso

Versión 1. Estimación de materia seca (kg MS/ha) de pasturas a partir de imágenes satelitales.

Estado actual: demostración. Mientras el servicio corra en modo demostración, los valores son sintéticos y no corresponden a mediciones reales. Cada respuesta lo indica con "demo": true.

1. Autenticación

Todas las rutas /v1/... requieren la cabecera X-API-Key con la clave que te entrega Pasto. Sin clave, o con una clave vencida o dada de baja, la respuesta es 401.

Tratá la clave como un secreto: usala desde tu servidor, no la pongas en páginas web públicas ni en repositorios.

2. Medir los lotes de un archivo KML o KMZ

POST /v1/measurements/kml (multipart/form-data)

Campo Descripción
file obligatorio Archivo .kml o .kmz con uno o más lotes (polígonos).
species obligatorio Especie de pastura (ver la sección 4).
date opcional Fecha de interés, AAAA-MM-DD. Si falta, se usa la imagen más reciente.
include_geometry opcional true para recibir también el GeoJSON de cada lote.
curl -X POST "https://pasto.mateinalab.com/v1/measurements/kml" \
  -H "X-API-Key: pasto_TU_CLAVE" \
  -F "file=@lotes.kml" \
  -F "species=Verdeo avena"

Sobre el archivo: - Se miden los polígonos, uno por lote (por cada Placemark, con su nombre). Los puntos y las líneas se ignoran. - Coordenadas en WGS84 (longitud,latitud, el formato estándar de KML). - Máximo 25 lotes y 5 MB por pedido; cada lote entre 0,1 y 500 ha.

3. Medir un círculo alrededor de un punto

POST /v1/measurements/point (JSON)

Campo Descripción
latitude, longitude obligatorios Centro, en grados decimales.
radius obligatorio Radio en metros, entre 20 y 500.
species obligatorio Especie de pastura.
date, include_geometry opcionales Igual que en el endpoint de KML.
curl -X POST "https://pasto.mateinalab.com/v1/measurements/point" \
  -H "X-API-Key: pasto_TU_CLAVE" \
  -H "Content-Type: application/json" \
  -d '{"latitude": -34.9, "longitude": -60.3, "radius": 150, "species": "Verdeo avena"}'

4. Especies

GET /v1/species devuelve la lista vigente, cada especie con su name, su resource y una description legible. Hoy son nueve: Verdeo ryegrass, Promocion ryegrass, Verdeo avena, Graminea pura, Leguminosa pura, Consociada base gramineas, Consociada base leguminosas, Consociada gramineas y leguminosas y Campo natural. El name es el identificador que se envía; no distingue mayúsculas ni tildes.

5. Respuesta

{
  "request_id": "35241fa2734a449985d7d5534a19d80f",
  "species": "Verdeo avena",
  "demo": true,
  "results": [
    {
      "name": "Potrero Norte",
      "area_ha": 25.1,
      "status": "ok",
      "satellite_date": "2026-10-09",
      "dry_matter_kg_ha": { "mean": 990, "median": 1029, "p10": 864, "p90": 1190 },
      "pixels": { "total": 2509, "valid": 2240, "percent_valid": 89.3 },
      "warnings": [],
      "geometry": null
    }
  ],
  "warnings": []
}

Hay un elemento en results por lote. dry_matter_kg_ha resume la materia seca en kg por hectárea (promedio, mediana y percentiles 10 y 90), calculada sobre los píxeles utilizables de 10 m × 10 m; las nubes y sombras se descartan y se cuentan en pixels. status es ok, o no_imagery si no hubo una imagen satelital utilizable para ese lote (en ese caso no hay estadísticas). Los warnings avisan, por ejemplo, de que pocos píxeles fueron utilizables. geometry es null salvo que envíes include_geometry=true, y entonces trae el lote como GeoJSON.

6. Errores

Siempre tienen el mismo formato, con un request_id para pedir soporte (el ejemplo se pidió con ?lang=es; por defecto el message viene en inglés):

{ "error": { "code": "unknown_species", "message": "Especie desconocida: 'Soja'.", "request_id": "..." } }
HTTP code Cuándo
401 invalid_api_key Clave ausente, inválida, vencida o dada de baja.
413 file_too_large El archivo supera los 5 MB.
422 invalid_request, unknown_species, invalid_date, invalid_radius Parámetros inválidos.
422 invalid_kml, no_polygons, invalid_geometry, too_many_features, area_too_small, area_too_large Problemas con el KML.
502, 503 engine_error, engine_not_ready, auth_unavailable Falla temporal del servicio: reintentar más tarde.

7. Ejemplos de código

Python

import requests

URL = "https://pasto.mateinalab.com"
KEY = "pasto_TU_CLAVE"

with open("lotes.kml", "rb") as archivo:
    respuesta = requests.post(
        f"{URL}/v1/measurements/kml",
        headers={"X-API-Key": KEY},
        files={"file": archivo},
        data={"species": "Verdeo avena"},
        timeout=120,
    )
respuesta.raise_for_status()
for lote in respuesta.json()["results"]:
    print(lote["name"], lote["dry_matter_kg_ha"]["mean"], "kg MS/ha")

JavaScript (Node 20 o superior)

import { openAsBlob } from "node:fs";

const URL_BASE = "https://pasto.mateinalab.com";
const KEY = "pasto_TU_CLAVE";

const form = new FormData();
form.append("file", await openAsBlob("lotes.kml"), "lotes.kml");
form.append("species", "Verdeo avena");

const res = await fetch(`${URL_BASE}/v1/measurements/kml`, {
  method: "POST",
  headers: { "X-API-Key": KEY },
  body: form,
});
const datos = await res.json();
if (!res.ok) throw new Error(`${datos.error.code}: ${datos.error.message}`);
for (const lote of datos.results) console.log(lote.name, lote.dry_matter_kg_ha.mean, "kg MS/ha");

8. Idioma

Los mensajes (errores y advertencias) y las descripciones de las especies vienen en inglés por defecto. Agregá ?lang=es a cualquier pedido /v1/... para recibirlos en español, por ejemplo POST /v1/measurements/kml?lang=es. Los códigos (code, status) y los nombres de los campos nunca cambian: el code es para tu programa y el message es para personas.

9. Recomendaciones