Skip to content
Foldbun StackDocs
中Get an API keyComing soon

Background removal with a hair-level alpha matte

POST
/v1/remove-background
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.

Idempotency-Key
string
>= 1 characters <= 128 characters /^[\x21-\x7e]+$/

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.

Image and output options.

Media typeapplication/json

Background removal request.

object
model

Background removal model.

string
default: birefnet
Allowed values: birefnet
image
required

The image to process.

object
>= 1 properties <= 1 properties
id

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.

string
/^img_[0-9a-f]{64}$/
url

Reserved (later). Currently 400 unsupported.

string format: uri
/^https:///
base64

Standard base64 of a JPEG, PNG or WebP file; a data: prefix is tolerated.

string
options

Output options.

object
output

cutout: RGBA image of the subject. matte: 8-bit grayscale alpha matte.

string
default: cutout
Allowed values: cutout matte
format

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.

string
default: png
Allowed values: png webp
size

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.

integer
default: 2048 >= 64 <= 4096

Example

{
"image": {
"id": "img_3b1f0c5e9a7d42c8b6e1f0a9d8c7b6a5f4e3d2c1b0a998877665544332211000"
},
"options": {
"output": "cutout",
"format": "webp"
}
}

The cut-out or matte as a base64 image; a byte string with Accept: application/cbor.

object
id
required

Call id call_<uuid>; quote it to support.

string
model
required

Id of the model that served the call.

string
image
required

The oriented original the coordinates refer to. Absent for text-only embeddings.

object
id
required

Image handle: img_ plus the SHA-256 of the sanitized bytes.

string
/^img_[0-9a-f]{64}$/
width
required

Width of the oriented original in pixels (EXIF orientation applied).

integer
height
required

Height of the oriented original in pixels (EXIF orientation applied).

integer
bytes
required

Size of the stored image in bytes.

integer
contentType
required

Media type of the stored image (the type of the upload).

string
Allowed values: image/jpeg image/png image/webp
cost
required

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.

number
balance
required

Account balance in credits after the call (unchanged for internal accounts).

number
timing
required

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
queueMs
required

Milliseconds from submission until a GPU node took the job.

integer
processingMs
required

Milliseconds from there until the result was back.

integer
inferenceMs

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.

integer
imageFetchMs

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.

integer
serverMs

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.

integer
billing

How the call was priced.

object
lines
required

One line per priced unit of the call.

Array<object>
object
unit
required

Price-book unit, as in GET /v1/models prices[].unit (for example encode_image, prompt, refine, image).

string
quantity
required

Units used.

integer
>= 1
unitPrice
required

List price of one unit.

number
amount
required

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.

number
waived
required

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.

boolean
total
required

Price of the call (sum of the line amounts, cut down to the balance when capped).

number
charged
required

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.

boolean
pool
required

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.

string | null
allowance

Today’s (UTC) included calls of pool, counting this one. Present only when pool is set.

object
used
required

Calls used today (UTC), including this one.

integer
>= 1
limit
required

Included calls per UTC day.

integer
>= 1
capped

Present and true only when the price exceeded the balance and the debit was cut down to it.

boolean
format
required

Echoes options.format.

string
Allowed values: png webp
width
required

Width of the returned image in pixels.

integer
height
required

Height of the returned image in pixels.

integer
data
required

Base64 PNG or WebP, as format says; a byte string in CBOR responses.

string

Example

{
"image": {
"contentType": "image/jpeg"
},
"format": "png"
}

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.

Media typeapplication/json

Body of every error response.

object
error
required

The error.

object
code
required

Stable machine-readable error code. Branch on this, not on message. Listed with the HTTP statuses under Responses.

string
message
required

Human-readable explanation. The wording can change.

string
retryable
required

True when repeating the same request unchanged can succeed.

boolean
retryAfterMs
required

Suggested wait before a retry in milliseconds; 0 when there is no hint.

integer

Example

{
"error": {
"code": "model_busy",
"message": "model sam3 is busy; retry shortly",
"retryable": true,
"retryAfterMs": 5000
}
}
Retry-After
integer
>= 1

Whole seconds to wait before retrying; present on 429 and 503.

X-Request-Id
string
/^[0-9a-f]{16}$/

Server-generated request id (16 hexadecimal characters); present on every response. Quote it when contacting support.