Solver as a Service
Sign Up Now →Sign Up Now

HTTP API

The solver contract, version 0.2.0: every operation of the solver service with its request and response bodies. Generated from the published OpenAPI contract.

Preview

POST /api/v1/feasibility/check#

Run the manifest's pre-solve checks through the solve contract. The same function the embedded runtime's ``check_feasibility`` calls. ``feasible`` is false exactly when a declared check fails; the failed checks are named in ``issues`` with the demand, supply and deficit, and ``contract.suggestions`` gives the smallest changes they prove necessary. Problem types with no declared checks are a typed 422.

Request body: FeasibilityCheckRequest

StatusMeaningBody
200Successful ResponseFeasibilityCheckResponse
422The request cannot be solved as submitted: missing inputs (missing_problem_data), an option the solve contract does not accept (unsupported_option), a problem type it has no answer for (unsupported_problem_type), a malformed repair request, or a structurally infeasible problem (rostering_structurally_infeasible, with named shortfalls and any ranked alternates). A body that is not a solve request at all returns the request-validation shape.SolveFailureEnvelope | RequestValidationFailure
503The solver engine or a dependency is unavailable (engine_unavailable: a requested engine is not installed in this deployment); retrying later may succeed.SolveFailureEnvelope

POST /api/v1/feasibility/check-quick#

The same checks as ``/feasibility/check``, in a compact answer (the body is the problem).

Request body: object

StatusMeaningBody
200Successful ResponseQuickFeasibilityResponse
422The request cannot be solved as submitted: missing inputs (missing_problem_data), an option the solve contract does not accept (unsupported_option), a problem type it has no answer for (unsupported_problem_type), a malformed repair request, or a structurally infeasible problem (rostering_structurally_infeasible, with named shortfalls and any ranked alternates). A body that is not a solve request at all returns the request-validation shape.SolveFailureEnvelope | RequestValidationFailure
503The solver engine or a dependency is unavailable (engine_unavailable: a requested engine is not installed in this deployment); retrying later may succeed.SolveFailureEnvelope

GET /api/v1/health#

Shallow liveness for THIS process only. This endpoint used to call the GPU worker's /health on every request. It is public and it is polled, so each poll cold-started an L4 and Cloud Run then held it for ~15 minutes — meaning a liveness check kept an accelerator billing around the clock. Measured 2026-08-19: 100% of worker traffic was GET /health from this fan-out, ~1280 requests/day, holding the GPU 12+ hours/day for zero solves. A liveness probe must never wake an accelerator. Worker status now comes from the explicit deep check at /api/v1/health/gpu/aws-sqs-ec2, and even that is cached (see _worker_health).

StatusMeaningBody
200Successful Responseobject

POST /api/v1/recommendations/{problem_type}#

Recommendations from the solver's own advice (``solve_contract.recommend``). ``parameters``: the smallest parameter changes the pre-solve checks prove necessary (empty when nothing fails). ``constraints``: each constraint's gate/hard/soft class and where it is enforced. ``data``: missing inputs and the declared defaults in effect.

ParameterInRequiredTypeDescription
problem_typepathYesstring

Request body: RecommendationRequest

StatusMeaningBody
200Successful ResponseRecommendationsResponse
422The request cannot be solved as submitted: missing inputs (missing_problem_data), an option the solve contract does not accept (unsupported_option), a problem type it has no answer for (unsupported_problem_type), a malformed repair request, or a structurally infeasible problem (rostering_structurally_infeasible, with named shortfalls and any ranked alternates). A body that is not a solve request at all returns the request-validation shape.SolveFailureEnvelope | RequestValidationFailure
503The solver engine or a dependency is unavailable (engine_unavailable: a requested engine is not installed in this deployment); retrying later may succeed.SolveFailureEnvelope

GET /api/v1/recommendations/{problem_type}/types#

Recommendation Types

ParameterInRequiredTypeDescription
problem_typepathYesstring
StatusMeaningBody
200Successful ResponseRecommendationTypesResponse
422Validation ErrorHTTPValidationError

