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

# Build lifecycle

> What each build state means, what fires a webhook, and what to do when a build is rejected.

When you upload a build, it moves through a fixed set of states before going live. Each state fires a webhook so you can track progress from your own systems instead of polling the dashboard. This page is the reference for what each state means, how long it usually takes, and what to do when things fail.

## State reference

The happy path: `pending → Downloading Files → Extracting & Scanning → Saving to Repository → Distribute → Approved`. A build can also end in `Reject` if something fails along the way.

Each state corresponds to a [webhook event](/resources/api-reference/webhooks). The event fires when the build **enters** the state.

| State                   | Webhook event        | What's happening                                         | Typical duration | Why it might fail                                       |
| ----------------------- | -------------------- | -------------------------------------------------------- | ---------------- | ------------------------------------------------------- |
| `pending`               | `build.uploaded`     | Upload accepted, queued for processing.                  | \< 5 sec         | Rate limit (1 req per 2 min per user).                  |
| `Downloading Files`     | `build.downloading`  | Pulling your `.zip` from `fileUrl`.                      | 1–10 min         | URL not public, redirects to login, transfer aborted.   |
| `Extracting & Scanning` | `build.extracting`   | Unpacking and scanning for required UE files.            | 1–5 min          | Corrupt archive, missing executable, malformed package. |
| `Saving to Repository`  | `build.saving`       | Storing files in the regional build repository.          | 30 sec – 3 min   | Storage error (rare).                                   |
| `Distribute`            | `build.distributing` | Releasing the build to GPU workers.                      | 1–5 min          | Worker pool unreachable, build fails sanity check.      |
| `Approved`              | `build.approved`     | Live and ready to stream.                                | terminal state   | —                                                       |
| `Reject`                | `build.rejected`     | Failed somewhere in the pipeline; reason in `objection`. | terminal state   | —                                                       |

<Info>
  Durations are typical, not guaranteed. Large builds (close to the 24 GB soft limit, or larger if you've had it raised), slow source hosts, and busy regions all stretch the pipeline. The 24 GB cap is a soft limit — raise a [support ticket](https://dashboard.streampixel.io) if you need it bumped, no extra charges.
</Info>

## When a build sits longer than expected

Two situations are normal even though they look slow:

* **Stuck in `pending`** — the processing service is busy with other users' uploads and yours is in the queue. No action needed; it'll move on automatically.
* **Long `Downloading Files` when re-activating an older build** — older builds are moved into archive storage to save costs, and we have to retrieve them before they can stream. Retrieval takes up to 30 minutes.

<Warning>
  If a build is stuck in any state for more than **2 hours**, contact [support](mailto:support@streampixel.io) with the project ID and build name. Anything beyond that window is unusual and worth a look.
</Warning>

## Auto-release vs manual release

The `autoRelease` flag on the [Upload File API](/resources/api-reference/upload-file-api) decides what happens after `Saving to Repository`.

<Tabs>
  <Tab title="autoRelease: true (default)">
    The build automatically moves through `Distribute` and into `Approved`. Goes live as soon as it's validated.

    Use this when every successful upload should ship.
  </Tab>

  <Tab title="autoRelease: false">
    The build stops at `Saving to Repository`. To release it, call the [Distribute File API](/resources/api-reference/distribute-file-api) with the returned `uploadId`.

    Use this when you want a manual gate — staging review, scheduled releases, A/B-style rollouts.
  </Tab>
</Tabs>

```bash theme={"dark"}
curl -X POST https://api.streampixel.io/pixelStripeApi/projects/upload-file \
  -H "Content-Type: application/json" \
  -d '{
    "apiKey": "[YOUR_API_KEY]",
    "userId": "[YOUR_USER_ID]",
    "projectId": "[YOUR_PROJECT_ID]",
    "fileUrl": "https://your-bucket.s3.amazonaws.com/MyBuild.zip",
    "autoRelease": false
  }'
```

## Why a build gets rejected

When a build ends in `Reject`, the `build.rejected` webhook payload includes an `objection` field describing the cause.

| `objection` says                          | What to do                                                                               |
| ----------------------------------------- | ---------------------------------------------------------------------------------------- |
| "Failed to download file"                 | The `fileUrl` is private, returns HTML, or times out. Use a direct-download S3/GCS link. |
| "Build contains unsupported file formats" | The archive has files outside the expected UE package layout.                            |
| "Missing executable"                      | Re-package from the Unreal Editor — the expected `.exe` isn't in the folder.             |
| "Archive could not be extracted"          | Corrupt `.zip`, encrypted archive, or non-zip file renamed. Re-zip and retry.            |
| "Validation failed on worker"             | The build doesn't launch headlessly. Check Pixel Streaming plugin and command-line args. |

The full `objection` string is whatever the pipeline produced — surface it directly to your team or CI logs.

## Tracking a build's progress

<CardGroup cols={2}>
  <Card title="Dashboard" icon="gauge">
    The project's **Builds** tab shows every upload's current state, with timestamps and the rejection reason if any.
  </Card>

  <Card title="Webhooks" icon="bell" href="/resources/api-reference/webhooks">
    HTTP POSTs to your endpoint at every state transition. The recommended path for CI/CD.
  </Card>
</CardGroup>

<Warning>
  Webhook deliveries are **not retried**. If your endpoint is down when an event fires, you'll miss it. Listen for `build.approved` from the dashboard or poll the project state as a fallback.
</Warning>

## Next steps

<CardGroup cols={2}>
  <Card title="Webhooks" icon="bell" href="/resources/api-reference/webhooks">
    Wire up events that fire at each state transition.
  </Card>

  <Card title="Upload File API" icon="upload" href="/resources/api-reference/upload-file-api">
    The endpoint that kicks off the lifecycle.
  </Card>

  <Card title="Distribute File API" icon="paper-plane" href="/resources/api-reference/distribute-file-api">
    Used when `autoRelease: false`.
  </Card>

  <Card title="Uploading your build" icon="cloud-arrow-up" href="/resources/quick-start-guide/uploading-your-build">
    The dashboard path for non-automated workflows.
  </Card>
</CardGroup>
