var apiKey = os.Getenv("API_KEY")
const url = "https://api.cloud.nextmv.io/v0/run"
// solve solves the problem using the Nextmv Cloud API.
func solve(data io.Reader) ([]byte, error) {
// Post job to Nextmv Cloud endpoint.
response, err := request("POST", url, data)
if err = json.Unmarshal(response, runIdResp); err != nil {
// Poll job status until it is finished or there is a timeout.
start, waitTime, waitMax, timeout := time.Now(), 0.2, 5., 60.
if time.Since(start).Seconds() > timeout {
return nil, fmt.Errorf("timed out after %f", timeout)
response, err = request("GET", url+"/"+runId+"/status", nil)
if err = json.Unmarshal(response, statusResp); err != nil {
status := statusResp.Status
if status == "started" || status == "requested" {
time.Sleep(time.Duration(waitTime) * time.Second)
waitTime = math.Min(waitTime*2, waitMax)
} else if status == "succeeded" {
} else if status == "timed_out" {
return nil, errors.New("no solution found within time limit")
} else if status == "failed" {
return nil, errors.New("failed to solve the problem")
return nil, fmt.Errorf("unknown status ocurred: %s", status)
response, err = request("GET", url+"/"+runId+"/result", nil)
if err := json.Indent(&out, response, "", " "); err != nil {
// request performs an HTTP request.
func request(method string, url string, data io.Reader) ([]byte, error) {
req, err := http.NewRequestWithContext(
req.Header.Add("Authorization", "Bearer "+apiKey)
req.Header.Add("Content-Type", "application/json")
req.Header.Add("accept", "application/json")
res, err := client.Do(req)
body, err := ioutil.ReadAll(res.Body)
data := strings.NewReader(`{
"shift_start": "2021-01-01T12:00:00-05:00",
"position": {"lon": 9.992, "lat": 53.553}
"id": "Landungsbrücken",
"position": {"lon": 9.968, "lat": 53.545}
"id": "Hauptbahnhof Nord",
"position": {"lon": 10.006, "lat": 53.553}
result, err := solve(data)
fmt.Println(string(result))