GET /api/v1/solve/{job_id}#

Job Status

ParameterInRequiredTypeDescription
job_idpathYesstring
StatusMeaningBody
200Successful Responseobject
422Validation ErrorHTTPValidationError

POST /api/v1/solve/{problem_type}#

Solve

ParameterInRequiredTypeDescription
problem_typepathYesstring

Request body: ApiSolveRequest

StatusMeaningBody
200The solve resultHostedSolveResponse
422The request cannot be solved as submitted: missing inputs (missing_problem_data), an option the solve contract does not accept (unsupported_option), a problem type it has no answer for (unsupported_problem_type), a malformed repair request, or a structurally infeasible problem (rostering_structurally_infeasible, with named shortfalls and any ranked alternates). A body that is not a solve request at all returns the request-validation shape.SolveFailureEnvelope | RequestValidationFailure
503The solver engine or a dependency is unavailable (engine_unavailable: a requested engine is not installed in this deployment); retrying later may succeed.SolveFailureEnvelope

GET /api/v1/version#

Version

StatusMeaningBody
200Successful Responseobject

Schemas#

ApiSolveRequest#

FieldTypeRequiredDescription
contextobject | nullNoAdmitted invocation context (single-lane execution)
optionsobjectNo
problemobjectNo
solverobjectNo

FeasibilityCheckRequest#

Pre-solve check request. ``problem.problem_type`` names the problem type.

FieldTypeRequiredDescription
enabled_constraintsarray of string | nullNo
problemobjectYesThe problem, with problem_type (vrp or rostering)

FeasibilityCheckResponse#

Pre-solve checks computed by the solver's own code. ``feasible`` is false exactly when a fail-severity check fails; true means no declared check found a blocker, which does not prove a plan exists. ``contract`` is the typed report, identical in the embedded model.

FieldTypeRequiredDescription
analysis_time_msintegerYes
analyzers_runarray of objectYes
confidencenumber | nullNo1.0 when a failed check certifies infeasibility; null otherwise
constraint_qualityobjectYes
contractFeasibilityReportYes
feasiblebooleanYes
issuesarray of FeasibilityIssueYes
problem_typestringYes
summarystringYes
warningsarray of FeasibilityIssueYes

FeasibilityIssue#

FieldTypeRequiredDescription
codestringYes
detailsobjectNo
messagestringYes
severityerror | warningYes

FeasibilityReport#

Pre-solve checks. They are necessary conditions: passing proves no plan exists.

FieldTypeRequiredDescription
checks_runintegerYes
contract_versionstringNo
findingsarray of objectYes
modelhosted | embeddedYes
notestringYes
problem_typestringYes
shortfallsarray of objectYes
skippedarray of objectYes
structurally_infeasiblebooleanYes
suggestionsarray of objectYes
totalsobjectYes
verdictinfeasible | no_blocker_foundYes

HTTPValidationError#

FieldTypeRequiredDescription
detailarray of ValidationErrorNo

HostedSolveResponse#

A completed or queued solve. ``contract`` is the solve-contract answer for contract problem types (vrp, rostering): the same shape the embedded model returns. Other fields are the service's legacy envelope.

FieldTypeRequiredDescription
contractSolveOutcome | nullNoSolve-contract answer (verdict, plan only when feasible, shortfalls, alternates, certificate, metadata)
job_idstring | nullNo
objective_valuenumber | nullNo
resultobject | nullNo
solutionobject | nullNoThe plan; null when the verdict is infeasible
solver_usedstring | nullNo
statusstringYescompleted, queued, running, or failed

QuickFeasibilityResponse#

FieldTypeRequiredDescription
contractFeasibilityReportYes
feasiblebooleanYes
reasonstringYes
suggestionsarray of objectYes

RecommendationRequest#

FieldTypeRequiredDescription
problemobject | nullNoThe problem; the body itself is read as the problem when absent
recommendation_typeparameters | constraints | dataNo

