Run an async job
Submit a long-running simulation as an async job, poll its status by id, fetch the result when it completes, and cancel a queued or running job.
This guide shows you how to offload a large or slow simulation to an asynchronous job. Instead of holding an HTTP connection open while the engine works, you submit the simulation to POST /v1/jobs, get a job_id back immediately, then poll GET /v1/jobs/{job_id} until the job reaches a terminal state and read the result from GET /v1/jobs/{job_id}/result. You need a verified account and an API key (see Authentication). The examples target the hosted API at https://api.algenta.ai; a self-hosted engine at http://localhost:8000 behaves the same way.
When to use an async job
Use an async job when the work does not comfortably fit in one request/response cycle. The clearest case is a very large simulation — an expert-mode run can request up to 1,000,000 runs (runs is bounded 100 <= runs <= 1_000_000 in expert mode, and 100 <= runs <= 100_000 in auto mode). A 1,000,000-run scenario, a heavy sensitivity or mcmc model, or any operation you expect to take many seconds is a good candidate. The async path also lets you fire many jobs without blocking, and optionally receive a webhook when each finishes via the callback_url.
Submitting a job creates an underlying simulation run in the queued state with execution_type = async, then enqueues the work. If no background worker is available (common in local and self-hosted setups), the API executes the job in-process instead — the contract you poll is identical either way.
Submit a job
Send the same simulation body you would send to POST /v1/simulate, wrapped under a request key. The mode field on the request (auto or expert) is the discriminator. Optionally add a top-level callback_url — when set, the engine POSTs a job.completed webhook to that URL when the job finishes (it must be HTTPS in production).
curl -sS -X POST "$ALGENTA_API_URL/v1/jobs" \
-H "Authorization: Bearer $ALGENTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"request": {
"mode": "expert",
"simulation_model": "monte_carlo",
"simulation": {
"variables": [
{"name": "revenue", "distribution": "lognormal", "params": {"mean": 11.5, "std": 0.4}},
{"name": "cost", "distribution": "triangular", "params": {"low": 40000, "mode": 60000, "high": 90000}}
],
"objective_function": "revenue - cost",
"scoring": {"expected_value": 0.6, "downside_risk": 0.4}
},
"runs": 1000000,
"seed": 42
},
"callback_url": "https://example.com/hooks/algenta"
}'import os
import httpx
base = os.environ.get("ALGENTA_API_URL", "https://api.algenta.ai")
headers = {"Authorization": f"Bearer {os.environ['ALGENTA_API_KEY']}"}
body = {
"request": {
"mode": "expert",
"simulation_model": "monte_carlo",
"simulation": {
"variables": [
{"name": "revenue", "distribution": "lognormal", "params": {"mean": 11.5, "std": 0.4}},
{"name": "cost", "distribution": "triangular", "params": {"low": 40000, "mode": 60000, "high": 90000}},
],
"objective_function": "revenue - cost",
"scoring": {"expected_value": 0.6, "downside_risk": 0.4},
},
"runs": 1_000_000,
"seed": 42,
},
"callback_url": "https://example.com/hooks/algenta",
}
resp = httpx.post(f"{base}/v1/jobs", headers=headers, json=body, timeout=30)
resp.raise_for_status()
submitted = resp.json()
job_id = submitted["job_id"]
print(submitted["status"], job_id)Expected result. The endpoint returns HTTP 202 Accepted with a SubmitJobResponse body — the work is acknowledged, not yet finished:
Capture the job_id (and the convenience poll_url) — you will use the id for every subsequent call.
Job status values
A job moves through a small state machine. The status field on the job object is always one of:
queued
Accepted and waiting to start.
No
validating
Request payload is being validated.
No
running
The engine is executing the simulation.
No
completed
Finished successfully; result is available.
Yes
failed
Execution errored; see error_message.
Yes
cancelled
Cancelled before completion.
Yes
expired
Completed result aged out past its TTL.
Yes
Valid transitions are queued -> validating -> running -> completed, with failed and cancelled reachable from the non-terminal states, and completed -> expired once a result passes its time-to-live. A submitted job's result has a default TTL of 24 hours, surfaced as ttl_expires_at on the job object.
Poll a job's status
Poll GET /v1/jobs/{job_id} on an interval until status is terminal. Each poll returns the full JobStatusResponse.
Expected result. While the job is in flight you will see status values of queued, then validating, then running. Once the engine finishes, a poll returns the terminal completed state with started_at and completed_at populated:
The callback_status field tracks webhook delivery: not_configured when no callback_url was given, pending before delivery, then delivered or failed. If the job ends in failed, error_message carries the reason.
Fetch the result
Once a job is completed, fetch its result from GET /v1/jobs/{job_id}/result. This endpoint is safe to call at any time — if the job is not yet done it reports the current status rather than erroring.
Expected result. For a completed job, the response wraps the simulation's decision envelope under a result key:
The shapes for the other terminal and in-flight states are:
List your jobs
To see all jobs for your organization, call GET /v1/jobs/list. It is paginated with page (default 1) and limit (default 25, max 200), and accepts an optional status filter (any of the status values above).
Expected result. A paginated envelope: jobs is an array of JobStatusResponse objects (ordered newest first), alongside total, page, limit, and pages.
Cancel a job
If a job is still in a non-terminal state, cancel it with POST /v1/jobs/{job_id}/cancel.
Expected result. The cancelled job is returned as a JobStatusResponse with status set to cancelled and completed_at populated. The underlying simulation run is also moved to cancelled.
Next steps
Simulate a scenario — build the synchronous
POST /v1/simulatebody that async jobs wrap.Run an agent — kick off and track long-running agent work the same way you track jobs.
Execution policy & safety limits — distinguish unlimited execution from request-shape and worker-capacity controls.
API reference — the full schema for every job endpoint, field, and status value.
Last updated
Was this helpful?