Async tasks & results
Quote a task, submit it safely, follow progress and download the result.
Get a quote
Section titled “Get a quote”Use a confirmed asset and a tool from the catalog. The example uses image-sr with a 2× scale. To process a prior version, include sourceVersionId; otherwise the original is used. fitToLimits: true permits proportional downscaling to tool limits when applicable.
This request is read-only and does not charge credits. A non-null problem means the selection cannot currently be submitted. A valid quote returns quoteId, expiresAt and the integer costCredits. Quotes do not reserve balance or compute capacity.
/api/v1/tasks/quoteRequest body fields · application/json
assetIdstringrequiredfitToLimitsbooleanoptionalmaxCostCreditsinteger · int64optionalminimum: 0
paramsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
quoteIdstringoptionalrushbooleanoptionalsourceVersionIdstringoptionaltoolIdstringrequireduseImagePackbooleanoptional
Request example
curl --include --fail-with-body --silent --show-error --max-time 60 \ --request POST 'https://app.berserkapi.com/api/v1/tasks/quote' \ --header "Authorization: Bearer $GLACIER_API_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}'// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks/quote', { method: 'POST', headers: { Authorization: `Bearer ${key}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}), signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}headers["Content-Type"] = "application/json"request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks/quote", method="POST", headers=headers, data="""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}""".encode("utf-8"),)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "strings" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } req, err := http.NewRequest("POST", "https://app.berserkapi.com/api/v1/tasks/quote", strings.NewReader(`{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}`)) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) req.Header.Set("Content-Type", "application/json") client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::POST, "https://app.berserkapi.com/api/v1/tasks/quote") .bearer_auth(env::var("GLACIER_API_KEY")?) .header("Content-Type", "application/json") .body(r#"{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}"#) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks/quote")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}""")) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://app.berserkapi.com/api/v1/tasks/quote");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);request.Content = new StringContent("""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }}""", Encoding.UTF8, "application/json");using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 200
balanceCreditsinteger · int64requiredcanFitbooleanrequiredcostCreditsinteger · int64requiredexpiresAtstring | null · date-timerequiredfixedCreditsinteger · int64requiredimageUnitsinteger · int64requiredminCreditsinteger · int64requiredneedsTopupbooleanrequiredoutputHeightinteger · int64requiredoutputWidthinteger · int64requiredpriceIdstring | nullrequiredproblemstring | nullrequiredquoteIdstring | nullrequiredresizedbooleanrequiredunitCreditsinteger · int64requiredunitDivisorinteger · int64requiredunitSizeinteger · int64requiredunitsMilliinteger · int64requiredusesFreeRushbooleanrequired
Submit the task
Section titled “Submit the task”Replace QUOTE_ID with the quote you just received, keeping the same asset, source version, tool, parameters and fit-to-limits setting. Within its validity window the quote locks the price; expired or mismatched quotes return 409. One quote creates at most one task. maxCostCredits can additionally cap the charge.
Set GLACIER_IDEMPOTENCY_KEY to a unique value for this logical task (for example, a UUID). Save the key and exact request body before sending. Reuse both on retries, including after restarting your process. Create a new key only for an intentionally new task. The allowed characters are letters, digits, ., _, : and -, with a maximum length of 128.
Success returns 202 Accepted, not a completed image. Credits are precharged atomically with task creation. The response includes id, status, urls.status, urls.result, urls.cancel, plus Location and Retry-After: 2 headers. A network timeout only stops your client’s wait; it does not cancel the server task.
/api/v1/tasksPath, query and headers
| Parameter | Location | Type & constraints |
|---|---|---|
Idempotency-Keyrequired | header | stringminLength: 1 · maxLength: 128 · pattern: "^[A-Za-z0-9._:-]+$" |
Request body fields · application/json
assetIdstringrequiredfitToLimitsbooleanoptionalmaxCostCreditsinteger · int64optionalminimum: 0
paramsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
quoteIdstringoptionalrushbooleanoptionalsourceVersionIdstringoptionaltoolIdstringrequireduseImagePackbooleanoptional
Request example
# Set GLACIER_IDEMPOTENCY_KEY once per logical task; reuse it AND the body on retries.curl --include --fail-with-body --silent --show-error --max-time 60 \ --request POST 'https://app.berserkapi.com/api/v1/tasks' \ --header "Authorization: Bearer $GLACIER_API_KEY" \ --header "Idempotency-Key: $GLACIER_IDEMPOTENCY_KEY" \ --header 'Content-Type: application/json' \ --data-raw '{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}'// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const idempotencyKey = process.env.GLACIER_IDEMPOTENCY_KEY;if (!idempotencyKey) throw new Error('Set a stable GLACIER_IDEMPOTENCY_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks', { method: 'POST', headers: { Authorization: `Bearer ${key}`, 'Idempotency-Key': idempotencyKey, 'Content-Type': 'application/json', }, body: JSON.stringify({ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}), signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}headers["Idempotency-Key"] = os.environ["GLACIER_IDEMPOTENCY_KEY"]headers["Content-Type"] = "application/json"request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks", method="POST", headers=headers, data="""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}""".encode("utf-8"),)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "strings" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } idem := os.Getenv("GLACIER_IDEMPOTENCY_KEY") if idem == "" { panic("Set a stable GLACIER_IDEMPOTENCY_KEY") } req, err := http.NewRequest("POST", "https://app.berserkapi.com/api/v1/tasks", strings.NewReader(`{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}`)) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) req.Header.Set("Idempotency-Key", idem) req.Header.Set("Content-Type", "application/json") client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::POST, "https://app.berserkapi.com/api/v1/tasks") .bearer_auth(env::var("GLACIER_API_KEY")?) .header("Idempotency-Key", env::var("GLACIER_IDEMPOTENCY_KEY")?) .header("Content-Type", "application/json") .body(r#"{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}"#) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .header("Idempotency-Key", Objects.requireNonNull(System.getenv("GLACIER_IDEMPOTENCY_KEY"))) .header("Content-Type", "application/json") .method("POST", HttpRequest.BodyPublishers.ofString("""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}""")) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://app.berserkapi.com/api/v1/tasks");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);request.Headers.Add("Idempotency-Key", Environment.GetEnvironmentVariable("GLACIER_IDEMPOTENCY_KEY") ?? throw new InvalidOperationException("Set a stable GLACIER_IDEMPOTENCY_KEY"));request.Content = new StringContent("""{ "assetId": "ASSET_ID", "toolId": "image-sr", "params": { "type": "scale", "value": 2 }, "quoteId": "QUOTE_ID"}""", Encoding.UTF8, "application/json");using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 202
assetIdstringrequiredassetNamestringrequiredcostCreditsinteger · int64requiredcreatedAtstring · date-timerequiredenginestringrequirederrorstring | nullrequiredfinishedAtstring | null · date-timerequiredidstringrequiredmaskPreviewUrlstring | nullrequiredmodelLoadingbooleanrequiredoutputVersionDeletedbooleanrequiredoutputVersionIdstring | nullrequiredoutputVersionIndexinteger | null · int64requiredparamsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
processingStartProgressnumber · doublerequiredprocessingStartedAtstring | null · date-timerequiredprogressnumber · doublerequiredqueuePositioninteger | null · int64requiredqueueRunninginteger | null · int64requiredreportobjectrequiredExpand fields / variants
degradedbooleanrequireddetectorsobject[]requiredExpand fields / variants
idstringrequiredmarginnumber | null · doublerequired
modelVersionstringrequiredprobabilitynumber · doublerequiredminimum: 0 · maximum: 1
scorenumber | null · doublerequiredminimum: 0 · maximum: 100
thresholdnumber · doublerequiredminimum: 0 · maximum: 1
verdict"ai" | "real"required
sourceVersionIdstring | nullrequiredsourceVersionIndexinteger · int64requiredstartedAtstring | null · date-timerequiredstatus"queued" | "running" | "succeeded" | "failed" | "canceled"requiredtoolIdstringrequiredtoolNamestringrequiredurlsobjectrequiredExpand fields / variants
cancelstringrequiredresultstringrequiredstatusstringrequired
watermarkAnalysisbooleanrequiredwatermarkFindobjectrequiredExpand fields / variants
candidatesobject[]requiredExpand fields / variants
boxobjectrequiredExpand fields / variants
heightnumber · doublerequiredminimum: 0 · maximum: 1
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
endMsinteger | null · int64requiredevidencestring[]requiredExpand fields / variants
stringkeyframesMsinteger · int64[]requiredExpand fields / variants
integer · int64namestring | nullrequiredobjectIdinteger · int64requiredminimum: 0 · maximum: 7
startMsinteger · int64requiredsubtitlebooleanrequiredthumbnailstring | nullrequiredmaxLength: 65536
modelVersionstringrequired
watermarkRevisionbooleanrequired
Response headers: Location, Retry-After
Poll progress
Section titled “Poll progress”Call this endpoint using the returned id, or resolve urls.status against the site origin (it already starts with /api/v1; do not append it to the API base a second time). Respect Retry-After; the suggested interval is two seconds. Stop polling on a terminal state. progress ranges from 0 to 1; queue position and timestamps may be null.
| State | Next step |
|---|---|
queued |
Wait for compute; keep polling |
running |
Processing; keep polling |
succeeded |
Fetch the result |
failed |
Read the task error; no output is available |
canceled |
Processing stopped; do not fetch a result |
/api/v1/tasks/{taskId}Path, query and headers
| Parameter | Location | Type & constraints |
|---|---|---|
taskIdrequired | path | string |
Request example
curl --include --fail-with-body --silent --show-error --max-time 60 \ --request GET 'https://app.berserkapi.com/api/v1/tasks/TASK_ID' \ --header "Authorization: Bearer $GLACIER_API_KEY"// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks/TASK_ID', { method: 'GET', headers: { Authorization: `Bearer ${key}`, }, signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks/TASK_ID", method="GET", headers=headers,)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } req, err := http.NewRequest("GET", "https://app.berserkapi.com/api/v1/tasks/TASK_ID", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::GET, "https://app.berserkapi.com/api/v1/tasks/TASK_ID") .bearer_auth(env::var("GLACIER_API_KEY")?) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks/TASK_ID")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("GET"), "https://app.berserkapi.com/api/v1/tasks/TASK_ID");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 200
assetIdstringrequiredassetNamestringrequiredcostCreditsinteger · int64requiredcreatedAtstring · date-timerequiredenginestringrequirederrorstring | nullrequiredfinishedAtstring | null · date-timerequiredidstringrequiredmaskPreviewUrlstring | nullrequiredmodelLoadingbooleanrequiredoutputVersionDeletedbooleanrequiredoutputVersionIdstring | nullrequiredoutputVersionIndexinteger | null · int64requiredparamsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
processingStartProgressnumber · doublerequiredprocessingStartedAtstring | null · date-timerequiredprogressnumber · doublerequiredqueuePositioninteger | null · int64requiredqueueRunninginteger | null · int64requiredreportobjectrequiredExpand fields / variants
degradedbooleanrequireddetectorsobject[]requiredExpand fields / variants
idstringrequiredmarginnumber | null · doublerequired
modelVersionstringrequiredprobabilitynumber · doublerequiredminimum: 0 · maximum: 1
scorenumber | null · doublerequiredminimum: 0 · maximum: 100
thresholdnumber · doublerequiredminimum: 0 · maximum: 1
verdict"ai" | "real"required
sourceVersionIdstring | nullrequiredsourceVersionIndexinteger · int64requiredstartedAtstring | null · date-timerequiredstatus"queued" | "running" | "succeeded" | "failed" | "canceled"requiredtoolIdstringrequiredtoolNamestringrequiredurlsobjectrequiredExpand fields / variants
cancelstringrequiredresultstringrequiredstatusstringrequired
watermarkAnalysisbooleanrequiredwatermarkFindobjectrequiredExpand fields / variants
candidatesobject[]requiredExpand fields / variants
boxobjectrequiredExpand fields / variants
heightnumber · doublerequiredminimum: 0 · maximum: 1
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
endMsinteger | null · int64requiredevidencestring[]requiredExpand fields / variants
stringkeyframesMsinteger · int64[]requiredExpand fields / variants
integer · int64namestring | nullrequiredobjectIdinteger · int64requiredminimum: 0 · maximum: 7
startMsinteger · int64requiredsubtitlebooleanrequiredthumbnailstring | nullrequiredmaxLength: 65536
modelVersionstringrequired
watermarkRevisionbooleanrequired
Response headers: Location, Retry-After
Retrieve and download results
Section titled “Retrieve and download results”Call only after success. File tasks return an output version with downloadUrl. Download that signed URL without an API key. Detection and watermark helper tasks may instead return report, watermarkFind or maskPreviewUrl, with output: null; check the field before accessing it. watermarkAnalysisUrl is an API path and does require the API key.
urlExpiresAt indicates when this set of signed URLs expires. Call this result endpoint again to refresh them without another processing charge. A task not yet successful returns 409; deleted output returns 410.
/api/v1/tasks/{taskId}/resultPath, query and headers
| Parameter | Location | Type & constraints |
|---|---|---|
taskIdrequired | path | string |
Request example
curl --include --fail-with-body --silent --show-error --max-time 60 \ --request GET 'https://app.berserkapi.com/api/v1/tasks/TASK_ID/result' \ --header "Authorization: Bearer $GLACIER_API_KEY"// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks/TASK_ID/result', { method: 'GET', headers: { Authorization: `Bearer ${key}`, }, signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks/TASK_ID/result", method="GET", headers=headers,)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } req, err := http.NewRequest("GET", "https://app.berserkapi.com/api/v1/tasks/TASK_ID/result", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::GET, "https://app.berserkapi.com/api/v1/tasks/TASK_ID/result") .bearer_auth(env::var("GLACIER_API_KEY")?) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks/TASK_ID/result")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("GET"), "https://app.berserkapi.com/api/v1/tasks/TASK_ID/result");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 200
maskPreviewUrlstring | nullrequiredoutputobjectrequiredExpand fields / variants
assetIdstringrequiredcreatedAtstring · date-timerequireddownloadUrlstringrequireddurationMsinteger | null · int64requiredframeCountinteger | null · int64requiredframeRatenumber | null · doublerequiredheightinteger · int64requiredidstringrequiredindexinteger · int64requiredlabelstringrequiredmaskUrlstring | nullrequiredmimeTypestringrequiredpreviewPendingbooleanrequiredpreviewUrlstring | nullrequiredsizeBytesinteger · int64requiredsourceVersionIdstring | nullrequiredthumbnailUrlstring | nullrequiredtoolIdstring | nullrequiredurlstringrequiredwatermarkMarksobject[]requiredExpand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
watermarkObjectsobject[]requiredExpand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
widthinteger · int64required
reportobjectrequiredExpand fields / variants
degradedbooleanrequireddetectorsobject[]requiredExpand fields / variants
idstringrequiredmarginnumber | null · doublerequired
modelVersionstringrequiredprobabilitynumber · doublerequiredminimum: 0 · maximum: 1
scorenumber | null · doublerequiredminimum: 0 · maximum: 100
thresholdnumber · doublerequiredminimum: 0 · maximum: 1
verdict"ai" | "real"required
status"queued" | "running" | "succeeded" | "failed" | "canceled"requiredtaskIdstringrequiredurlExpiresAtstring | null · date-timerequiredwatermarkAnalysisUrlstring | nullrequiredwatermarkFindobjectrequiredExpand fields / variants
candidatesobject[]requiredExpand fields / variants
boxobjectrequiredExpand fields / variants
heightnumber · doublerequiredminimum: 0 · maximum: 1
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
endMsinteger | null · int64requiredevidencestring[]requiredExpand fields / variants
stringkeyframesMsinteger · int64[]requiredExpand fields / variants
integer · int64namestring | nullrequiredobjectIdinteger · int64requiredminimum: 0 · maximum: 7
startMsinteger · int64requiredsubtitlebooleanrequiredthumbnailstring | nullrequiredmaxLength: 65536
modelVersionstringrequired
Query task history
Section titled “Query task history”Filter with assetId, toolId and status. limit defaults to 50 and supports up to 200; this endpoint has no cursor pagination. Use your saved task IDs to poll individual jobs.
/api/v1/tasksPath, query and headers
| Parameter | Location | Type & constraints |
|---|---|---|
assetIdoptional | query | string |
toolIdoptional | query | string |
statusoptional | query | "queued" | "running" | "succeeded" | "failed" | "canceled" |
limitoptional | query | integer · int64minimum: 1 · maximum: 200 · default: 50 |
Request example
curl --include --fail-with-body --silent --show-error --max-time 60 \ --request GET 'https://app.berserkapi.com/api/v1/tasks?limit=20' \ --header "Authorization: Bearer $GLACIER_API_KEY"// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks?limit=20', { method: 'GET', headers: { Authorization: `Bearer ${key}`, }, signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks?limit=20", method="GET", headers=headers,)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } req, err := http.NewRequest("GET", "https://app.berserkapi.com/api/v1/tasks?limit=20", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::GET, "https://app.berserkapi.com/api/v1/tasks?limit=20") .bearer_auth(env::var("GLACIER_API_KEY")?) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks?limit=20")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .method("GET", HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("GET"), "https://app.berserkapi.com/api/v1/tasks?limit=20");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 200
assetIdstringrequiredassetNamestringrequiredcostCreditsinteger · int64requiredcreatedAtstring · date-timerequiredenginestringrequirederrorstring | nullrequiredfinishedAtstring | null · date-timerequiredidstringrequiredmaskPreviewUrlstring | nullrequiredmodelLoadingbooleanrequiredoutputVersionDeletedbooleanrequiredoutputVersionIdstring | nullrequiredoutputVersionIndexinteger | null · int64requiredparamsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
processingStartProgressnumber · doublerequiredprocessingStartedAtstring | null · date-timerequiredprogressnumber · doublerequiredqueuePositioninteger | null · int64requiredqueueRunninginteger | null · int64requiredreportobjectrequiredExpand fields / variants
degradedbooleanrequireddetectorsobject[]requiredExpand fields / variants
idstringrequiredmarginnumber | null · doublerequired
modelVersionstringrequiredprobabilitynumber · doublerequiredminimum: 0 · maximum: 1
scorenumber | null · doublerequiredminimum: 0 · maximum: 100
thresholdnumber · doublerequiredminimum: 0 · maximum: 1
verdict"ai" | "real"required
sourceVersionIdstring | nullrequiredsourceVersionIndexinteger · int64requiredstartedAtstring | null · date-timerequiredstatus"queued" | "running" | "succeeded" | "failed" | "canceled"requiredtoolIdstringrequiredtoolNamestringrequiredwatermarkAnalysisbooleanrequiredwatermarkFindobjectrequiredExpand fields / variants
candidatesobject[]requiredExpand fields / variants
boxobjectrequiredExpand fields / variants
heightnumber · doublerequiredminimum: 0 · maximum: 1
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
endMsinteger | null · int64requiredevidencestring[]requiredExpand fields / variants
stringkeyframesMsinteger · int64[]requiredExpand fields / variants
integer · int64namestring | nullrequiredobjectIdinteger · int64requiredminimum: 0 · maximum: 7
startMsinteger · int64requiredsubtitlebooleanrequiredthumbnailstring | nullrequiredmaxLength: 65536
modelVersionstringrequired
watermarkRevisionbooleanrequired
Cancel a task
Section titled “Cancel a task”Cancellation is idempotent. Queued tasks cancel immediately; running tasks wait for worker acknowledgement. Continue checking the state because a task can finish before cancellation reaches it. Failed or canceled tasks follow the normal refund rules. Canceling a successful task does not refund it.
/api/v1/tasks/{taskId}/cancelPath, query and headers
| Parameter | Location | Type & constraints |
|---|---|---|
taskIdrequired | path | string |
Request example
curl --include --fail-with-body --silent --show-error --max-time 60 \ --request POST 'https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel' \ --header "Authorization: Bearer $GLACIER_API_KEY"// Node.js 22+; save as example.mjs, then: node example.mjsconst key = process.env.GLACIER_API_KEY;if (!key) throw new Error('Set GLACIER_API_KEY');const response = await fetch('https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel', { method: 'POST', headers: { Authorization: `Bearer ${key}`, }, signal: AbortSignal.timeout(60_000),});const text = await response.text();if (!response.ok) throw new Error(`HTTP ${response.status}: ${text}`);console.log(response.status, text);# Python 3.10+; standard library; python example.pyimport osimport urllib.requestimport urllib.error
headers = {"Authorization": "Bearer " + os.environ["GLACIER_API_KEY"]}request = urllib.request.Request( "https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel", method="POST", headers=headers,)try: with urllib.request.urlopen(request, timeout=60) as response: print(response.status, response.read().decode("utf-8"))except urllib.error.HTTPError as error: raise RuntimeError(f"HTTP {error.code}: {error.read().decode('utf-8')}") from error// Go 1.22+; go run example.gopackage main
import ( "fmt" "io" "net/http" "os" "time")
func main() { key := os.Getenv("GLACIER_API_KEY") if key == "" { panic("Set GLACIER_API_KEY") } req, err := http.NewRequest("POST", "https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer " + key) client := &http.Client{Timeout: 60 * time.Second} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := io.ReadAll(res.Body) if err != nil { panic(err) } if res.StatusCode >= 300 { panic(fmt.Sprintf("HTTP %d: %s", res.StatusCode, data)) } fmt.Println(res.StatusCode, string(data))}// cargo add reqwest@0.13 --features blocking// Save in src/main.rs, then: cargo runuse std::{env, error::Error, time::Duration};
fn main() -> Result<(), Box<dyn Error>> { let client = reqwest::blocking::Client::builder() .timeout(Duration::from_secs(60)).build()?; let response = client.request(reqwest::Method::POST, "https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel") .bearer_auth(env::var("GLACIER_API_KEY")?) .send()?; let status = response.status(); let text = response.text()?; if !status.is_success() { return Err(format!("HTTP {status}: {text}").into()); } println!("{status} {text}"); Ok(())}// Java 17+; save as Example.java, then: java Example.javaimport java.net.URI;import java.net.http.*;import java.time.Duration;import java.util.Objects;
class Example { public static void main(String[] args) throws Exception { var key = Objects.requireNonNull(System.getenv("GLACIER_API_KEY")); var client = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(30)).build(); var request = HttpRequest.newBuilder(URI.create("https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel")) .timeout(Duration.ofSeconds(60)) .header("Authorization", "Bearer " + key) .method("POST", HttpRequest.BodyPublishers.noBody()) .build(); var response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() >= 300) throw new IllegalStateException("HTTP " + response.statusCode() + ": " + response.body()); System.out.println(response.statusCode() + " " + response.body()); }}// .NET 8+; dotnet new console; replace Program.cs; dotnet runusing System;using System.Net.Http;using System.Net.Http.Headers;using System.Text;
var key = Environment.GetEnvironmentVariable("GLACIER_API_KEY") ?? throw new InvalidOperationException("Set GLACIER_API_KEY");using var client = new HttpClient { Timeout = TimeSpan.FromSeconds(60) };using var request = new HttpRequestMessage(new HttpMethod("POST"), "https://app.berserkapi.com/api/v1/tasks/TASK_ID/cancel");request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", key);using var response = await client.SendAsync(request);var text = await response.Content.ReadAsStringAsync();if (!response.IsSuccessStatusCode) throw new HttpRequestException($"HTTP {(int)response.StatusCode}: {text}");Console.WriteLine($"{(int)response.StatusCode} {text}");Response fields · 200
assetIdstringrequiredassetNamestringrequiredcostCreditsinteger · int64requiredcreatedAtstring · date-timerequiredenginestringrequirederrorstring | nullrequiredfinishedAtstring | null · date-timerequiredidstringrequiredmaskPreviewUrlstring | nullrequiredmodelLoadingbooleanrequiredoutputVersionDeletedbooleanrequiredoutputVersionIdstring | nullrequiredoutputVersionIndexinteger | null · int64requiredparamsobject | object | object | object | object | objectrequiredExpand fields / variants
Variant 1 ·
objecttype"none"required
Variant 2 ·
objecttype"scale"requiredvalueinteger · int64required
Variant 3 ·
objecttype"fps"requiredvalueinteger · int64required
Variant 4 ·
objecttype"faceProtect"requiredvaluebooleanrequired
Variant 5 ·
objecttype"regions"requiredvalueobject[]requiredminItems: 1
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
Variant 6 ·
objecttype"watermark"requiredvalueobjectrequiredExpand fields / variants
objectsobject[]optionalmaxItems: 8
Expand fields / variants
namestringrequiredminLength: 1 · maxLength: 24
objectIdinteger · int64requiredminimum: 0 · maximum: 7
regionsobject[]requiredmaxItems: 64
Expand fields / variants
colorstringoptionalpattern: "^#[0-9a-fA-F]{6}$"
endMsinteger · int64optionalminimum: 0
heightnumber · doublerequiredminimum: 0 · maximum: 1
kind"positive" | "negative" | "absent" | "suggested"optionalobjectIdinteger · int64optionalminimum: 0 · maximum: 7
strokesobject[]optionalmaxItems: 64
Expand fields / variants
pointsnumber · double[][]requiredminItems: 1 · maxItems: 4000
Expand fields / variants
number · doubleradiusnumber · doublerequiredminimum: 0 · maximum: 0.25
timeMsinteger · int64optionalminimum: 0
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
revisionIdstringoptional
processingStartProgressnumber · doublerequiredprocessingStartedAtstring | null · date-timerequiredprogressnumber · doublerequiredqueuePositioninteger | null · int64requiredqueueRunninginteger | null · int64requiredreportobjectrequiredExpand fields / variants
degradedbooleanrequireddetectorsobject[]requiredExpand fields / variants
idstringrequiredmarginnumber | null · doublerequired
modelVersionstringrequiredprobabilitynumber · doublerequiredminimum: 0 · maximum: 1
scorenumber | null · doublerequiredminimum: 0 · maximum: 100
thresholdnumber · doublerequiredminimum: 0 · maximum: 1
verdict"ai" | "real"required
sourceVersionIdstring | nullrequiredsourceVersionIndexinteger · int64requiredstartedAtstring | null · date-timerequiredstatus"queued" | "running" | "succeeded" | "failed" | "canceled"requiredtoolIdstringrequiredtoolNamestringrequiredurlsobjectrequiredExpand fields / variants
cancelstringrequiredresultstringrequiredstatusstringrequired
watermarkAnalysisbooleanrequiredwatermarkFindobjectrequiredExpand fields / variants
candidatesobject[]requiredExpand fields / variants
boxobjectrequiredExpand fields / variants
heightnumber · doublerequiredminimum: 0 · maximum: 1
widthnumber · doublerequiredminimum: 0 · maximum: 1
xnumber · doublerequiredminimum: 0 · maximum: 1
ynumber · doublerequiredminimum: 0 · maximum: 1
endMsinteger | null · int64requiredevidencestring[]requiredExpand fields / variants
stringkeyframesMsinteger · int64[]requiredExpand fields / variants
integer · int64namestring | nullrequiredobjectIdinteger · int64requiredminimum: 0 · maximum: 7
startMsinteger · int64requiredsubtitlebooleanrequiredthumbnailstring | nullrequiredmaxLength: 65536
modelVersionstringrequired
watermarkRevisionbooleanrequired
Response headers: Location, Retry-After