Skip to content

Run Cloud applications

Info

Learn the concepts and fundamentals of runs in the Explanation page.

A run is a single execution of an app against an instance. It is the basic functionality encompassed of receiving an input, running the app, and returning an output.

This how-to guide explains how to interact with runs using the /v1/applications/{application_id}/runs endpoints. Go to the reference section to see all the available parameters for each endpoint.

There are limits for submitting a new run and retrieving the results. If your input (or output) exceeds those limits, use the upload URL endpoint shown in the multi-file section of this guide to work with large payloads.

Start and get a run

Use the POST /v1/applications/{application_id}/runs endpoint to start a new run. The instance_id is passed as a query parameter, and the json input data is passed in the input field of the request payload. The endpoint returns a run_id that can be used to retrieve information about the run, including metadata and results.

curl -s -X POST "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs?instance_id=latest" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{"input": {"name": "world", "radius": 6378, "distance": 147.6}}' \
  | jq '.'
{
  "run_id": "latest-Lfjm3UPvg"
}

Retrieve the run information using the run_id with the GET /v1/applications/{application_id}/runs/{run_id}/metadata endpoint. The result includes important metadata, such as the status.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-Lfjm3UPvg/metadata" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq '.'
{
  "id": "latest-Lfjm3UPvg",
  "user_email": "sebastian@nextmv.io",
  "name": "",
  "description": "",
  "metadata": {
    "status": "succeeded",
    "status_v2": "succeeded",
    "created_at": "2026-07-29T05:33:44Z",
    "initiated_at": "2026-07-29T05:33:45.354762332Z",
    "duration": 5397,
    "execution_duration": 4537,
    "input_size": 52,
    "output_size": 913,
    "error": "",
    "application_id": "uncanny-rodent",
    "application_instance_id": "latest",
    "application_version_id": "",
    "execution_class": "6c9500mb870s",
    "runtime": "python-3_11",
    "run_type": {
      "type": "standard",
      "definition_id": "",
      "reference_id": ""
    },
    "format": {
      "input": {
        "type": "json"
      },
      "output": {
        "type": "json"
      }
    },
    "options": {
      "active_options": {
        "details": "true"
      },
      "request_options": null,
      "options_summary": [
        {
          "name": "details",
          "value": "true",
          "source": "version"
        }
      ]
    },
    "queuing_priority": 6,
    "queuing_disabled": false,
    "metrics": {
      "message": "Hello, world",
      "value": 1.23
    }
  }
}

Use the .metadata.status_v2 field to determine the status of the run. Please read our documentation on run polling to learn how to wait for a run to finish before retrieving its results.

Once the run completes, you can retrieve the results using the run_id with the GET /v1/applications/{application_id}/runs/{run_id} endpoint. The response includes the output of the run, along with the run information.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-Lfjm3UPvg" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq 'del(.output.assets)'
{
  "id": "latest-Lfjm3UPvg",
  "user_email": "sebastian@nextmv.io",
  "name": "",
  "description": "",
  "metadata": {
    "status": "succeeded",
    "status_v2": "succeeded",
    "created_at": "2026-07-29T05:33:44Z",
    "initiated_at": "2026-07-29T05:33:45.354762332Z",
    "duration": 5397,
    "execution_duration": 4537,
    "input_size": 52,
    "output_size": 913,
    "error": "",
    "application_id": "uncanny-rodent",
    "application_instance_id": "latest",
    "application_version_id": "",
    "execution_class": "6c9500mb870s",
    "runtime": "python-3_11",
    "run_type": {
      "type": "standard",
      "definition_id": "",
      "reference_id": ""
    },
    "format": {
      "input": {
        "type": "json"
      },
      "output": {
        "type": "json"
      }
    },
    "options": {
      "active_options": {
        "details": "true"
      },
      "request_options": null,
      "options_summary": [
        {
          "name": "details",
          "value": "true",
          "source": "version"
        }
      ]
    },
    "queuing_priority": 6,
    "queuing_disabled": false,
    "metrics": {
      "message": "Hello, world",
      "value": 1.23
    }
  },
  "output": {
    "options": {
      "details": true
    },
    "solution": {
      "message": "Hello, world"
    },
    "metrics": {
      "value": 1.23,
      "message": "Hello, world"
    }
  }
}

