# Uploading recordings

> Upload from the CLI, the Python SDK or the HTTP API, resume interrupted uploads, and follow processing.

Source: https://rayform.world/docs/guides/uploading
Last updated: 2026-10-18
Status: Rayform is in private preview. APIs, formats and the SDK described here may change before general availability.

Every upload becomes a [session](https://rayform.world/docs/concepts#sessions). Large files are sent in parts, each with its own checksum, so an interrupted upload resumes instead of starting again.

## From the command line

```bash
rayform upload recordings/kitchen_2026-10-14.mcap --site lab-2 --wait
```

```text
Uploading kitchen_2026-10-14.mcap  4.2 GB  ████████████████████  100%  38 MB/s
Verified sha256:e2d9c1…  session ses_01JA8K2M9Q
Processing  validate ✓  align ✓  reconstruct ✓  label ✓  segment ✓
Processed: 14 segments, 2 issues (run `rayform sessions show ses_01JA8K2M9Q`)
```

Upload a whole folder; files already uploaded are skipped by checksum:

```bash
rayform upload recordings/ --site lab-2 --recursive
```

## From Python

```python
session = client.sessions.upload(
    "recordings/kitchen_2026-10-14.mcap",
    site="lab-2",
    device="arm-cell-1",
    notes="afternoon light, two people",
    wait=False,
)

# Later, or from another process:
session = client.sessions.get(session.id)
session.wait(timeout=3600)
```

## With the HTTP API

The API upload is three steps: create the session, upload parts to the signed URLs it returns, then complete it.

```bash
curl https://api.rayform.world/v1/sessions \
  -H "Authorization: Bearer $RAYFORM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6f1c2a-kitchen-2026-10-14" \
  -d '{
    "site": "lab-2",
    "filename": "kitchen_2026-10-14.mcap",
    "bytes": 4512876544,
    "sha256": "e2d9c1...",
    "part_size": 67108864
  }'
```

Upload each part with `PUT` to its URL, then send the parts' ETags to complete. See [Sessions](https://rayform.world/docs/api/sessions) for the full request and response.

## Following processing

Processing time depends on length and sensors; a ten-minute recording with three cameras typically takes tens of minutes. Instead of polling, subscribe to the `session.processed` and `session.failed` [webhooks](https://rayform.world/docs/api/webhooks).

## Issues

Problems that do not stop processing are reported as `issues` on the session:

```json
{
  "issues": [
    { "code": "clock_offset_estimated", "severity": "info", "channel": "cam1/rgb", "detail": "Shifted by +18.4 ms" },
    { "code": "low_coverage", "severity": "warning", "detail": "The back wall was seen in fewer than 3 frames" }
  ]
}
```

## Deleting

Deleting a session removes the original upload and everything derived from it: segments, assets and cached exports. Slices that referenced it stop resolving.

```bash
rayform sessions delete ses_01JA8K2M9Q
```
