Solve
The Solve endpoints are the core of the JAOT API. Send any optimization problem as JSON and receive the optimal solution. JAOT supports linear programming (LP), integer programming (IP), mixed-integer programming (MIP), and binary problems.
POST /api/v2/solve
Solve an optimization problem synchronously. The request blocks until the solver finishes or the time limit is reached.
Authentication: Requires API key or JWT token.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | A descriptive name for the problem |
objective | object | Yes | Objective function definition |
objective.sense | string | Yes | "minimize" or "maximize" |
objective.expression | string | Yes | Mathematical expression (e.g. "50*chairs + 40*tables") |
variables | array | Yes | List of decision variable definitions |
variables[].name | string | Yes | Variable name used in expressions |
variables[].type | string | Yes | "continuous", "integer", or "binary" |
variables[].lower_bound | number | No | Lower bound (default: 0) |
variables[].upper_bound | number | No | Upper bound (default: infinity) |
constraints | array | Yes | List of constraint definitions |
constraints[].name | string | No | Descriptive constraint name |
constraints[].expression | string | Yes | Constraint expression (e.g. "2*chairs + 3*tables <= 240") |
options | object | No | Solver options |
options.time_limit_seconds | number | No | Maximum solve time in seconds (default: 60) |
options.gap_tolerance | number | No | Optimality gap tolerance (default: 0.0001) |
template | string | No | Template name for template-based solving |
input | object | No | Input data for template-based solving |
Response
| Field | Type | Description |
|---|---|---|
status | string | Solve status (see table below) |
objective_value | number | Optimal objective function value |
variables | array | Variable names and their optimal values |
solution | object | Variable-value map for quick access |
solve_time_seconds | number | Wall-clock solve time |
gap | number | Optimality gap (0.0 = proven optimal) |
iterations | number | Solver iterations performed |
nodes | number | Branch-and-bound nodes explored |
credits_used | number | Credits consumed by this solve |
credits_remaining | number | Organization credit balance after solve |
Status values:
| Status | Meaning |
|---|---|
optimal | Globally optimal solution found |
feasible | Solution found, but optimality not proven |
infeasible | No feasible solution exists |
unbounded | Objective is unbounded |
time_limit | Time limit reached; best solution (if any) returned |
error | Solver exception |
Examples
import httpx
API_URL = "https://api.jaot.io/api/v2"
headers = {"Authorization": "Bearer ok_live_your_key_here"}
response = httpx.post(f"{API_URL}/solve", headers=headers, json={
"name": "furniture_production",
"variables": [
{"name": "chairs", "type": "integer", "lower_bound": 0, "upper_bound": 100},
{"name": "tables", "type": "integer", "lower_bound": 0, "upper_bound": 80},
],
"objective": {"sense": "maximize", "expression": "50*chairs + 40*tables"},
"constraints": [
{"name": "assembly_hours", "expression": "2*chairs + 3*tables <= 240"},
{"name": "finishing_hours", "expression": "4*chairs + 2*tables <= 200"},
],
"options": {"time_limit_seconds": 30},
})
result = response.json()
print(f"Status: {result['status']}")
print(f"Revenue: ${result['objective_value']}")
print(f"Chairs: {result['solution']['chairs']}, Tables: {result['solution']['tables']}")Response
{
"status": "optimal",
"objective_value": 3500.0,
"variables": [
{"name": "chairs", "value": 30, "type": "integer"},
{"name": "tables", "value": 60, "type": "integer"}
],
"solution": {"chairs": 30, "tables": 60},
"solve_time_seconds": 0.045,
"gap": 0.0,
"iterations": 12,
"nodes": 1,
"credits_used": 2,
"credits_remaining": 93
}Errors
| HTTP Code | Error | Description |
|---|---|---|
| 400 | bad_request | Invalid problem definition (undefined variable, invalid bounds) |
| 401 | unauthorized | Missing or invalid API key |
| 402 | insufficient_credits | Not enough credits to solve this problem |
| 429 | rate_limited | Too many requests |
Insufficient credits response:
{
"error": "insufficient_credits",
"credits_needed": 5,
"credits_available": 2,
"message": "This problem requires 5 credits, but you only have 2."
}POST /api/v2/solve/async
Start an asynchronous solve. Returns immediately with a task ID. Use polling or WebSocket to retrieve the result when it completes.
Authentication: Requires API key or JWT token.
Request Body
Same as POST /api/v2/solve.
Response
| Field | Type | Description |
|---|---|---|
task_id | string | Unique task identifier for polling |
status | string | Always "pending" on creation |
message | string | Confirmation message |
ws_url | string | WebSocket URL for real-time updates |
poll_url | string | Polling URL for status checks |
estimated_credits | number | Estimated credit cost |
Examples
import httpx
API_URL = "https://api.jaot.io/api/v2"
headers = {"Authorization": "Bearer ok_live_your_key_here"}
# For large problems, use async mode
response = httpx.post(f"{API_URL}/solve/async", headers=headers, json={
"name": "warehouse_routing",
"variables": [
{"name": f"route_{i}", "type": "binary"}
for i in range(500)
],
"objective": {
"sense": "minimize",
"expression": " + ".join(f"{cost}*route_{i}" for i, cost in enumerate(costs)),
},
"constraints": warehouse_constraints,
"options": {"time_limit_seconds": 120},
})
task = response.json()
print(f"Task ID: {task['task_id']}, Status: {task['status']}")Response
{
"task_id": "b7a3c9e2-1234-5678-abcd-ef0123456789",
"status": "pending",
"message": "Task queued for processing",
"ws_url": "/api/v2/ws/executions/b7a3c9e2-1234-5678-abcd-ef0123456789",
"poll_url": "/api/v2/solve/async/b7a3c9e2-1234-5678-abcd-ef0123456789",
"estimated_credits": 15
}Tip: Use async mode for problems with more than 1,000 variables or long time limits. Async solves run on dedicated workers and support real-time progress updates via WebSocket.
Polling for Results
Use GET /api/v2/solve/async/{task_id} to check the status of an async solve.
Pending:
{"task_id": "b7a3c9e2-...", "status": "pending", "message": "Task is waiting to be processed"}Running:
{"task_id": "b7a3c9e2-...", "status": "running", "progress": 0.45, "objective_value": 1234.56}Completed:
{"task_id": "b7a3c9e2-...", "status": "completed", "result": {"status": "optimal", "objective_value": 3500.0, "..."}}To retrieve async execution results, see the Executions page.
POST /api/v2/solve/validate
Validate a problem without solving it. No credits are charged. Useful for checking problem definitions before committing.
Authentication: Requires API key or JWT token.
Request Body
Same as POST /api/v2/solve.
Response (Valid Problem)
{
"valid": true,
"estimated_credits": 3,
"num_variables": 5,
"num_constraints": 8,
"variable_types": {
"continuous": 2,
"integer": 3,
"binary": 0
}
}Response (Invalid Problem)
{
"valid": false,
"errors": ["Objective references undefined variables: {'unknown_var'}"]
}POST /api/v2/solve/async/{task_id}/cancel
Cancel a running async task.
Authentication: Requires API key or JWT token.
Response
{"task_id": "b7a3c9e2-...", "cancelled": true, "message": "Task cancellation requested"}If the task already completed:
{"task_id": "b7a3c9e2-...", "cancelled": false, "message": "Task already completed, cannot cancel"}