.output.assets was removed from the response above for a cleaner display.

Run with options

If an application is designed to accept options, you can pass them when starting a run using the options field in the request payload. The format for the options is a JSON object of string keys and string values.

curl -s -X POST "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs?instance_id=latest" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  -H "Content-Type: application/json" \
  -d '{
    "input": {"name": "world", "radius": 6378, "distance": 147.6},
    "options": {"details": "false"}
  }' \
  | jq '.'
{
  "run_id": "latest-jZlWq8PDR"
}

Once the run finishes, fetch its result with the same GET /v1/applications/{application_id}/runs/{run_id} endpoint used above.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-jZlWq8PDR" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq '.'
{
  "id": "latest-jZlWq8PDR",
  "user_email": "sebastian@nextmv.io",
  "name": "",
  "description": "",
  "metadata": {
    "status": "succeeded",
    "status_v2": "succeeded",
    "created_at": "2026-07-29T05:34:14Z",
    "initiated_at": "2026-07-29T05:34:14.374125279Z",
    "duration": 3986,
    "execution_duration": 3701,
    "input_size": 52,
    "output_size": 914,
    "error": "",
    "application_id": "uncanny-rodent",
    "application_instance_id": "latest",
    "application_version_id": "",
    "execution_class": "6c9500mb870s",
    "runtime": "python-3_11",
    "run_type": {
      "type": "standard",
      "definition_id": "",
      "reference_id": ""
    },
    "format": {
      "input": {
        "type": "json"
      },
      "output": {
        "type": "json"
      }
    },
    "options": {
      "active_options": {
        "details": "false"
      },
      "request_options": {
        "details": "false"
      },
      "options_summary": [
        {
          "name": "details",
          "value": "false",
          "source": "run"
        }
      ]
    },
    "queuing_priority": 6,
    "queuing_disabled": false,
    "metrics": {
      "message": "Hello, world",
      "value": 1.23
    }
  },
  "output": {
    "options": {
      "details": false
    },
    "solution": {
      "message": "Hello, world"
    },
    "metrics": {
      "value": 1.23,
      "message": "Hello, world"
    }
  }
}

List runs

Use the GET /v1/applications/{application_id}/runs endpoint to list all runs for an application. This endpoint is paginated, so the snippet below always uses pagination: it keeps requesting pages by passing the next_page_token value returned in each response as the pagetoken query parameter, until no token is returned.

ITEMS="[]"
PAGE_TOKEN=""

while :; do
  RESPONSE=$(curl -s -G "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs" \
    -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
    --data-urlencode "limit=50" \
    --data-urlencode "pagetoken=${PAGE_TOKEN}")

  ITEMS=$(jq -n --argjson existing "$ITEMS" --argjson page "$(echo "$RESPONSE" | jq '.runs')" '$existing + $page')
  PAGE_TOKEN=$(echo "$RESPONSE" | jq -r '.next_page_token // empty')

  [ -z "$PAGE_TOKEN" ] && break
done

echo "$ITEMS" | jq '.'
[
  {
    "id": "latest-jZlWq8PDR",
    "user_email": "sebastian@nextmv.io",
    "name": "",
    "description": "",
    "created_at": "2026-07-29T05:34:14.14158846Z",
    "application_id": "uncanny-rodent",
    "application_instance_id": "latest",
    "application_version_id": "",
    "run_type": {
      "type": "standard",
      "definition_id": "",
      "reference_id": ""
    },
    "execution_class": "6c9500mb870s",
    "queuing_priority": 6,
    "queuing_disabled": false,
    "runtime": "python-3_11",
    "status": "succeeded",
    "status_v2": "succeeded",
    "options": {
      "details": "false"
    },
    "request_options": {
      "details": "false"
    },
    "options_summary": [
      {
        "name": "details",
        "value": "false",
        "source": "run"
      }
    ]
  },
  ...
]

You can also filter the query by passing the start and end query parameters (RFC3339 timestamps), and include experiment, shadow, or ensemble child runs with the include_exp_runs, include_shad_runs, and include_ens_runs query parameters, respectively.

Get run logs

