Kernel API

Use this API to read your studies and datasets, and to start analysis pipelines.

Overview

The Kernel API is a REST API. Use it to read the datasets in a study. Also use it to start analysis pipelines on those datasets. Send all requests with HTTPS to one host:

https://api.kernel.com

Your organization must have a subscription plan that includes Kernel Cloud API Access. If your organization does not have such a plan, the API refuses all requests. To change your plan, contact Kernel.

Requests and responses use the JSON format. Each route needs an API key. Refer to Authentication. In this document, a dataset is one recording session. All times are floating-point seconds after the Unix epoch (UTC).

Authentication

An Organization Owner can make an API key on the Organization Settings page in the Kernel portal. Keep the key safe, as you keep a password safe. A person who has the key can read the studies and the datasets of your organization.

The key has this format: api_key_production.<uuid>. Copy the key exactly as the settings page shows it. Put the key in the Authorization header of each request:

http
Authorization: api_key_production.5e9c1e0a-1b23-4c56-8def-0123456789ab

The examples that follow set the key one time and then use it again:

python
import requests

api_key = "YOUR_API_KEY"
base_url = "https://api.kernel.com"
headers = {"Authorization": api_key}

If the API key is missing or not correct, the API returns 401 Unauthorized. A key gives access only to the studies of the organization that the key is for.

Requests and errors

These rules apply to all the routes:

  • All the IDs (study_id, dataset_id, pipeline_batch_id) must be UUIDs. If an ID is not correct, the API returns 400 Bad Request.
  • pipeline_name must be one of the available pipelines. If the name is unknown, the API returns 404 Not Found.
  • A request body can contain only the fields in this document. If the body contains a different field, the API returns 400 Bad Request.
  • pipeline_params is an object of boolean flags. For a batch, the API returns 400 Bad Request if a flag name is unknown or a flag value is not a boolean.
  • If a dataset is not part of the given study, the API returns 400 Bad Request. If the study or the dataset does not exist, the API returns 404 Not Found.

List studies

This route returns all the studies in an organization.

GET /api/v1/organization/{org_id}/studies

Path parameters

NameTypeDescription
org_idstring (uuid) requiredThe UUID of your organization. The API key must be for this organization.

Response

FieldTypeDescription
studiesarrayAll the studies in the organization. Each item contains the fields that follow.
studies[].idstring (uuid)The UUID of the study. Use this value for study_id in the other routes.
studies[].namestringThe name of the study.
studies[].is_completebooleanThis field is true if a user set the study to complete.
json
{
  "studies": [
    {
      "id": "96a09389-1079-49f5-9df0-fdbbf357d07d",
      "name": "Resting-state fNIRS cohort",
      "is_complete": false
    },
    {
      "id": "b4c1f0e2-8a77-4e39-9c15-2d6a1f4e7b8c",
      "name": "Pilot study 2025",
      "is_complete": true
    }
  ]
}

Example

python
import requests

api_key = "YOUR_API_KEY"
org_id = "d2f4a1b8-6c3e-4a90-8b17-5e9c0a2f3d61"

response = requests.get(
    f"https://api.kernel.com/api/v1/organization/{org_id}/studies",
    headers={"Authorization": api_key},
)
response.raise_for_status()

studies = response.json()["studies"]
open_studies = [study for study in studies if not study["is_complete"]]
print(open_studies)

List datasets

This route returns the ID and the metadata of each dataset in a study. The most recent dataset is first.

GET /api/v1/study/{study_id}/datasets

Path parameters

NameTypeDescription
study_idstring (uuid) requiredThe UUID of the study.

Response

FieldTypeDescription
datasetsarrayThe datasets in the study. The most recent dataset is first. Each item contains the fields that follow.
datasets[].idstring (uuid)The UUID of the dataset. Use this value for dataset_id in the pipeline routes.
datasets[].metaobjectThe metadata of the dataset. The keys can include name, description, experiment, number, and invalid.
datasets[].participantobjectThe data of the participant: id (uuid), participant_id (a name, for example S014), created_at (float), active (bool), pending (bool), and status (string).
datasets[].created_datefloatThe time when the dataset was made, in seconds after the epoch.
datasets[].started_atfloatThe time when the recording started, in seconds after the epoch.
datasets[].stopped_atfloatThe time when the recording stopped, in seconds after the epoch.
json
{
  "datasets": [
    {
      "id": "85f2c077-2d11-4fb5-acaf-5149db0922c6",
      "meta": {
        "name": "Session 2",
        "description": "Resting-state, eyes closed",
        "experiment": "resting_state",
        "number": "2"
      },
      "participant": {
        "id": "4ae9d4da-b6cb-4fb0-8636-8c6b44d0e808",
        "participant_id": "S014",
        "created_at": 1749556800.0,
        "active": true,
        "pending": false,
        "status": "enrolled"
      },
      "created_date": 1750939200.0,
      "started_at": 1750939230.0,
      "stopped_at": 1750939830.0
    }
  ]
}

