Skip to content

recordings

Recording endpoint handlers.

RecordingsEndpoint

Bases: BaseEndpoint

Handles recording-related API endpoints.

Recordings are sleep study files (EDF, EDF+, etc.) associated with studies.

__init__(client)

Hold the parent client, and the policies of the studies uploaded to.

add_in_place(project_id, key, header_bytes, full_file_size, filename, *, folder=None) async

Add the bucket's file at key as a recording, from its cleaned header.

register_in_place reads and cleans the header first; send only a header cleaned by the project's rule.

Parameters:

Name Type Description Default
project_id UUID | str

A project whose recordings are in its organisation's bucket.

required
key str

The file's key in the bucket.

required
header_bytes bytes

The file's EDF header, cleaned by the project's rule.

required
full_file_size int

The file's size in bytes.

required
filename str

The name the recording carries; its study takes it without its extension.

required
folder str | None

The folder the file was chosen from; the file's own folder if not given.

None

Returns:

Type Description
RecordingOut

The registered recording.

delete(recording_id) async

Delete a recording.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording to delete

required

Returns:

Type Description
MessageResponse

Message confirming deletion

Raises:

Type Description
NotFoundError

If recording doesn't exist

AuthenticationError

If not authenticated

download_url(recording_id) async

Get a pre-signed download URL for a recording file.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required

Returns:

Type Description
PreSignedDownloadUrl

Pre-signed download URL with expiry information

Raises:

Type Description
NotFoundError

If recording doesn't exist

AuthenticationError

If not authenticated

finalize(recording_id) async

Finalize a recording after upload.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required

Returns:

Type Description
RecordingOut

Finalized recording information

Raises:

Type Description
NotFoundError

If recording doesn't exist

ValidationError

If recording cannot be finalized

AuthenticationError

If not authenticated

get(recording_id) async

Get detailed information about a recording.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required

Returns:

Type Description
RecordingOut

Detailed recording information including header data

Raises:

Type Description
NotFoundError

If recording doesn't exist

AuthenticationError

If not authenticated

get_channel(recording_id, channel_index) async

Get a specific channel by index.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required
channel_index int

Index of the channel

required

Returns:

Type Description
ChannelOut

Channel information

Raises:

Type Description
NotFoundError

If recording or channel doesn't exist

AuthenticationError

If not authenticated

Example
channel = await client.recordings.get_channel(
    recording_id=recording.id,
    channel_index=0
)
print(f"{channel.name} ({channel.type}): {channel.sample_rate} Hz")

get_events(recording_id) async

Get all events for a recording across all analyses.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required

Returns:

Type Description
list[Event]

List of events from all analyses on this recording

Raises:

Type Description
NotFoundError

If recording doesn't exist

AuthenticationError

If not authenticated

list(study_id, *, offset=None, limit=None) async

List the recordings of a study.

With neither offset nor limit every recording is returned.

Parameters:

Name Type Description Default
study_id UUID | str

UUID of the study

required
offset int | None

Recordings to skip

None
limit int | None

Maximum recordings to return (1-500)

None

Returns:

Type Description
list[RecordingOut]

List of recordings

Raises:

Type Description
NotFoundError

If study doesn't exist

AuthenticationError

If not authenticated

list_channels(recording_id) async

List all channels in a recording.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required

Returns:

Type Description
list[ChannelOut]

List of channels with metadata

Raises:

Type Description
NotFoundError

If recording doesn't exist

AuthenticationError

If not authenticated

Example
channels = await client.recordings.list_channels(
    recording_id=recording.id
)
for channel in channels:
    print(f"{channel.name} ({channel.type}): {channel.sample_rate} Hz")

list_for_project(project_id, *, offset=0, limit=50) async

List one page of a project's recordings across all of its studies.

Each recording carries its study's id and name and a summary of its analyses, so a project overview needs no request per study.

Parameters:

Name Type Description Default
project_id UUID | str

UUID of the project

required
offset int

Recordings to skip (default: 0)

0
limit int

Maximum recordings to return (default: 50, max: 200)

50

Returns:

Type Description
PaginatedRecordingsResponse

One page of recordings with the total across all pages

Raises:

Type Description
NotFoundError

If project doesn't exist

AuthenticationError

If not authenticated

Example
page = await client.recordings.list_for_project(project.id, limit=200)
for recording in page.recordings:
    print(recording.study_name, recording.original_filename)
print(f"{page.total} recordings in the project")

pre_register(study_id, header_bytes, full_file_size, filename) async

Pre-register a recording before upload.

Sends the EDF file header for server-side validation and receives a presigned PUT URL for the file.

Parameters:

Name Type Description Default
study_id UUID | str

UUID of the study

required
header_bytes bytes

EDF header bytes (extracted from the file)

required
full_file_size int

Total size of the file in bytes

required
filename str

Name of the recording file

required

Returns:

Type Description
PreRegistrationResponse

Pre-registration response with recording info and presigned PUT URL

Raises:

Type Description
NotFoundError

If study doesn't exist