The Nextmv platform stores logs for applications that correctly implement logging. Each run that produces logs will have them available for inspection. You can retrieve the logs for a finished run using the GET /v1/applications/{application_id}/runs/{run_id}/logs endpoint.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-Lfjm3UPvg/logs" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq '.'
{
  "log": "Hello, world\nYou are 147.6 million km from the sun\n"
}

If a run is still in a running state, use the GET /v1/applications/{application_id}/runs/{run_id}/logs/live endpoint instead, which returns log lines produced so far (retained for 13 hours). Each response includes a status_v2 field and, while the run is not finalized, a next_available_in_seconds hint for when to poll again. If more log lines are available than fit in a single response, a next_page_token is also returned, which can be passed back as the since query parameter to continue reading from where you left off.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-2UwE38EDg/logs/live" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq '.'
{
  "items": [],
  "status_v2": "running",
  "next_available_in_seconds": 30
}

Get the input of a run

As a DecisionOps platform, Nextmv is focused on reproducibility. This means that you can always retrieve the input of a run using the GET /v1/applications/{application_id}/runs/{run_id}/input endpoint.

curl -s -X GET "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-Lfjm3UPvg/input" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  | jq '.'
{
  "name": "world",
  "radius": 6378,
  "distance": 147.6
}

If the input is large, or its content format is not json, the response instead contains a url field (pass format=url as a query parameter to always get this shape) that you can use to download the raw input file.

Cancel a run

You can cancel a run that is in these states using the PATCH /v1/applications/{application_id}/runs/{run_id}/cancel endpoint.

curl -s -X PATCH "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/latest-Lfjm3UPvg/cancel" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}"

Run multi-file and large inputs

Up to now in this how-to guide, we have been using the json content format for showing how to run applications. The Nextmv platform also supports the multi-file content format for running applications. When you run with the multi-file content format, input data is provided from one or more files.

When running json content format runs that exceed the limits for input or output, you can also use this methodology to submit runs with large payloads.

The steps for running multi-file or a large payload are as follows:

  1. Package the input files into a tar.gz file.
  2. Request an upload URL with the POST /v1/applications/{application_id}/runs/uploadurl endpoint.
  3. Upload the packaged input files directly to that URL.
  4. Start the run using the returned upload_id instead of input.
  5. Retrieve the result using the GET /v1/applications/{application_id}/runs/{run_id} endpoint, passing format=url as a query parameter to get a URL for downloading the output as a tar.gz file.
  6. Extract the output files from the downloaded tar.gz file.

For this example, assume the input data lives in a directory called inputs.

tar -czf inputs.tar.gz -C inputs .

UPLOAD_RESPONSE=$(curl -s -X POST "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/uploadurl" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}")
UPLOAD_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.upload_url')
UPLOAD_ID=$(echo "$UPLOAD_RESPONSE" | jq -r '.upload_id')

curl -s -X PUT "$UPLOAD_URL" --data-binary @inputs.tar.gz

curl -s -X POST "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs?instance_id=multi-file" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  -H "Content-Type: application/json" \
  -d "{
    \"upload_id\": \"${UPLOAD_ID}\"
  }" \
  | jq '.'
{
  "run_id": "multi-file-a_KrVqUPvg"
}

You can use all the same endpoints to get the run information and logs as shown in previous sections of this how-to guide. The difference lies in getting the result: because the output is not json, the GET /v1/applications/{application_id}/runs/{run_id} endpoint returns a 400 error asking you to pass format=url as a query parameter instead. That returns a url you can use to download the output as a tar.gz file, which you then extract into a directory of your choosing.

DOWNLOAD_URL=$(curl -s -G "https://api.cloud.nextmv.io/v1/applications/uncanny-rodent/runs/multi-file-a_KrVqUPvg" \
  -H "Authorization: Bearer ${NEXTMV_API_KEY}" \
  --data-urlencode "format=url" \
  | jq -r '.output.url')

mkdir -p outputs
curl -s "$DOWNLOAD_URL" -o output.tar.gz
tar -xzf output.tar.gz -C outputs

find outputs -type f
outputs/output.json

Normally, you specify the content format of the application in the app.yaml manifest, but you can also override it when starting a run with the configuration field.