Example

python
import requests

api_key = "YOUR_API_KEY"
study_id = "96a09389-1079-49f5-9df0-fdbbf357d07d"

response = requests.get(
    f"https://api.kernel.com/api/v1/study/{study_id}/datasets",
    headers={"Authorization": api_key},
)
response.raise_for_status()

datasets = response.json()["datasets"]
dataset_ids = [dataset["id"] for dataset in datasets]
print(dataset_ids)

Start a pipeline

This route starts an analysis pipeline for one dataset.

POST /api/v1/study/{study_id}/dataset/{dataset_id}/pipeline/{pipeline_name}

Path parameters

NameTypeDescription
study_idstring (uuid) requiredThe UUID of the study.
dataset_idstring (uuid) requiredThe UUID of the dataset.
pipeline_namestring requiredOne of the available pipelines that follow.

Available pipelines

  • analysis_eeg
  • analysis_nirs_epoched
  • analysis_nirs_glm
  • analysis_task
  • qc_eeg
  • qc_nirs_basic
  • qc_nirs
  • qc_syncbox
  • reconstruction
  • pipeline_snirf_gated
  • snirf_hb_moments
  • snirf_moments

Request body (optional)

FieldTypeDescription
pipeline_paramsobject optionalBoolean flags that change the operation of the pipeline. The permitted flags are different for each pipeline. The analysis pipelines accept the flags that follow.
json
{
  "pipeline_params": {
    "skip_channel_pruning": true,
    "skip_artifact_correction": true,
    "skip_global_short_channel_regression": true
  }
}

Response

FieldTypeDescription
job_idstring (uuid)The UUID of the pipeline job. Use this value to read the status of the job.
json
{
  "job_id": "32ce0eae-8d39-4ff4-ab59-249e034ebb8d"
}

Example

python
import requests

api_key = "YOUR_API_KEY"
study_id = "96a09389-1079-49f5-9df0-fdbbf357d07d"
dataset_id = "85f2c077-2d11-4fb5-acaf-5149db0922c6"
pipeline_name = "analysis_nirs_glm"

response = requests.post(
    f"https://api.kernel.com/api/v1/study/{study_id}/dataset/{dataset_id}/pipeline/{pipeline_name}",
    headers={"Authorization": api_key},
    json={  # optional
        "pipeline_params": {
            "skip_channel_pruning": True,
            "skip_artifact_correction": True,
            "skip_global_short_channel_regression": True,
        }
    },
)
response.raise_for_status()

job_id = response.json()["job_id"]
print(job_id)

Show the pipeline status

This route returns the status of the most recent pipeline job for a dataset. If the job is successful, the route also returns signed download URLs for the results.

GET /api/v1/study/{study_id}/dataset/{dataset_id}/pipeline/{pipeline_name}/status

Path parameters

NameTypeDescription
study_idstring (uuid) requiredThe UUID of the study.
dataset_idstring (uuid) requiredThe UUID of the dataset.
pipeline_namestring requiredThe name of the pipeline that you started.

Response

FieldTypeDescription
job_idstring (uuid)The UUID of the most recent job.
statusstringThe status of the job. It is one of the values that follow.
pipeline_paramsobjectThe flags for this job. This field is present only if the request set flags.
signed_urlsobjectThis field is present only when status is SUCCEEDED. It contains batch_job_id, execution_id, mime_type, urls (each asset path and its signed download URL), and sizes (each asset path and its size in bytes).

SUBMITTEDPENDINGRUNNABLESTARTINGRUNNINGSUCCEEDEDFAILED

json
{
  "job_id": "32ce0eae-8d39-4ff4-ab59-249e034ebb8d",
  "status": "SUCCEEDED",
  "pipeline_params": { "skip_channel_pruning": true },
  "signed_urls": {
    "batch_job_id": "7a1f5478-9cd1-4b35-916c-20372a86eb03",
    "execution_id": "5083918b-5ced-49da-b208-7edffa0f9566",
    "mime_type": "application/vnd.kernel.download",
    "urls": {
      "moments/HbO_moments.snirf": "https://kernel-assets.s3.amazonaws.com/...&X-Amz-Signature=...",
      "qc/qc_report.html": "https://kernel-assets.s3.amazonaws.com/...&X-Amz-Signature=..."
    },
    "sizes": {
      "moments/HbO_moments.snirf": 8734512.0,
      "qc/qc_report.html": 45213.0
    }
  }
}

Example

python
import requests

api_key = "YOUR_API_KEY"
study_id = "96a09389-1079-49f5-9df0-fdbbf357d07d"
dataset_id = "85f2c077-2d11-4fb5-acaf-5149db0922c6"
pipeline_name = "analysis_nirs_glm"

