Skip to content

batch

Batch operation endpoint handlers.

BatchEndpoint

Bases: BaseEndpoint

Handles batch operation API endpoints.

Batch endpoints allow bulk operations across multiple resources in a single request. All endpoints are project-scoped.

cancel_analyses(project_id, request) async

Batch cancel multiple analyses.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchCancelAnalysesRequest

Batch cancellation request with analysis IDs

required

Returns:

Type Description
BatchCancelAnalysesResponse

Response with per-item results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

create_studies(project_id, request) async

Batch create multiple studies in a project.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchCreateStudiesRequest

Batch study creation request with list of studies

required

Returns:

Type Description
BatchCreateStudiesResponse

Response with per-item results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

Example
from yousleep_common.models import BatchCreateStudiesRequest, BatchStudyItem

request = BatchCreateStudiesRequest(
    studies=[
        BatchStudyItem(name="Subject 001", age=35),
        BatchStudyItem(name="Subject 002", age=42),
    ]
)
result = await client.batch.create_studies(project_id, request)
print(f"Created: {result.summary.created}, Errors: {result.summary.errors}")

delete_analyses(project_id, request) async

Delete analyses by selector — e.g. clear failed runs by status.

Example
from yousleep_common.models import (
    AnalysisFilter, AnalysisSelector, DeleteAnalysesRequest,
)

accepted = await client.batch.delete_analyses(
    project_id,
    DeleteAnalysesRequest(
        selector=AnalysisSelector(
            filter=AnalysisFilter(status_any=["failed"])
        ),
        expected_count=3,
    ),
)

delete_recordings(project_id, request) async

Delete recordings by selector (ids | all); same contract.

delete_studies(project_id, request) async

Delete studies by selector (background cascade; returns on acceptance).

The selector addresses the set with exactly one mode — ids, filter or all. Live-set selectors (filter/all) must carry expected_count: the count previewed via the filtered study list; a drifted set is rejected with a conflict error.

Example
from yousleep_common.models import (
    DeleteStudiesRequest, StudyFilter, StudySelector,
)

# Delete every study tagged "pilot" (previewed as 12 studies).
accepted = await client.batch.delete_studies(
    project_id,
    DeleteStudiesRequest(
        selector=StudySelector(filter=StudyFilter(tags_any=["pilot"])),
        expected_count=12,
    ),
)
print(f"{accepted.count} studies scheduled for deletion")

edit_study_tags(project_id, request) async

Add/remove tags across the selected studies, set-based.

Example
from yousleep_common.models import (
    EditStudyTagsRequest, StudyFilter, StudySelector,
)

# Remove the tag "pilot" from every study carrying it.
result = await client.batch.edit_study_tags(
    project_id,
    EditStudyTagsRequest(
        selector=StudySelector(filter=StudyFilter(tags_any=["pilot"])),
        remove=["pilot"],
        expected_count=12,
    ),
)
print(f"{result.count} studies updated")

get_analyses_status(project_id, request) async

Batch poll analysis status for multiple analyses.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchGetAnalysesStatusRequest

Batch status request with analysis IDs

required

Returns:

Type Description
BatchGetAnalysesStatusResponse

Response with per-analysis status results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

get_event_blocks(project_id, request) async

Batch retrieve event blocks for multiple analyses.

The block-shaped counterpart to :meth:get_events: the same analyses, as one block document each rather than expanded event lists. Prefer it when reading dense per-epoch output across many analyses — the saving is in parse cost and object count (a night of staging decodes to one block rather than tens of thousands of events) rather than in compressed bytes.

There is no filter, matching the single-analysis block endpoint: a document is fetched once and sliced locally. Filtered access stays on :meth:get_events.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchGetEventBlocksRequest

Batch request with the analysis IDs

required

Returns:

Type Description
BatchGetEventBlocksResponse

Response with a block document per analysis and summary counts.

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

Example
from yousleep_common.models import BatchGetEventBlocksRequest
from yousleep_common.utils.event_blocks import blocks_to_events

