Tutoriales
Ejemplo de uso con Python
El tutorial comienza con un login de usuario. Con esas credenciales se realiza un flujo completo y se crea una API Key. Después se muestra el flujo limitado de una integración que utiliza esa API Key.
Dependencia
pip install requests
Cliente y autenticación
import time
from pathlib import Path
import requests
class VeraquoAPI:
BASE_URL = "https://veraquo.gradiant.org/api/v2"
AUTH_URL = "https://veraquo.gradiant.org/api/auth/login"
def __init__(self):
self.base_url = self.BASE_URL
self.session = requests.Session()
def login(self, username: str, password: str) -> dict:
response = self.session.post(
self.AUTH_URL,
data={
"grant_type": "password",
"username": username,
"password": password,
},
headers={"user-agent": "custom"},
)
response.raise_for_status()
login_info = response.json()
self.session.headers.pop("X-API-Key", None)
self.session.headers.update(
{"Authorization": f"Bearer {login_info['access_token']}"}
)
return login_info
def create_api_key(self, name: str, expiration_days: int | None = None) -> dict:
response = self.session.post(
f"{self.base_url}/api-keys",
json={"name": name, "expiration_days": expiration_days},
)
response.raise_for_status()
return response.json()
def use_api_key(self, api_key: str) -> None:
self.session.headers.pop("Authorization", None)
self.session.headers.update({"X-API-Key": api_key})
def upload_file(self, path: str) -> dict:
file_path = Path(path)
with file_path.open("rb") as file_handle:
response = self.session.post(
f"{self.base_url}/files",
files={"file": (file_path.name, file_handle)},
)
response.raise_for_status()
return response.json()
def list_files(self) -> dict:
response = self.session.get(f"{self.base_url}/files")
response.raise_for_status()
return response.json()
def get_file(self, file_id: str) -> dict:
response = self.session.get(f"{self.base_url}/files/{file_id}")
response.raise_for_status()
return response.json()
def create_run(self, file_id: str, workers: list[str] | None = None) -> dict:
response = self.session.post(
f"{self.base_url}/runs",
json={
"file_id": file_id,
"run_schemas": None,
"workers": workers,
},
)
response.raise_for_status()
return response.json()
def list_runs(self) -> dict:
response = self.session.get(f"{self.base_url}/runs")
response.raise_for_status()
return response.json()
def get_run(self, run_id: str) -> dict:
response = self.session.get(f"{self.base_url}/runs/{run_id}")
response.raise_for_status()
return response.json()
def wait_for_run(self, run_id: str, interval_seconds: int = 5) -> dict:
while True:
run = self.get_run(run_id)
if run["status"] in {"ready", "ok", "alert", "error", "unprocessed"}:
return run
time.sleep(interval_seconds)
def get_results(self, run_id: str, result: str | None = None) -> dict:
params = {"result": result} if result is not None else None
response = self.session.get(
f"{self.base_url}/runs/{run_id}/results",
params=params,
)
response.raise_for_status()
return response.json()
def get_result(self, run_id: str, result_id: str) -> dict:
response = self.session.get(
f"{self.base_url}/runs/{run_id}/results/{result_id}"
)
response.raise_for_status()
return response.json()
def download_file(self, file_id: str, destination: str) -> None:
response = self.session.get(f"{self.base_url}/files/{file_id}/download")
response.raise_for_status()
Path(destination).write_bytes(response.content)
def download_result_file(
self, run_id: str, result_id: str, file_url: str, destination: str
) -> None:
response = self.session.get(
f"{self.base_url}/runs/{run_id}/results/{result_id}/files/{file_url}"
)
response.raise_for_status()
Path(destination).write_bytes(response.content)
El endpoint de login es /api/auth/login. La API de recursos utiliza la base URL https://veraquo.gradiant.org/api/v2.
Flujo completo con credenciales de usuario
El token de usuario permite utilizar la aplicación y administrar las API Keys.
api = VeraquoAPI()
api.login("{USERNAME}", "{PASSWORD}")
file_info = api.upload_file("./fichero.webp")
run_info = api.create_run(file_info["id"])
completed_run = api.wait_for_run(run_info["id"])
if completed_run["status"] in {"ready", "ok", "alert"}:
results = api.get_results(completed_run["id"])
print(results)
else:
print(f"La ejecución terminó con estado: {completed_run['status']}")
key_info = api.create_api_key("mi-integracion", expiration_days=90)
print(key_info["key_hash"])
La respuesta de GET /runs/{run_id}/results contiene runs_results y total. Cada elemento puede incluir id, result, result_details, worker_name, result_file_urls, detail, created_at, started_at, completed_at, info, extra_details y run_id.
Si el resultado incluye archivos, usa download_result_file con el run_id, el id del resultado y cada valor de result_file_urls. Para descargar el fichero original puedes usar download_file(file_info["id"], "./original.webp").
No existe un endpoint /status separado. Consulta GET /runs/{run_id} hasta que status sea ready, ok, alert, error o unprocessed, y después recupera los resultados con GET /runs/{run_id}/results.
Uso con una API Key
Una API Key no puede utilizarse para hacer login, consultar /users/me ni crear, listar o administrar API Keys. Esas operaciones requieren un token de usuario y devuelven 401 Unauthorized cuando se intenta utilizar una API Key.
Una API Key solo puede operar sobre los recursos que se hayan creado utilizando esa misma clave:
POST /files: subir ficheros.GET /files: listar los ficheros subidos con esa clave.GET /files/{file_id}yGET /files/{file_id}/download: consultar o descargar uno de sus ficheros.POST /runs: crear ejecuciones sobre sus ficheros.GET /runsyGET /runs/{run_id}: listar y consultar sus ejecuciones.GET /runs/{run_id}/results: listar los resultados de una ejecución propia.GET /runs/{run_id}/results/{run_result_id}yGET /runs/{run_id}/results/{run_result_id}/files/{file_url}: consultar un resultado y descargar sus archivos.
El objeto key_info del ejemplo anterior contiene la clave creada por el usuario. use_api_key cambia el cliente actual a autenticación mediante API Key y elimina el token de usuario antes de enviar la siguiente petición:
api.use_api_key(key_info["key_hash"])
my_files = api.list_files()
file_info = api.upload_file("./otro-fichero.webp")
run_info = api.create_run(file_info["id"])
completed_run = api.wait_for_run(run_info["id"])
if completed_run["status"] in {"ready", "ok", "alert"}:
my_runs = api.list_runs()
results = api.get_results(completed_run["id"])
print(my_files)
print(my_runs)
print(results)
El servidor filtra los listados y las consultas para que la API Key solo pueda acceder a sus propios ficheros, ejecuciones y resultados. No reutilices un file_id o run_id creado con otra clave.
Elegir workers y esquemas
Puedes solicitar workers concretos al crear la ejecución. Si no envías workers, el sistema selecciona los workers permitidos para el usuario.
run_info = api.create_run(
file_info["id"],
workers=["gradiant.org.syp.veraquo.heatmap.generation"],
)
run_schemas permite enviar configuración por cola cuando el worker lo requiere. La estructura depende de los workers disponibles para tu usuario; consulta GET /runs/schemas para obtener el esquema de ejecución.