curl -X GET https://api.bizmori.com/api/v3/orders/ORDER_ID/download \
-H "Authorization: Bearer YOUR_API_KEY"const orderId = 'ORDER_ID';
const response = await fetch(`https://api.bizmori.com/api/v3/orders/${orderId}/download`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const { data } = await response.json();
import requests
order_id = 'ORDER_ID'
response = requests.get(
f'https://api.bizmori.com/api/v3/orders/{order_id}/download',
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()['data']
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bizmori.com/api/v3/orders/{orderId}/download",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.bizmori.com/api/v3/orders/{orderId}/download"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.bizmori.com/api/v3/orders/{orderId}/download")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bizmori.com/api/v3/orders/{orderId}/download")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/zip/1001/archive.zip?X-Amz-...",
"files": [
{
"fileId": "21",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/cat.png?X-Amz-..."
},
{
"fileId": "22",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/dog.png?X-Amz-..."
}
],
"expiresInSeconds": 3600
}
}Get order result download URLs
Issue a download URL for every output file of a completed Anti-AI or watermark embed order, plus one URL for all results, in a single call. The response has the same shape whether the watermark order was created with v2 or v3.
files[]:{ fileId, downloadUrl }for each output file. It lists the same files in the same order asresult.outputFiles[]fromGET /api/v3/orders/{orderId}, with the samefileIdvaluesarchiveUrl: one URL for all results. Always a string- Anti-AI orders and watermark embed orders created with v2: a ZIP archive of the results
- Watermark embed orders created with v3: a ZIP archive with two or more output files. With one output file, the URL of that file (the same file as
files[0].downloadUrl)
expiresInSeconds: how long the URLs are valid. 3600 seconds (1 hour) by default, shortened to the time left until the retention period ends (expiresAt) if that is sooner. Call this endpoint again for fresh URLs
Error check order (the first matching error is returned)
- The order does not exist or belongs to another account →
404 ORDER_NOT_FOUND - Watermark extract or AI Detection order →
400 ORDER_TYPE_CANT_DOWNLOAD, even after the retention period ends - The retention period has ended →
400 ORDER_EXPIRED. If the retention period cannot be determined →409 FILE_RETENTION_UNKNOWN statusis notcomplete(pending,inProgress, orfailed) →400 ORDER_NOT_COMPLETED
Changes from the previous v3 response (breaking change, 2026-10-08): the response changed from { downloadUrl, expiresInSeconds: 300 } to { archiveUrl, files, expiresInSeconds }, and Anti-AI orders and v2 watermark embed orders are now supported. URLs are valid for up to 3600 seconds instead of 300. An incomplete order returns ORDER_NOT_COMPLETED instead of VALIDATION_FAILED, and an extract order returns ORDER_TYPE_CANT_DOWNLOAD. The per-file endpoint GET /api/v3/orders/{orderId}/files/{fileId}/download was removed; use files[] instead.
Test keys (sk_test_): works for completed Anti-AI and watermark embed test orders created with the same key, whether with v2 or v3. The URLs point to sample files served from https://api.bizmori.com/api/v2/test-samples/{signedToken}, not to your processed files. An Anti-AI test order without output files returns files: [] and a sample ZIP as archiveUrl. A v3 embed test order with one output file returns that sample file as archiveUrl; other test orders return a sample ZIP. expiresInSeconds, the error codes, and the check order follow the same rules as live orders.
curl -X GET https://api.bizmori.com/api/v3/orders/ORDER_ID/download \
-H "Authorization: Bearer YOUR_API_KEY"const orderId = 'ORDER_ID';
const response = await fetch(`https://api.bizmori.com/api/v3/orders/${orderId}/download`, {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
});
const { data } = await response.json();
import requests
order_id = 'ORDER_ID'
response = requests.get(
f'https://api.bizmori.com/api/v3/orders/{order_id}/download',
headers={'Authorization': 'Bearer YOUR_API_KEY'}
)
data = response.json()['data']
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.bizmori.com/api/v3/orders/{orderId}/download",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.bizmori.com/api/v3/orders/{orderId}/download"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.bizmori.com/api/v3/orders/{orderId}/download")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.bizmori.com/api/v3/orders/{orderId}/download")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"data": {
"archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/zip/1001/archive.zip?X-Amz-...",
"files": [
{
"fileId": "21",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/cat.png?X-Amz-..."
},
{
"fileId": "22",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/dog.png?X-Amz-..."
}
],
"expiresInSeconds": 3600
}
}GET /api/v3/orders/{orderId}/files/{fileId}/download was removed. See Changes from the previous response.Response fields
| Field | Type | Description |
|---|---|---|
archiveUrl | string | One URL for all results. Always present |
files[] | array | { fileId, downloadUrl } for each output file |
expiresInSeconds | integer | How long the URLs are valid, in seconds. At most 3600 |
files[] lists the same files in the same order as result.outputFiles[] from Get order details, with the same fileId values. Use fileId to match each URL to its output file and its inputFileId.
What archiveUrl points to
| Order | archiveUrl |
|---|---|
| Anti-AI | ZIP archive of all output files |
| Watermark embed created with v2 | ZIP archive of all output files |
| Watermark embed created with v3, two or more output files | ZIP archive of all output files |
| Watermark embed created with v3, one output file | That output file, the same file as files[0].downloadUrl |
archiveUrl to a single Download button: it is either the only result file or a ZIP of all of them.
URL lifetime
The URLs are valid for 3600 seconds (1 hour). If the order’s retention period ends sooner (expiresAt), the lifetime is shortened to the time left, and expiresInSeconds reports the shorter value. Don’t store the URLs. Call this endpoint again whenever you need to download.
Examples
{
"data": {
"archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/zip/1001/archive.zip?X-Amz-...",
"files": [
{
"fileId": "21",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/cat.png?X-Amz-..."
},
{
"fileId": "22",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/dog.png?X-Amz-..."
}
],
"expiresInSeconds": 3600
}
}
{
"data": {
"archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-...",
"files": [
{
"fileId": "201",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo.png?X-Amz-..."
}
],
"expiresInSeconds": 3600
}
}
{
"data": {
"archiveUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/archive/2001.zip?X-Amz-...",
"files": [
{
"fileId": "201",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-1.png?X-Amz-..."
},
{
"fileId": "202",
"downloadUrl": "https://bucket.s3.ap-northeast-2.amazonaws.com/out/logo-2.png?X-Amz-..."
}
],
"expiresInSeconds": 3600
}
}
Download every output file
import { writeFile } from 'node:fs/promises';
const headers = { Authorization: 'Bearer YOUR_API_KEY' };
const base = `https://api.bizmori.com/api/v3/orders/${orderId}`;
const { data: order } = await (await fetch(base, { headers })).json();
const { data: download } = await (await fetch(`${base}/download`, { headers })).json();
// files[] and result.outputFiles[] share fileId values and order.
const names = new Map(order.result.outputFiles.map((file) => [file.fileId, file.fileName]));
for (const { fileId, downloadUrl } of download.files) {
const res = await fetch(downloadUrl);
await writeFile(`${fileId}-${names.get(fileId)}`, Buffer.from(await res.arrayBuffer()));
}
import requests
headers = {'Authorization': 'Bearer YOUR_API_KEY'}
base = f'https://api.bizmori.com/api/v3/orders/{order_id}'
order = requests.get(base, headers=headers).json()['data']
download = requests.get(f'{base}/download', headers=headers).json()['data']
# files[] and result.outputFiles[] share fileId values and order.
names = {f['fileId']: f['fileName'] for f in order['result']['outputFiles']}
for item in download['files']:
res = requests.get(item['downloadUrl'])
with open(f"{item['fileId']}-{names[item['fileId']]}", 'wb') as out:
out.write(res.content)
Errors
The endpoint checks for errors in this order and returns the first one that applies:| Order | Condition | HTTP | code |
|---|---|---|---|
| 1 | The order does not exist or belongs to another account | 404 | ORDER_NOT_FOUND |
| 2 | Watermark extract or AI Detection order, even after the retention period ends | 400 | ORDER_TYPE_CANT_DOWNLOAD |
| 3 | The retention period has ended | 400 | ORDER_EXPIRED |
| 3 | The retention period cannot be determined | 409 | FILE_RETENTION_UNKNOWN |
| 4 | status is pending, inProgress, or failed | 400 | ORDER_NOT_COMPLETED |
orderId format returns 400 VALIDATION_FAILED.
Changes from the previous response
On October 8, 2026, this endpoint switched to the shape above. This is a breaking change.| Previous behavior | Now |
|---|---|
Response { downloadUrl, expiresInSeconds } | { archiveUrl, files, expiresInSeconds }. archiveUrl replaces downloadUrl |
| v3 watermark embed orders only | Anti-AI orders and watermark embed orders created with v2 or v3 |
| URLs valid for 300 seconds | Up to 3600 seconds, capped by the retention period |
Incomplete order: 400 VALIDATION_FAILED | 400 ORDER_NOT_COMPLETED |
| Watermark extract and AI Detection orders: not supported | Still not supported, with a dedicated error: 400 ORDER_TYPE_CANT_DOWNLOAD |
GET /api/v3/orders/{orderId}/files/{fileId}/download for one output file | Removed. Use files[] from this endpoint |
GET /api/v2/orders/{orderId}/download still returns its previous response, unchanged.
Test keys
With ansk_test_ key, this endpoint works for completed Anti-AI and watermark embed test orders created with the same key. The URLs point to fixed sample files, not to your processed files. See Test API keys.Authorizations
Bearer API key for external client access. Live keys use the sk_ prefix; test keys use the sk_test_ prefix and support order-lifecycle testing with mock responses without processing or credit usage.
Path Parameters
Order ID
^[0-9]{1,20}$Response
A download URL for each output file and one URL for all results
Hide child attributes
Hide child attributes
One URL for all results. A ZIP archive for Anti-AI orders and v2 watermark embed orders. For v3 watermark embed orders, a ZIP archive with two or more output files, or the URL of the single output file (the same file as files[0].downloadUrl)
Download URL for each output file. Lists the same files in the same order as result.outputFiles in the order detail
How long the URLs are valid, in seconds. 3600 by default, shortened to the time left until expiresAt if that is sooner
x <= 36003600