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.
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)