RecommendationTypesResponse#

FieldTypeRequiredDescription
problem_typestringYes
supportedbooleanYes
typesarray of stringYes

Recommendations#

Parameter changes the pre-solve checks prove necessary, and constraint classes.

FieldTypeRequiredDescription
contract_versionstringNo
modelhosted | embeddedYes
problem_typestringYes
recommendation_typeparameters | constraints | dataYes
recommendationsarray of objectYes
sourcestringYes

RecommendationsResponse#

FieldTypeRequiredDescription
contractRecommendationsYes
metadataobjectYes
recommendationsarray of objectYes
successbooleanYes

RequestValidationFailure#

FastAPI request-shape validation error (the body is not a solve request).

FieldTypeRequiredDescription
detailarray of objectYes

RosteringShortfall#

One named shortfall found by the pre-solve marginal feasibility checks.

FieldTypeRequiredDescription
check_idstringYesDeclared feasibility check that failed
check_typestring | nullNoExecutor type of the check
deficit_hoursnumber | nullNodemand_hours - supply_hours
demand_hoursnumber | nullNoHours of coverage the slice demands
messagestring | nullNoHuman-readable explanation of the shortfall
scopestring | nullNoWhat the check slices demand and supply by
sliceobjectNoThe slice that cannot be staffed (e.g. a location, a day, a skill)
supply_hoursnumber | nullNoHours the eligible staff can supply to the slice

SolveFailureEnvelope#

Typed failure body of a solve. Status tells the caller what kind of failure it is: * **422** - the request cannot be solved as submitted: inputs are missing (``missing_problem_data``, with ``missing_inputs``), a repair request is malformed, or the problem is structurally infeasible (``rostering_structurally_infeasible``, with the named ``shortfalls`` and any ranked ``alternates``). Retrying the same request fails the same way. * **503** - the engine or a dependency is unavailable (e.g. ``rostering_solver_unavailable``). Retrying later may succeed.

FieldTypeRequiredDescription
alternatesarray of object | nullNoRanked best-effort alternates, when an engine ran. Empty when the solve stopped before any engine ran (see alternates_unavailable_reason).
alternates_unavailable_reasonstring | nullNoWhy alternates is empty
detailstring | nullNoHuman-readable failure description
failure_codestringYesTyped failure code
missing_inputsarray of string | nullNoInput fields that are missing or invalid (missing_problem_data)
problem_typestring | nullNo
reportobject | nullNoFull pre-solve feasibility report, when one produced the failure
shortfallsarray of RosteringShortfall | nullNoNamed shortfalls behind rostering_structurally_infeasible (fail-severity findings of the pre-solve checks)
solver_usedstring | nullNo
solver_versionobject | nullNoBuild stamp of the solver that answered
statusstringYes'failed' or 'unsupported'

SolveMetadata#

Which model served the solve, which engine ran, and what it cost.

FieldTypeRequiredDescription
budget_secondsnumber | nullYes
contract_versionstringNo
cost_unitstringYes
enginestring | nullYesDotted name of the engine that produced the answer; None when no engine ran (the pre-solve checks certified the problem infeasible).
engine_reasonstringYes
engine_requestedstringYes
final_costnumber | nullYes
modelhosted | embeddedYes
problem_typestringYes
seedinteger | nullYes
seed_costnumber | nullYesCost of the construction seed, for comparison.
solvers_versionstringYes
wall_secondsnumberYes

SolveOutcome#

The answer to one solve, identical in shape in both models.

FieldTypeRequiredDescription
alternatesarray of objectNo
certificateobjectYes
contract_versionstringNo
costnumber | nullYes
metadataSolveMetadataYes
not_enforcedarray of stringNo
problem_typestringYes
shortfallsarray of objectNo
solutionobject | nullYesThe plan (routes or roster). Present only when the verdict is feasible.
verdictfeasible | infeasibleYes

ValidationError#

FieldTypeRequiredDescription
locarray of string | integerYes
msgstringYes
typestringYes