Optimize: Async

POST /api/v1/optimize/async

Queue a solve and return a job ID immediately, without waiting for the solver to finish.

Description

Accepts the same OptimizationRequest body as /optimize/sync. The request is stored, a job record is created in queued status, and a background task is launched to run the solve. The HTTP response returns immediately with the job ID and initial status. Poll GET /jobs/{job_id} to retrieve the result once it transitions to completed.

Job store is in-memory

The current job store implementation is an in-memory dictionary. Queued and completed async jobs do not survive a process restart. A persistent (Redis or SQLite-backed) job store is a planned production-readiness item, not yet implemented.

Request body

Full OptimizationRequest, identical shape to /optimize/sync.

Response

202 Accepted with an AsyncJobStatus object:

NameTypeRequiredDefaultDescription
job_idstringoptional-Generated job identifier; use this to poll GET /jobs/{job_id}.
statusstringoptional-One of queued, running, completed, failed, cancelled.
problem_idstring | nulloptionalnullEcho of metadata.problem_id.
created_atstring | nulloptionalnullISO-8601 timestamp.
started_atstring | nulloptionalnullISO-8601 timestamp; set once the solve begins.
completed_atstring | nulloptionalnullISO-8601 timestamp; set once terminal.
resultOptimizationResponse | nulloptionalnullPopulated once status is completed.
errorobject | nulloptionalnullPopulated if launching or running the solve failed.

Examples

curl -X POST https://api.fieldgenius.be/api/v1/optimize/async \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-adapter-key" \
  -H "X-Client-Key: your-client-key" \
  -d @large_fleet_problem.json

# {"job_id": "3fa6c1e2-...", "status": "queued", "problem_id": "large-fleet-2026-06-29"}
import time
import httpx

headers = {"X-API-Key": "your-adapter-key", "X-Client-Key": "your-client-key"}
resp = httpx.post("https://api.fieldgenius.be/api/v1/optimize/async", json=payload, headers=headers)
job = resp.json()
job_id = job["job_id"]

while True:
    status = httpx.get(f"https://api.fieldgenius.be/api/v1/jobs/{job_id}", headers=headers).json()
    if status["status"] in ("completed", "failed", "cancelled"):
        break
    time.sleep(2)

if status["status"] == "completed":
    print(status["result"]["score"]["total"])
else:
    print(status.get("error"))

Errors

StatusCodeResolution
202(none, always accepted)If launching the background task fails, the job is marked failed with an INTERNAL_ERROR in its error field rather than returning a non-202 status.
422VALIDATION_ERRORSurfaces in the job's error field once it transitions to failed, since validation happens inside the background task.

FieldGenius VRP API documentation. Generated from the engineering source of truth (.tex docs and app/ source).