Consultar jobs
Cuando disparas un proceso con la API pública obtienes un job (ejecución). Un job es asíncrono: el endpoint de disparo responde de inmediato con un job en estado pending, y el robot lo va avanzando hasta un estado final. Esta página explica cómo consultar su estado y resultado, qué estados existen y cómo detener una ejecución en curso.
Todos los endpoints aquí descritos pertenecen a la API pública y se autentican con la cabecera X-API-Key: nora_ak_.... Consulta autenticación para crear y gestionar tus claves. La URL base de producción es https://nora.valisoftconsulting.com y el prefijo de la API es /api/v1.
Estados de un job
Sección titulada «Estados de un job»Un job pasa por uno de estos seis estados. Solo completed, failed y cancelled son finales (el job ya no cambiará).
| Estado | Significado | ¿Final? |
|---|---|---|
pending | Creado y encolado, aún sin asignar a una máquina. | No |
assigned | Asignado a una máquina; el agente está por arrancarlo. | No |
running | El robot se está ejecutando. | No |
completed | Terminó correctamente. El resultado está en output_data. | Sí |
failed | Terminó con error. El detalle está en error_message. | Sí |
cancelled | Cancelado o detenido antes de completar. | Sí |
flowchart TD
A[pending] --> B[assigned]
B --> C[running]
C --> D[completed]
C --> E[failed]
A --> F[cancelled]
B --> F
C --> F
Consultar estado y resultado
Sección titulada «Consultar estado y resultado»GET /api/v1/jobs/{job_id}Devuelve el job completo. Requiere el scope jobs:read (o una clave sin restricción de scopes). Límite de uso: 60 solicitudes por minuto por clave o IP.
Ejemplo (curl)
Sección titulada «Ejemplo (curl)»curl https://nora-api.valisoftconsulting.com/api/v1/jobs/3f1c0b4a-7c2e-4a1d-9b8e-1a2b3c4d5e6f \ -H "X-API-Key: nora_ak_xxxxxxxxxxxxxxxx"Respuesta
Sección titulada «Respuesta»Como toda la API pública, la respuesta va envuelta en {"success": true, "data": ...}:
{ "success": true, "data": { "id": "3f1c0b4a-7c2e-4a1d-9b8e-1a2b3c4d5e6f", "tenant_id": "9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d", "process_id": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e", "machine_id": "c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f", "status": "completed", "priority": 3, "input_data": { "factura": "F001-123" }, "output_data": { "total": 1180.0, "estado": "registrada" }, "logs": null, "error_message": null, "started_at": "2026-06-19T14:03:11Z", "finished_at": "2026-06-19T14:04:02Z", "retry_count": 0, "stop_requested": false, "progress_percent": 100, "progress_message": "Listo", "created_at": "2026-06-19T14:03:00Z", "updated_at": "2026-06-19T14:04:02Z", "process_name": "Registro de facturas", "machine_name": "BOT-CONTA-01" }}Campos más relevantes:
| Campo | Tipo | Descripción |
|---|---|---|
status | string | Estado actual (ver tabla de estados). |
output_data | objeto | null | Resultado del robot. Disponible al completed. |
error_message | string | null | Mensaje de error cuando el estado es failed. |
progress_percent | entero | null | Avance reportado por el robot (0–100). |
progress_message | string | null | Mensaje de avance del robot. |
stop_requested | boolean | true si se solicitó detener el job. |
started_at / finished_at | fecha-hora | null | Inicio y fin reales de la ejecución. |
process_name / machine_name | string | null | Nombres del proceso y la máquina asociados. |
Esperar el resultado: patrón de polling
Sección titulada «Esperar el resultado: patrón de polling»Como la ejecución es asíncrona, para obtener el resultado se consulta el job de forma periódica hasta que alcance un estado final (completed, failed o cancelled).
sequenceDiagram
participant C as Cliente
participant API as NORA API
C->>API: POST /api/v1/jobs/trigger
API-->>C: { data: { id, status: "pending" } }
loop cada N segundos
C->>API: GET /api/v1/jobs/{job_id}
API-->>C: { data: { status } }
end
Note over C: status final → leer output_data / error_message
Ejemplo (Python)
Sección titulada «Ejemplo (Python)»import timeimport requests
BASE = "https://nora-api.valisoftconsulting.com/api/v1"HEADERS = {"X-API-Key": "nora_ak_xxxxxxxxxxxxxxxx"}
FINAL = {"completed", "failed", "cancelled"}
def esperar_job(job_id: str, timeout: int = 600, intervalo: int = 5) -> dict: """Consulta el job hasta que termine o se agote el tiempo.""" limite = time.time() + timeout while time.time() < limite: r = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS) r.raise_for_status() job = r.json()["data"] if job["status"] in FINAL: return job time.sleep(intervalo) raise TimeoutError(f"El job {job_id} no terminó en {timeout}s")
job = esperar_job("3f1c0b4a-7c2e-4a1d-9b8e-1a2b3c4d5e6f")if job["status"] == "completed": print("Resultado:", job["output_data"])else: print("No completó:", job["status"], job.get("error_message"))Detener un job en curso
Sección titulada «Detener un job en curso»POST /api/v1/jobs/{job_id}/stopSolicita la detención de una ejecución. Requiere el scope jobs:stop (o una clave sin restricción de scopes). Límite de uso: 30 solicitudes por minuto por clave o IP.
Esta operación marca el job con stop_requested = true; el agente detecta la señal y detiene el robot. Solo se puede detener un job en estado running: con cualquier otro estado la API responde 422 con code: "VALIDATION_ERROR".
Ejemplo (curl)
Sección titulada «Ejemplo (curl)»curl -X POST \ https://nora-api.valisoftconsulting.com/api/v1/jobs/3f1c0b4a-7c2e-4a1d-9b8e-1a2b3c4d5e6f/stop \ -H "X-API-Key: nora_ak_xxxxxxxxxxxxxxxx"Respuesta
Sección titulada «Respuesta»Devuelve el job actualizado (envuelto en data), con stop_requested en true:
{ "success": true, "data": { "id": "3f1c0b4a-7c2e-4a1d-9b8e-1a2b3c4d5e6f", "status": "running", "stop_requested": true }}Errores
Sección titulada «Errores»Los errores siguen el formato estándar de la API: {"success": false, "error": {"code": "...", "message": "..."}}.
| HTTP | code | Cuándo ocurre |
|---|---|---|
| 401 | UNAUTHORIZED | Falta X-API-Key o la clave es inválida. |
| 403 | FORBIDDEN | La clave no tiene el scope requerido (jobs:read o jobs:stop). |
| 404 | NOT_FOUND | El job no existe o no pertenece a tu organización. |
| 422 | VALIDATION_ERROR | Intentas detener un job que no está running. |
| 429 | RATE_LIMIT_EXCEEDED | Se superó el límite de solicitudes por minuto. |