AuthenticationError

If not authenticated

register_in_place(project_id, key, *, name=None, folder=None) async

Register a file a bucket project's bucket already stores, where it is.

Nothing is uploaded or copied: the file stays in the organisation's bucket, and deleting its recording only unregisters it. It: 1. Reads the file's header through a ranged GET the platform signs; the bucket answers only where the organisation's network reaches it, so run this from there. 2. Applies the project's pseudonymisation rule to the header, as an upload's is cleaned. The file in the bucket is not changed. 3. Registers the file with the cleaned header and its size, in a study of its own named after the file.

Parameters:

Name Type Description Default
project_id UUID | str

A project whose recordings are in its organisation's bucket.

required
key str

The file's key in the bucket, as client.projects.bucket_files lists it.

required
name str | None

The name the recording and its study carry; the file's own name if not given. A project that codes file names requires it: pass the code your own records map to the file.

None
folder str | None

The folder the file was chosen from, ending in /, or empty for the whole bucket: client.projects.new_bucket_files looks there again. The file's own folder if not given.

None

Returns:

Type Description
RecordingOut

The registered recording.

Raises:

Type Description
ValueError

If the file does not start with an EDF header, or the project codes file names and no name is given

ClientConnectionError

If the bucket does not answer, or refuses.

ValidationError

If the file cannot be registered: it is under youSleep/ or not an EDF file (key_not_registrable).

YouSleepClientError

If the project already has the file (already_registered).

Example
for file in await client.projects.bucket_files(project.id, "nights/"):
    await client.recordings.register_in_place(project.id, file.key)

set_channel_identity(recording_id, channel_index, patch) async

Set or clear what a channel is: the side it records and its canonical name.

A field included with a value sets it, a field included as None clears it, and a field left out keeps its value. A value set here is recorded as a person's correction, and re-reading the file's label never overwrites it.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required
channel_index int

Index of the channel

required
patch ChannelIdentityPatch

The correction (at least one field must be included)

required

Returns:

Type Description
ChannelOut

The channel as it now stands

Raises:

Type Description
NotFoundError

If recording or channel doesn't exist

ValidationError

If the canonical name or side is invalid

AuthenticationError

If not authenticated

Example
from yousleep_common.models import ChannelIdentityPatch

channel = await client.recordings.set_channel_identity(
    recording.id,
    channel_index=2,
    patch=ChannelIdentityPatch(laterality="left", canonical_name="E1"),
)
print(channel.laterality, channel.identity_source)

sign_bucket_reads(project_id, keys) async

Sign a ranged GET of each file's header in a bucket project's bucket.

register_in_place sends it, cleans the header and registers the file.

Parameters:

Name Type Description Default
project_id UUID | str

A project whose recordings are in its organisation's bucket.

required
keys list[str]

The files' keys, at most 100.

required

Returns:

Type Description
BucketReadsOut

Each key's GET of its first 64 KiB, valid for a few minutes.

update_channel_type(recording_id, channel_index, type) async

Update the type of a specific channel.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required
channel_index int

Index of the channel

required
type str

New channel type

required

Returns:

Type Description
MessageResponse

Message confirming update

Raises:

Type Description
NotFoundError

If recording or channel doesn't exist

ValidationError

If channel type is invalid

AuthenticationError

If not authenticated

update_channel_unit(recording_id, channel_index, unit) async

Update the unit of a specific channel.

Parameters:

Name Type Description Default
recording_id UUID | str

UUID of the recording

required
channel_index int

Index of the channel

required
unit str

New unit

required

Returns:

Type Description
MessageResponse

Message confirming update

Raises:

Type Description
NotFoundError

If recording or channel doesn't exist

ValidationError

If unit is invalid

AuthenticationError

If not authenticated

upload(study_id, file, on_progress=None, *, name=None) async

Upload a recording file, pseudonymised by its project's policy.

It: 1. Applies the pseudonymisation rule to the file's EDF header: the patient and recording identification fields are blanked, and the start date becomes EDF+'s unknown date if the project removes dates. Your file is not changed; only the uploaded copy is. 2. Pre-registers the recording with the API (sends the cleaned header) 3. Uploads the file, with the cleaned header, via presigned PUT 4. Finalizes the recording

Parameters:

Name Type Description Default
study_id UUID | str

UUID of the study

required
file BinaryIO | Path

File-like object or path to recording file

required
on_progress Callable[[int], None] | None

Optional callback for upload progress (percentage 0-100)

None
name str | None

The name the recording carries on the platform; the file's own name if not given. A project that codes file names requires it: pass the code your own records map to the file. The file's extension is added if the name has none.

None

Returns:

Type Description
RecordingOut

Information about the uploaded recording

Raises:

Type Description
ValueError

If the file does not start with an EDF header, or the project codes file names and no name is given

ValidationError

If file is invalid or unsupported format

NotFoundError

If study doesn't exist

AuthenticationError

If not authenticated

Example
recording = await client.recordings.upload(
    study_id=study.id,
    file=Path("recording.edf"),
)