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.
apiKey header where a step says so. Keep it out of your code..zip of the packaged Windows build folder, with <AppName>.exe at the top and the Pixel Streaming plugin enabled (Prepare your app in Unreal)._ only. It is the name the build gets in your Control Panel.agw.eagle3dstreaming.com is wrapped: the useful part is in data.data, and data.status is "success" when the call worked.GET https://agw.eagle3dstreaming.com/api/storage-provider
Answer: {"storageProvider": "r2"}. Continue with the steps below when it says r2.
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.
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.
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.
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.
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:
| Answer | Means |
|---|---|
| HTTP 404 | The test has not started yet - ask again |
data.uploadSystemFile.isRenamed is true | Passed - the build is ready in your Control Panel (its version becomes a number: 1, 2, ...) |
data.error is set | Failed - the text says why; you also get an email |
| anything else | Still testing - ask again |
Last updated