Generation Endpoints
Download Videos as Zip
Endpoint:POST /api/v1/generations/download
Download the generated MP4 videos for a list of generation IDs as a single zip archive in one request. This is the batch counterpart to Get Generated Video — instead of fetching one video at a time, you pass many IDs and receive one .zip.
Authentication
All requests require an API key.
Include your API key in the Authorization header as a Bearer token:
Authorization: Bearer YOUR_API_KEY
Request Body
Send a JSON object with a videoIds array of generation IDs.
{
"videoIds": [4983, 4982, 4981]
}
ID Limit
A maximum of 100 IDs can be included in a single request. The key ids is also accepted as an alias for videoIds.
videoIds(number[], required): The IDs of the generations whose videos you want to download. These are theidvalues returned by the Bulk Generations endpoint. Duplicate IDs are de-duplicated automatically.
Query String Variant
The same archive can be requested with a GET so it can be fetched from a plain link:
GET /api/v1/generations/download?ids=4983,4982,4981
Response
- 200 OK: Returns a
application/ziparchive (streamed) containing one MP4 per ready generation. - 400 Bad Request: The request body or
idsparameter is missing or invalid. - 404 Not Found: None of the requested IDs map to a downloadable video that you own.
Response Headers
| Header | Description |
|---|---|
Content-Type | application/zip |
Content-Disposition | attachment; filename="generations-<timestamp>.zip" |
X-Skipped-Not-Ready | Comma-separated IDs that exist but whose video has not finished yet. |
X-Skipped-Not-Found | Comma-separated IDs that do not exist or are not owned by your account. |
Partial archives
Only generations that you own and that have finished processing are included in the zip. Any IDs that are still rendering or invalid are skipped — never causing the whole request to fail — and reported back in the X-Skipped-* response headers. If none of the IDs are downloadable, a 404 is returned instead of an empty archive.
File Names Inside the Archive
Each video is named from its externalId:
- If an
externalIdwas set on the generation, it is used as the file name (sanitized — any character outsidea-z,A-Z,0-9,-,_is replaced with_). Example:externalId: "mug-2"→mug-2.mp4. - If no
externalIdwas set, the file is namedgeneration-<id>.mp4. - If two files would resolve to the same name, the generation ID is appended to keep names unique, e.g.
mug-2-4982.mp4.
Tip
Set a unique externalId per generation when you submit a bulk request to get predictable, meaningful file names in the archive.
Credits
Downloading videos does not consume credits. Credits are only spent when generating videos.
Example Usage
cURL
curl -X POST "https://rotateproduct.com/api/v1/generations/download" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "videoIds": [4983, 4982, 4981] }' \
-D - \
--output generations.zip
The -D - flag prints the response headers to your terminal so you can inspect X-Skipped-Not-Ready / X-Skipped-Not-Found.
JavaScript (fetch)
const response = await fetch(
'https://rotateproduct.com/api/v1/generations/download',
{
method: 'POST',
headers: {
Authorization: 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
},
body: JSON.stringify({ videoIds: [4983, 4982, 4981] }),
},
)
const skippedNotReady = response.headers.get('X-Skipped-Not-Ready')
const skippedNotFound = response.headers.get('X-Skipped-Not-Found')
const blob = await response.blob()
// Save `blob` to disk, e.g. with the File System Access API or a download link.
Error Responses
Validation Error
{
"success": false,
"error": {
"code": 4001,
"message": "Validation failed",
"meta": {
"friendlyMessage": "Maximum 100 videoIds are allowed",
"type": "error",
"title": "Validation Error"
}
}
}
Nothing to Download
{
"success": false,
"error": {
"code": 4006,
"message": "downloadable generations not found",
"meta": {
"friendlyMessage": "downloadable generations not found",
"type": "error",
"title": "Resource Not Found",
"resource": "downloadable generations"
}
}
}
Best Practices
- Wait until generations have a
succeededstatus before requesting the archive — see Get Generation Status. IDs that are not ready are skipped. - Always inspect the
X-Skipped-*headers so you know which IDs to retry later. - Keep batches reasonable. The archive is streamed, but very large batches take longer to assemble. The hard limit is 100 IDs per request.
- Download promptly. Videos are only retained for 1 hour after creation.
FAQ
Q: What happens if some videos are still processing?
A: They are skipped and listed in the X-Skipped-Not-Ready response header. The archive still contains every video that was ready. Retry those IDs once they reach a succeeded status.
Q: Can I download videos that belong to another account?
A: No. Only generations owned by the API key making the request are included; any others are reported in X-Skipped-Not-Found.
Q: Does this cost credits?
A: No. Downloading is free — credits are only used when generating videos.
For more help, contact info@rotateproduct.com.