response = requests.get(
    f"https://api.kernel.com/api/v1/study/{study_id}/dataset/{dataset_id}/pipeline/{pipeline_name}/status",
    headers={"Authorization": api_key},
)
response.raise_for_status()

status = response.json()
print(status["status"])
if status["status"] == "SUCCEEDED":
    for asset_path, url in status["signed_urls"]["urls"].items():
        print(asset_path, url)

Start a batch pipeline

This route starts the same pipeline for many datasets in a study with one request. The route returns a batch ID. Use the batch ID to read the progress of all the jobs.

POST /api/v1/study/{study_id}/pipeline/{pipeline_name}/batch

Path parameters

NameTypeDescription
study_idstring (uuid) requiredThe UUID of the study.
pipeline_namestring requiredOne of the available pipelines.

Request body

FieldTypeDescription
dataset_idsarray (uuid) requiredThe UUIDs of the datasets to process. Give a minimum of 1 dataset and a maximum of 500 datasets in one request.
pipeline_paramsobject optionalBoolean flags for each dataset in the batch. The API refuses unknown flag names and values that are not booleans.
json
{
  "dataset_ids": [
    "85f2c077-2d11-4fb5-acaf-5149db0922c6",
    "168d306d-2334-4340-a4d7-c6171c6cc21c",
    "7ab6093b-9639-4de4-8950-0569351aa0c8"
  ],
  "pipeline_params": {
    "skip_channel_pruning": true,
    "skip_artifact_correction": true,
    "skip_global_short_channel_regression": true
  }
}

Response

FieldTypeDescription
pipeline_batch_idstring (uuid)The UUID of the batch. Use this value to read the status of the batch.
json
{
  "pipeline_batch_id": "2425e5de-b37e-4f9e-8305-62433e862a9c"
}

Example

python
import requests

api_key = "YOUR_API_KEY"
study_id = "96a09389-1079-49f5-9df0-fdbbf357d07d"
pipeline_name = "analysis_nirs_glm"

response = requests.post(
    f"https://api.kernel.com/api/v1/study/{study_id}/pipeline/{pipeline_name}/batch",
    headers={"Authorization": api_key},
    json={
        "dataset_ids": [
            "85f2c077-2d11-4fb5-acaf-5149db0922c6",
            "168d306d-2334-4340-a4d7-c6171c6cc21c",
            "7ab6093b-9639-4de4-8950-0569351aa0c8",
        ],
        "pipeline_params": {  # optional
            "skip_channel_pruning": True,
            "skip_artifact_correction": True,
            "skip_global_short_channel_regression": True,
        },
    },
)
response.raise_for_status()

pipeline_batch_id = response.json()["pipeline_batch_id"]
print(pipeline_batch_id)

Show the batch pipeline status

This route returns the progress of a batch. When the batch is complete, the response also contains a signed URL. The URL gives a JSON file of results. The file has the status and the download links for each dataset.

GET /api/v1/study/{study_id}/pipeline/batch/{pipeline_batch_id}/status

Path parameters

NameTypeDescription
study_idstring (uuid) requiredThe UUID of the study.
pipeline_batch_idstring (uuid) requiredThe batch ID that the start-batch route returned.

Response

FieldTypeDescription
pipeline_batch_idstring (uuid)The UUID of the batch.
completebooleanThis field is true when all the jobs are complete.
statsobjectThe counts: total, not_analyzable, analyzable, succeeded, failed, and pending.
pipeline_paramsobjectThe flags for this batch. This field is present only if the request set flags.
results_urlstringThis field is present only when complete is true. It is a signed URL to the JSON file of batch results. The URL expires after 1 week.
json — batch not complete
{
  "pipeline_batch_id": "2425e5de-b37e-4f9e-8305-62433e862a9c",
  "complete": false,
  "stats": {
    "total": 3,
    "not_analyzable": 0,
    "analyzable": 3,
    "succeeded": 1,
    "failed": 0,
    "pending": 2
  }
}
json — batch complete
{
  "pipeline_batch_id": "2425e5de-b37e-4f9e-8305-62433e862a9c",
  "complete": true,
  "stats": {
    "total": 3,
    "not_analyzable": 0,
    "analyzable": 3,
    "succeeded": 2,
    "failed": 1,
    "pending": 0
  },
  "results_url": "https://kernel-assets.s3.amazonaws.com/...&X-Amz-Signature=..."
}

Example

python
import time
import requests

api_key = "YOUR_API_KEY"
study_id = "96a09389-1079-49f5-9df0-fdbbf357d07d"
pipeline_batch_id = "2425e5de-b37e-4f9e-8305-62433e862a9c"

while True:
    response = requests.get(
        f"https://api.kernel.com/api/v1/study/{study_id}/pipeline/batch/{pipeline_batch_id}/status",
        headers={"Authorization": api_key},
    )
    response.raise_for_status()
    status = response.json()
    print(status["stats"])

    if status["complete"]:
        print("Results:", status.get("results_url"))
        break
    time.sleep(30)