response = await client.batch.get_event_blocks(
    project.id,
    BatchGetEventBlocksRequest(analysis_ids=[a.id, b.id]),
)
for entry in response.results.values():
    if entry.status == "ok" and entry.document is not None:
        events = blocks_to_events(entry.document.blocks)

get_events(project_id, request) async

Batch retrieve events for multiple analyses.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchGetEventsRequest

Batch event retrieval request with analysis IDs and optional filter

required

Returns:

Type Description
BatchGetEventsResponse

Response with per-analysis event results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

get_recordings_by_studies(project_id, request) async

Fetch the recordings of many studies in one request, keyed by study.

get_recordings_details(project_id, request) async

Batch fetch recording details for multiple recordings.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchGetRecordingsDetailsRequest

Batch details request with recording IDs

required

Returns:

Type Description
BatchGetRecordingsDetailsResponse

Response with per-recording detail results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

get_studies_by_ids(project_id, request) async

Fetch many studies by id in one request (per-item results).

patch_channels(project_id, request) async

Bulk-edit channel metadata (type/unit/name) across a project.

patch_studies_metadata(project_id, request) async

Apply subject-metadata patches (age/sex/BMI) across many studies.

Rows address studies by exact name or id. Field PRESENCE is the PATCH semantics — this method serializes with exclude_unset so an absent field leaves the study unchanged and an explicit None clears it.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project.

required
request BatchPatchStudiesMetadataRequest

The metadata patch rows.

required

Returns:

Type Description
BatchPatchStudiesMetadataResponse

Per-item 207 results plus a summary.

quote_analyses(project_id, request) async

Pre-flight cost quote for a batch submission (same request body).

Runs the submission's own validation/pricing per (target, step) and returns per-step costs plus the batch total against the org balance. Advisory: the real submission's reserve remains the gate.

Parameters:

Name Type Description Default
project_id UUID | str

The project the targets belong to.

required
request BatchSubmitAnalysesRequest

The same pipeline/targets body you would submit.

required

Returns:

Type Description
BatchAnalysesQuote

BatchAnalysesQuote with per-step results, the total, and the

BatchAnalysesQuote

drain-order preview / blocked_reason for the batch total.

set_study_lights(project_id, request) async

Assign lights-off/on markers across many studies.

Each marker takes exactly one spelling: clock ("23:15", resolved per study with overnight wrap — only while the study's recording span is ≤ 24 h), datetime (read in the recording's wall-clock frame), or elapsed_ms. Existing markers win unless replace_existing; an explicit None deletes a marker (exclude_unset serialization, as for the metadata patch).

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project.

required
request BatchSetStudyLightsRequest

The lights assignment rows.

required

Returns:

Type Description
BatchSetStudyLightsResponse

Per-item 207 results (resolved instants echoed as elapsed ms).

submit_analyses(project_id, request) async

Batch submit analyses for multiple recordings with pipeline support.

Each pipeline step can depend on earlier steps via step_ids. If a step fails for a target, downstream steps auto-fail.

Parameters:

Name Type Description Default
project_id UUID | str

UUID or name of the project

required
request BatchSubmitAnalysesRequest

Batch analysis submission request with pipeline and targets

required

Returns:

Type Description
BatchSubmitAnalysesResponse

Response with per-item results and summary counts

Raises:

Type Description
NotFoundError

If project doesn't exist

ValidationError

If pipeline structure is invalid

AuthenticationError

If not authenticated

Example
from yousleep_common.models import (
    BatchSubmitAnalysesRequest,
    BatchAnalysisPipelineStep,
    BatchAnalysisTarget,
)

request = BatchSubmitAnalysesRequest(
    pipeline=[
        BatchAnalysisPipelineStep(
            step_id="staging",
            analysis_config_id="u-sleep-research-v1",
        ),
    ],
    targets=[
        BatchAnalysisTarget(study_id=study_id, recording_id=rec_id),
    ],
)
result = await client.batch.submit_analyses(project_id, request)