curl --request POST \
--url https://api.videobgremover.com/v1/jobs/{id}/refine-mask \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"op": "add",
"model": "videobgremover-pro",
"prompt": {
"mode": "text",
"text": "the left hand"
},
"edge_cleanup": {
"enabled": true,
"size": 512
}
}
'const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
op: 'add',
model: 'videobgremover-pro',
prompt: {mode: 'text', text: 'the left hand'},
edge_cleanup: {enabled: true, size: 512}
})
};
fetch('https://api.videobgremover.com/v1/jobs/{id}/refine-mask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.videobgremover.com/v1/jobs/{id}/refine-mask"
payload = {
"op": "add",
"model": "videobgremover-pro",
"prompt": {
"mode": "text",
"text": "the left hand"
},
"edge_cleanup": {
"enabled": True,
"size": 512
}
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)Refine a job's mask with a SAM3 text prompt
Stack a second SAM3 text-prompt segmentation onto a completed job’s existing mask. Use this when background removal is mostly correct but misses (or over-includes) part of the subject.
op: "add"unions the new mask onto the existing one (fills a missing region).op: "subtract"removes the new mask’s region from the existing one.
The refinement is non-destructive: the original mask is preserved and a new
versioned mask is written. On completion the job’s active mask is updated, so a
subsequent re-export (POST /v1/jobs/{id}/exports) returns the refined result in
any format. Refinement runs GPU inference and consumes credits (refunded on failure).
Only one refinement may run per job at a time, and the job must be completed.
Send an optional Idempotency-Key to retry safely. The same key and request
return the original refinement and its current status without another charge.
Reusing a key with different inputs returns 409. Keys are scoped to your account
and job and retained with the refinement record. After a terminal failure, use a
new key for a new attempt. Version numbers may have gaps after failed attempts.
curl --request POST \
--url https://api.videobgremover.com/v1/jobs/{id}/refine-mask \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"op": "add",
"model": "videobgremover-pro",
"prompt": {
"mode": "text",
"text": "the left hand"
},
"edge_cleanup": {
"enabled": true,
"size": 512
}
}
'const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
op: 'add',
model: 'videobgremover-pro',
prompt: {mode: 'text', text: 'the left hand'},
edge_cleanup: {enabled: true, size: 512}
})
};
fetch('https://api.videobgremover.com/v1/jobs/{id}/refine-mask', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.videobgremover.com/v1/jobs/{id}/refine-mask"
payload = {
"op": "add",
"model": "videobgremover-pro",
"prompt": {
"mode": "text",
"text": "the left hand"
},
"edge_cleanup": {
"enabled": True,
"size": 512
}
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)Authorizations
API key with format vbr_ followed by 32 characters
Headers
Unique request key; reuse only when retrying the same operation.
1 - 128^[\x21-\x7e]+$Path Parameters
Completed job ID to refine
Body
Show child attributes
Show child attributes
Fuse mode — union (add) or difference (subtract)
add, subtract Segmentation model (must support text prompts)
videobgremover-pro, videobgremover-original Optional VideoMaMa soft-alpha edge refinement on the fused mask (smooths the union seam). Same engine as edge_cleanup on the direct removal flow.
Show child attributes
Show child attributes
