Optimize: Sync

POST /api/v1/optimize/sync

Solve a routing problem synchronously and return the full result in the response body. This is the most commonly used endpoint and the one most examples in this documentation target.

Description

Accepts a complete OptimizationRequest. The request is validated, travel matrices are computed if needed, the problem is normalized and solved, and the resulting OptimizationResponse is returned. The HTTP call blocks for up to options.time_limit_seconds + 120 seconds (a fixed grace period for matrix computation and post-processing) before a timeout error is raised.

Recurring injection

If the recurring-jobs feature is enabled (RECURRING_ENABLED=true) and the request includes a recurring block, active recurring patterns for the tenant resolved from X-API-Key are expanded and merged into jobs before solving.

Request body

Full OptimizationRequest. See the complete schema reference. Only resources (min 1 entry) and travel are required; every other section has a safe default.

Response

200 OK with a full OptimizationResponse. See the complete schema reference.

Examples

curl -X POST https://api.fieldgenius.be/api/v1/optimize/sync \
  -H "Content-Type: application/json" \
  -H "X-API-Key: your-adapter-key" \
  -H "X-Client-Key: your-client-key" \
  -d '{
  "metadata": { "problem_id": "brussels-am-route-2026-06-29" },
  "travel": {
    "distance_matrix": [
      [0, 6200, 8400, 11300, 9100],
      [6200, 0, 5300, 7800, 6900],
      [8400, 5300, 0, 4200, 5100],
      [11300, 7800, 4200, 0, 3300],
      [9100, 6900, 5100, 3300, 0]
    ],
    "time_matrix": [
      [0, 720, 960, 1260, 1080],
      [720, 0, 600, 900, 780],
      [960, 600, 0, 480, 600],
      [1260, 900, 480, 0, 420],
      [1080, 780, 600, 420, 0]
    ]
  },
  "resources": [
    {
      "id": "truck-brussels-01",
      "depot_index": 0,
      "capacities": { "weight": 800 },
      "time_window": { "start": 0, "end": 28800 }
    }
  ],
  "jobs": [
    { "id": "job-leuven-01", "location_index": 1, "service_time": 600,
      "demands": { "weight": 50 }, "time_windows": [{ "start": 0, "end": 14400 }] },
    { "id": "job-namur-02", "location_index": 2, "service_time": 900,
      "demands": { "weight": 120 } },
    { "id": "job-charleroi-03", "location_index": 3, "service_time": 600,
      "demands": { "weight": 80 } },
    { "id": "job-mons-04", "location_index": 4, "service_time": 600,
      "demands": { "weight": 60 } }
  ],
  "options": { "time_limit_seconds": 15 }
}'
import httpx

payload = {
  "metadata": { "problem_id": "brussels-am-route-2026-06-29" },
  "travel": {
    "distance_matrix": [
      [0, 6200, 8400, 11300, 9100],
      [6200, 0, 5300, 7800, 6900],
      [8400, 5300, 0, 4200, 5100],
      [11300, 7800, 4200, 0, 3300],
      [9100, 6900, 5100, 3300, 0]
    ],
    "time_matrix": [
      [0, 720, 960, 1260, 1080],
      [720, 0, 600, 900, 780],
      [960, 600, 0, 480, 600],
      [1260, 900, 480, 0, 420],
      [1080, 780, 600, 420, 0]
    ]
  },
  "resources": [
    {
      "id": "truck-brussels-01",
      "depot_index": 0,
      "capacities": { "weight": 800 },
      "time_window": { "start": 0, "end": 28800 }
    }
  ],
  "jobs": [
    { "id": "job-leuven-01", "location_index": 1, "service_time": 600,
      "demands": { "weight": 50 }, "time_windows": [{ "start": 0, "end": 14400 }] },
    { "id": "job-namur-02", "location_index": 2, "service_time": 900,
      "demands": { "weight": 120 } },
    { "id": "job-charleroi-03", "location_index": 3, "service_time": 600,
      "demands": { "weight": 80 } },
    { "id": "job-mons-04", "location_index": 4, "service_time": 600,
      "demands": { "weight": 60 } }
  ],
  "options": { "time_limit_seconds": 15 }
}

headers = {"X-API-Key": "your-adapter-key", "X-Client-Key": "your-client-key"}
resp = httpx.post(
    "https://api.fieldgenius.be/api/v1/optimize/sync",
    json=payload,
    headers=headers,
    timeout=60,
)
resp.raise_for_status()
result = resp.json()
print(result["status"], result["score"]["total"])

Example response:

{
  "status": "optimal",
  "problem_id": "brussels-am-route-2026-06-29",
  "solve_time_ms": 184,
  "routes": [
    {
      "resource_id": "truck-brussels-01",
      "day": null,
      "activities": [
        { "type": "start", "location_index": 0, "arrival_time": 0, "departure_time": 0 },
        { "type": "service", "job_id": "job-leuven-01", "location_index": 1,
          "arrival_time": 720, "departure_time": 1320,
          "load_on_departure": { "by_dimension": { "weight": 50 } } },
        { "type": "service", "job_id": "job-namur-02", "location_index": 2,
          "arrival_time": 1920, "departure_time": 2820,
          "load_on_departure": { "by_dimension": { "weight": 170 } } },
        { "type": "service", "job_id": "job-charleroi-03", "location_index": 3,
          "arrival_time": 3300, "departure_time": 3900,
          "load_on_departure": { "by_dimension": { "weight": 250 } } },
        { "type": "service", "job_id": "job-mons-04", "location_index": 4,
          "arrival_time": 4320, "departure_time": 4920,
          "load_on_departure": { "by_dimension": { "weight": 310 } } },
        { "type": "end", "location_index": 0, "arrival_time": 6000, "departure_time": 6000 }
      ],
      "summary": {
        "total_distance": 28900, "total_travel_time": 3480,
        "total_service_time": 2700, "total_waiting_time": 0,
        "total_time": 6000, "num_stops": 4, "num_jobs": 4,
        "max_loads": { "weight": 310 }, "cost": 28900.0
      },
      "violations": []
    }
  ],
  "unserved": [],
  "score": {
    "total": 28900.0, "travel_distance": 28900.0, "travel_time": 3480.0,
    "fixed_vehicle_cost": 0.0, "penalty_dropped": 0.0,
    "fairness_cost": 0.0, "num_vehicles_used": 1
  },
  "warnings": []
}

Errors

StatusCodeResolution
422VALIDATION_ERROR / SCHEMA_ERROR / etc.Fix the field named in field and resubmit. Use /optimize/validate to debug request shape issues without waiting on the solver.
422SOLVER_INFEASIBLENo feasible plan exists. Enable output_options.include_diagnostics and inspect infeasibility_report.
422SOLVER_TIMEOUT_NO_SOLUTIONIncrease options.time_limit_seconds or simplify constraints.
500SOLVER_ERROR / INTERNAL_ERRORCheck server logs.

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