Background removal with a hair-level alpha matte
const url = 'https://api.stack.foldbun.com/v1/remove-background';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"image":{"id":"img_3b1f0c5e9a7d42c8b6e1f0a9d8c7b6a5f4e3d2c1b0a998877665544332211000"},"options":{"output":"cutout","format":"webp"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.stack.foldbun.com/v1/remove-background \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "image": { "id": "img_3b1f0c5e9a7d42c8b6e1f0a9d8c7b6a5f4e3d2c1b0a998877665544332211000" }, "options": { "output": "cutout", "format": "webp" } }'Model birefnet (default). Billed per image.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”1 to 128 printable ASCII characters. Within an account, a key is remembered for 24 hours: repeating the request
with the same body returns the original response (header Idempotent-Replayed: true) without charging or
running the call again. The same key with a different body is 409 idempotency_conflict. See the Overview.
Request Bodyrequired
Section titled “Request Bodyrequired”Image and output options.
Background removal request.
object
Background removal model.
The image to process.
object
Handle returned by POST /v1/images (or by an earlier call): img_ plus the SHA-256 of the sanitized image. Valid only inside the uploading account.
Reserved (later). Currently 400 unsupported.
Standard base64 of a JPEG, PNG or WebP file; a data: prefix is tolerated.
Output options.
object
cutout: RGBA image of the subject. matte: 8-bit grayscale alpha matte.
Encoding of the returned image. png: lossless PNG. webp: for cutout, lossy RGB (quality 90) with a lossless alpha channel (the matte is exact); for matte, lossless WebP of the gray matte (stored as gray RGB, so every decoder shows it as gray, and the red channel is the matte). A WebP cutout is typically about 10 times smaller than the PNG (about 200 kB instead of 2 MB at 1791x1008) with no visible difference, so responses arrive faster.
Long side of the returned image, in pixels. The default is 2048. A larger image is scaled down to this long side and is never enlarged, so the long side of the result is the smaller of the long side of the input and size.
Example
{ "image": { "id": "img_3b1f0c5e9a7d42c8b6e1f0a9d8c7b6a5f4e3d2c1b0a998877665544332211000" }, "options": { "output": "cutout", "format": "webp" }}Responses
Section titled “Responses”The cut-out or matte as a base64 image; a byte string with Accept: application/cbor.
object
Call id call_<uuid>; quote it to support.
Id of the model that served the call.
The oriented original the coordinates refer to. Absent for text-only embeddings.
object
Image handle: img_ plus the SHA-256 of the sanitized bytes.
Width of the oriented original in pixels (EXIF orientation applied).
Height of the oriented original in pixels (EXIF orientation applied).
Size of the stored image in bytes.
Media type of the stored image (the type of the upload).
Credits this call charged. 0 for failed calls and calls covered by an included daily allowance. Internal accounts are metered but not debited, so cost is then the price of the call.
Account balance in credits after the call (unchanged for internal accounts).
Server-side timing of this call in milliseconds. queueMs is the time from submission until a GPU node took the job (queueing, including a re-queue after a node failure); processingMs is from there until the result was back (image fetch, inference, and the node-to-server round trips). inferenceMs, imageFetchMs and serverMs break this down further. Network time between the client and the API is not included.
object
Milliseconds from submission until a GPU node took the job.
Milliseconds from there until the result was back.
Model time on the GPU node as the node measured it, without the image fetch. Never larger than processingMs. Absent when the node did not report it.
Time the node spent obtaining the image bytes. 0 when the image was sent with the job or the node did not need it (encode cache hit). Absent when the node did not report it.
Whole time inside the API server: request received, until just before the response is written. Includes reading the request body, image preparation, admission, queueMs, processingMs and billing settlement. Absent only in an idempotent replay of a response stored by an older server.
How the call was priced.
object
One line per priced unit of the call.
object
Price-book unit, as in GET /v1/models prices[].unit (for example encode_image, prompt, refine, image).
Units used.
List price of one unit.
Price of the line: unitPrice * quantity, or 0 when waived. On a call that is not charged (trial, included daily allowance) lines still show the list price.
True for the image-encoding fee when the node already held the encoding (cache: hit); amount is then 0 and the fee that would have applied is unitPrice * quantity.
Price of the call (sum of the line amounts, cut down to the balance when capped).
Whether the account balance was debited. False for Playground trial calls and for calls covered by an included daily allowance (then pool and allowance are set); true for billed calls. Internal accounts are metered at the list price and never debited, so charged is false and total is the price.
The pool whose included daily allowance covered the call (public or free). Null for billed calls (including calls beyond the allowance), trial calls and internal accounts.
Today’s (UTC) included calls of pool, counting this one. Present only when pool is set.
object
Calls used today (UTC), including this one.
Included calls per UTC day.
Present and true only when the price exceeded the balance and the debit was cut down to it.
Echoes options.format.
Width of the returned image in pixels.
Height of the returned image in pixels.
Base64 PNG or WebP, as format says; a byte string in CBOR responses.
Example
{ "image": { "contentType": "image/jpeg" }, "format": "png"}object
Call id call_<uuid>; quote it to support.
Id of the model that served the call.
The oriented original the coordinates refer to. Absent for text-only embeddings.
object
Image handle: img_ plus the SHA-256 of the sanitized bytes.
Width of the oriented original in pixels (EXIF orientation applied).
Height of the oriented original in pixels (EXIF orientation applied).
Size of the stored image in bytes.
Media type of the stored image (the type of the upload).
Credits this call charged. 0 for failed calls and calls covered by an included daily allowance. Internal accounts are metered but not debited, so cost is then the price of the call.
Account balance in credits after the call (unchanged for internal accounts).
Server-side timing of this call in milliseconds. queueMs is the time from submission until a GPU node took the job (queueing, including a re-queue after a node failure); processingMs is from there until the result was back (image fetch, inference, and the node-to-server round trips). inferenceMs, imageFetchMs and serverMs break this down further. Network time between the client and the API is not included.
object
Milliseconds from submission until a GPU node took the job.
Milliseconds from there until the result was back.
Model time on the GPU node as the node measured it, without the image fetch. Never larger than processingMs. Absent when the node did not report it.
Time the node spent obtaining the image bytes. 0 when the image was sent with the job or the node did not need it (encode cache hit). Absent when the node did not report it.
Whole time inside the API server: request received, until just before the response is written. Includes reading the request body, image preparation, admission, queueMs, processingMs and billing settlement. Absent only in an idempotent replay of a response stored by an older server.
How the call was priced.
object
One line per priced unit of the call.
object
Price-book unit, as in GET /v1/models prices[].unit (for example encode_image, prompt, refine, image).
Units used.
List price of one unit.
Price of the line: unitPrice * quantity, or 0 when waived. On a call that is not charged (trial, included daily allowance) lines still show the list price.
True for the image-encoding fee when the node already held the encoding (cache: hit); amount is then 0 and the fee that would have applied is unitPrice * quantity.
Price of the call (sum of the line amounts, cut down to the balance when capped).
Whether the account balance was debited. False for Playground trial calls and for calls covered by an included daily allowance (then pool and allowance are set); true for billed calls. Internal accounts are metered at the list price and never debited, so charged is false and total is the price.
The pool whose included daily allowance covered the call (public or free). Null for billed calls (including calls beyond the allowance), trial calls and internal accounts.
Today’s (UTC) included calls of pool, counting this one. Present only when pool is set.
object
Calls used today (UTC), including this one.
Included calls per UTC day.
Present and true only when the price exceeded the balance and the debit was cut down to it.
Echoes options.format.
Width of the returned image in pixels.
Height of the returned image in pixels.
Base64 PNG or WebP, as format says; a byte string in CBOR responses.
default
Section titled “default”The error envelope. The HTTP status follows the code; only retryable: true errors are worth repeating
unchanged. A failed call costs 0.
| Status | Codes |
|---|---|
| 400 | invalid_request, invalid_image (the image passed the upload checks but could not be decoded), unsupported |
| 401 | unauthorized |
| 402 | insufficient_balance |
| 403 | model_locked |
| 404 | not_found, image_not_found |
| 409 | idempotency_conflict, request_in_progress |
| 413 | payload_too_large |
| 429 | rate_limited, daily_limit_reached, too_many_batches (all with Retry-After) |
| 500 | internal_error |
| 502 | upstream_error, bad_model_output |
| 503 | model_unavailable, model_busy, unavailable (all with Retry-After) |
| 504 | upstream_timeout |
model_unavailable also covers a short loss of contact with the only GPU worker serving the model: for about a
minute after the loss, interactive calls answer it at once with a short Retry-After (5 s), while sync and
batch calls stay queued until their own deadline instead of failing.
Meaning and retry guidance for each code: Errors.
Body of every error response.
object
The error.
object
Stable machine-readable error code. Branch on this, not on message. Listed with the HTTP statuses under Responses.
Human-readable explanation. The wording can change.
True when repeating the same request unchanged can succeed.
Suggested wait before a retry in milliseconds; 0 when there is no hint.
Example
{ "error": { "code": "model_busy", "message": "model sam3 is busy; retry shortly", "retryable": true, "retryAfterMs": 5000 }}Headers
Section titled “Headers”Whole seconds to wait before retrying; present on 429 and 503.
Server-generated request id (16 hexadecimal characters); present on every response. Quote it when contacting support.