> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nebyoulous.space/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflows

> End-to-end recipes: upload frames into an integration set, stack them, and download the master.

These recipes use `curl` and `jq` with a token in `NEBYOULOUS_TOKEN` (see
[Authentication](/api-reference/authentication)). Every request and response
shape is in the endpoint reference.

```bash theme={null}
API=https://api.nebyoulous.space
AUTH="Authorization: Bearer $NEBYOULOUS_TOKEN"
```

## Upload frames

Files never pass through the API. You ask for presigned URLs, upload straight
to storage, then tell the API the uploads finished.

**1. Create an integration set**

```bash theme={null}
SET_ID=$(curl -s "$API/integration-sets" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d '{"title": "M42 2026-04-20"}' | jq -r .integrationSet.id)
```

**2. Presign the uploads**

Send up to 500 files per call. `relativePath` is where the file lands in
the set, and `clientId` is any string you use to match results to files.

```bash theme={null}
curl -s "$API/uploads/presign-batch" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d "{\"items\": [{
    \"kind\": \"INTEGRATION\",
    \"integrationSetId\": \"$SET_ID\",
    \"relativePath\": \"lights/m42_0001.fits\",
    \"contentType\": \"application/x-fits\",
    \"contentLength\": $(stat -f%z m42_0001.fits),
    \"clientId\": \"f1\"
  }]}" > presign.json
```

Each result has `ok`, plus `assetId` and `uploadUrl` on success or `error`
on failure. One bad item doesn't fail the batch. On Linux, use
`stat -c%s` instead of `stat -f%z`.

**3. Upload to storage**

`PUT` the file to `uploadUrl` with the same `Content-Type` you presigned.
The URL expires after an hour.

```bash theme={null}
curl -s -X PUT "$(jq -r '.results[0].uploadUrl' presign.json)" \
  -H "Content-Type: application/x-fits" \
  --upload-file m42_0001.fits
```

**4. Mark the uploads complete**

```bash theme={null}
curl -s "$API/uploads/complete-batch" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d "{\"items\": [{
    \"assetId\": \"$(jq -r '.results[0].assetId' presign.json)\",
    \"sizeBytes\": $(stat -f%z m42_0001.fits),
    \"clientId\": \"f1\"
  }]}"
```

The asset's status moves from `PRESIGNED` to `UPLOADED`. Until then it
doesn't show up in the set.

> [!TIP]
>
> `nebyoulous sync` does all of this for a whole folder, with dedupe,
> batching, and resume. Reach for the API when you're building your own
> uploader.

## Stack and download the master

**1. Get a recommended config**

The API looks at the set's frames and proposes frame groups (`light`,
`dark`, `flat`, `bias`, `darkflat`) and a staged stacking `config`.

```bash theme={null}
curl -s "$API/integration-sets/$SET_ID/stack-jobs/recommend" -H "$AUTH" \
  > recommend.json
```

Edit `recommend.json` if you want different frames or settings.

**2. Submit the stack**

Only `groups` is required. The API fills in and clamps any `config` you
leave out.

```bash theme={null}
JOB_ID=$(curl -s "$API/integration-sets/$SET_ID/stack-jobs" -H "$AUTH" \
  -H "Content-Type: application/json" \
  -d "$(jq '{groups, config}' recommend.json)" | jq -r .job.id)
```

The response is `202` with the job in `PENDING`.

**3. Poll until it finishes**

```bash theme={null}
while :; do
  JOB=$(curl -s "$API/integration-sets/$SET_ID/stack-jobs/$JOB_ID" -H "$AUTH")
  STATUS=$(echo "$JOB" | jq -r .job.status)
  echo "$STATUS"
  case "$STATUS" in READY|FAILED|CANCELLED) break ;; esac
  sleep 30
done
```

A job moves through `PENDING` and `RUNNING` to `READY`, `FAILED`, or
`CANCELLED`. On `FAILED`, `job.errorMessage` says why.

**4. Download the master**

When the job is `READY`, `job.downloadUrl` is a presigned link to the
master FITS.

```bash theme={null}
curl -s -o master.fits "$(echo "$JOB" | jq -r .job.downloadUrl)"
```

Frame analysis (`/analyses`), frame QA (`/frame-qa`), and exports
(`/export-jobs`) follow the same pattern: submit, poll the job, then read the
result. See **Stacking and analysis** and **Exports** in the sidebar.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.