# Run notebooks using API

The Datalore Run API lets you trigger notebook runs programmatically and check their execution status. Use it to automate workflows, integrate notebook execution into external systems, or run notebooks on a schedule.

Authentication
: Authenticate every request with a [bearer token](api-tokens.html).

Base URL
: ```URI
: https://datalore.jetbrains.com/
: ```
:
:
:
:
: ```URI
: https://{host}/
: ```

Request body
: Every request identifies a notebook by its `ownerId` and `id`. You can extract these values from the notebook URL, which follows the: `https://datalore.jetbrains.com/notebook/{ownerId}/{id}` format.
:
:
:
: Every request identifies a notebook by its `ownerId` and `id`. You can extract these values from the notebook URL, which follows the format `https://{host}/notebook/{ownerId}/{id}` format.

## Run a notebook

OpenAPI endpoint: POST /api/run/v1/notebook

Runs the notebook with the given ID and returns the run ID. Optionally accepts parameters for parameterized runs using values from the interactive controls in the notebook.

### Request parameters

**Request**

Body

Content type: application/json

- **application/json** (RunNotebookRequest, required)
- **notebookId** (string, required): The notebook identifier in the format {user_id}/{notebook_id}, taken from the notebook URL.
- **updateReport** (Enum): Updates the associated report if the run was successful. Ignored if no report has been published.
- **never**
- **on success**
- **directFileStorageWrite** (boolean): When true, saves run artifacts to notebook files instead of isolated artifact storage. Corresponds to the "Run data isolation" parameter in the UI.
- **parameters** (Array of RunParameter): Parameter values for a parameterized run, using variable names from the notebook's interactive controls.
- **name** (string, required): The variable name from the interactive control settings.
- **value** (string, required): The value to set for the variable.

**JSON example**

```JSON
{
  "notebookId": "user123/notebook456",
  "updateReport": "never",
  "directFileStorageWrite": true,
  "parameters": [
    {
      "name": "Columns",
      "value": "revenue"
    }
  ]
}
```

### Responses

**Response 200**

Content type: application/json

The notebook run was started successfully.

- **application/json** (RunNotebookResponse)
- **runId** (string): The ID of the executed run.

**200**

```JSON
{
  "runId": "example"
}
```

**Response 400**

The request is malformed or contains invalid parameters.

**Response 401**

No token was provided, or the token is invalid.

**Response 403**

You have view-only access to this notebook.

**Response 404**

The notebook is not shared with you, or the notebook ID is invalid.

## Get a run status

OpenAPI endpoint: GET /api/run/v1/{runId}

Returns the status of the run with the given ID.

### Request parameters

**Request**

Path

- **runId** (string, required): The ID of the run to check.

### Responses

**Response 200**

Content type: application/json

Run status retrieved successfully.

- **application/json** (RunStatusResponse)
- **runId** (string): The run ID.
- **userId** (string): The notebook user ID.
- **notebookId** (string): The notebook ID.
- **startTime** (string date-time): The run start time.
- **endTime** (string date-time): The run end time. Null while the run is in progress.
- **success** (boolean): Whether the run completed successfully.
- **status** (string): Current status of the run. Only present while the run is in progress.
- **updateReport** (Enum): The report update setting used for this run.
- **never**
- **on success**
- **directFileStorageWrite** (boolean): If true, the run results were saved to the notebook files, not a dedicated run artifact directory.
- **artifacts** (Array of Artifact): List of output artifacts produced by the run.
- **name** (string): Notebook file name (with .ipynb extension).
- **path** (string): Path to the notebook file.
- **readOnly** (boolean): Notebook access type: true for viewer access, false for editor access.

**200**

```JSON
{
  "runId": "example",
  "userId": "example",
  "notebookId": "example",
  "startTime": "1971-04-26T12:26:06Z",
  "endTime": "1971-04-26T12:26:06Z",
  "success": true,
  "status": "example",
  "updateReport": "never",
  "directFileStorageWrite": true,
  "artifacts": [
    {
      "name": "analysis.ipynb",
      "path": "/notebook/user123/notebook456/artifacts/run1/analysis.ipynb"
    }
  ],
  "readOnly": true
}
```

**Response 400**

The request is malformed or contains invalid parameters.

**Response 401**

No token was provided, or the token is invalid.

**Response 403**

You have view-only access to this notebook.

**Response 404**

The notebook is not shared with you, or the notebook ID is invalid.

## Run a notebook in interactive mode

OpenAPI endpoint: POST /api/computation/v1/notebook

Runs the notebook specified by its ID interactively. This updates the notebook outputs in place. Does not return a run ID or artifacts.

### Request parameters

**Request**

Body

Content type: application/json

- **application/json** (object, required)
- **notebookId** (string, required): The notebook identifier in the format {user_id}/{notebook_id}, taken from the notebook URL.

**JSON example**

```JSON
{
  "notebookId": "user123/notebook456"
}
```

### Responses

**Response 200**

The notebook was run interactively. Outputs are updated in place; no run ID or artifacts are returned.

**Response 400**

The request is malformed or contains invalid parameters.

**Response 401**

No token was provided, or the token is invalid.

**Response 403**

You have view-only access to this notebook.

**Response 404**

The notebook is not shared with you, or the notebook ID is invalid.

## Run API commands from a notebook

You can run API commands directly from a notebook in the Datalore editor to trigger another notebook. The following example shows a one-cell notebook containing API requests.

```PYTHON
HOST = "https://datalore.jetbrains.com"
API_TOKEN = "my-api-token"
NOTEBOOK_ID = "my-user/my-notebook" # make sure it's not the CURRENT notebook if you don't want infinite recursion

import requests
import time
from IPython.display import display, HTML
from urllib.parse import quote

response = requests.post(
  f"{HOST}/api/run/v1/notebook",
  headers={"Authorization": f"Bearer {API_TOKEN}"},
  json={"notebookId": NOTEBOOK_ID, "updateReport": "never"}
)
print('Submit response: ', response)
if not response.ok:
  raise RuntimeError("Error submitting request")
else:
  run_id = response.json()["runId"]

hasEndTime = False
while not hasEndTime:
  status_response = requests.get(
    f"{HOST}/api/run/v1/{run_id}",
    headers={"Authorization": f"Bearer {API_TOKEN}"}
  )
  run = status_response.json()
  if run.get('endTime'):
    hasEndTime = True
    print('Finished')
    print(status_response.json())
  else:
    print('Status: ', run.get('status'))
    time.sleep(1)

artifacts = {}
for artifact in status_response.json()['artifacts']:
  display(HTML(f"<a href='{artifact['path']}'>{artifact['name']}</a>"))
  artifacts[artifact['name']] = requests.get(
    f"{HOST}{quote(artifact['path'])}",
    headers={"Authorization": f"Bearer {API_TOKEN}"}
  ).text

artifacts
```

