Upload a build with the REST API

Upload a packaged Windows Unreal build with plain HTTP calls, from any language or tool: six requests take the zip from your disk to a tested build in your Control Panel. This is exactly what the Automation Kit does - use the kit if you can run Node.js; use these calls if you cannot, or if you are writing your own uploader.

1Storage?answer: r2 2Start uploaduploadId, key,part size, parts 3Send partsURL per part,PUT, keep ETag 4Completeversion = filename in key 5Stream testtest launch onour machine 6Resultpassedor failedevery 30 s ALL REQUESTS GO TO https://agw.eagle3dstreaming.com (except step 3's PUTs, which go to the part URLs you are given)
Six requests, in this order. Steps 2 to 4 move the zip; step 5 starts the same test launch as a Control Panel upload; step 6 tells you when the build is ready.

Before you start

1. Ask which storage is used

GET https://agw.eagle3dstreaming.com/api/storage-provider

Answer: {"storageProvider": "r2"}. Continue with the steps below when it says r2.

2. Start the upload

POST https://agw.eagle3dstreaming.com/api/v3/us/r2-initiate-upload
Content-Type: application/json
apiKey: YOUR_API_KEY

{ "childFolder": "MyApp", "fileSize": 742191845, "domain": "upload-api.eagle3dstreaming.com" }

childFolder is your app name, fileSize the zip's size in bytes. Answer (in data.data): uploadId, key (like yourname/MyApp/uv-1-1793040491659.zip), chunkSize (bytes per part) and totalParts.

3. Send the zip in parts

Ask for upload URLs for up to six parts at a time:

POST https://agw.eagle3dstreaming.com/api/v3/us/r2-batch-part-urls
Content-Type: application/json
apiKey: YOUR_API_KEY

{ "key": "<key from step 2>", "uploadId": "<uploadId>", "partNumbers": [1, 2, 3, 4, 5, 6] }

Answer: data.data.urls = [{ "partNumber": 1, "url": "https://..." }, ...]. For each part, PUT its bytes to its URL - part n starts at byte (n - 1) × chunkSize and is chunkSize long (the last part is shorter) - with Content-Type: application/octet-stream. Keep the ETag header of each answer. A failed part can simply be sent again. Repeat until all totalParts are sent.

4. Complete the upload

POST https://agw.eagle3dstreaming.com/api/v3/us/r2-complete-upload
Content-Type: application/json
apiKey: YOUR_API_KEY

{ "key": "<key>", "uploadId": "<uploadId>", "parts": [ { "PartNumber": 1, "ETag": "\"...\"" }, ... ] }

List the parts in order. The version of this upload is the file name in key without .zip - for yourname/MyApp/uv-1-1793040491659.zip it is uv-1-1793040491659.

5. Start the stream test

POST https://agw.eagle3dstreaming.com/api/v3/st/stream-test
Content-Type: application/json

{
  "dbname": "appExeData",
  "document": "MyApp_uv-1-1793040491659",
  "apiKey": "YOUR_API_KEY",
  "isUnverified": "true",
  "appname": "MyApp",
  "version": "uv-1-1793040491659",
  "data": {
    "dateTime": "2026-10-26T20:00:00.000Z",
    "isDeleted": false,
    "appname": "MyApp",
    "version": "uv-1-1793040491659",
    "appSize": 0.69,
    "isLinuxBuild": false,
    "buildType": "Windows_UE_Build_For_PS"
  }
}

document is <appName>_<version>; appSize is the zip's size in GB. This starts the test launch: the build is unpacked on one of our machines, started, and must stream within 5 minutes. Windows builds only - a Linux build is refused.

6. Read the result

POST https://agw.eagle3dstreaming.com/api/v3/fb/get-streamtest-result
Content-Type: application/json
apiKey: YOUR_API_KEY

{ "version": "MyApp_uv-1-1793040491659" }

Ask every 30 seconds, for up to about 10 minutes:

AnswerMeans
HTTP 404The test has not started yet - ask again
data.uploadSystemFile.isRenamed is truePassed - the build is ready in your Control Panel (its version becomes a number: 1, 2, ...)
data.error is setFailed - the text says why; you also get an email
anything elseStill testing - ask again

When a step fails

Related

Last updated