Adult filters
for your apps
One endpoint. Eleven presets. Send a photo, get a finished result back — at whatever volume your platform runs at.
Built to run in production
uncloth.app is an image transformation API for platforms that need generated imagery as a dependable part of their product, not as an experiment. You send a photo and the preset you want. We return the finished result.
Everything behind the endpoint is ours to operate — capacity, queueing, delivery and recovery. Your integration is a single authenticated HTTP call and, if you want live progress, one WebSocket connection.
Nothing about the request depends on how busy we are. The same call behaves the same way on your first day and at peak load.
One photo, every preset
Every result below came from the same source photograph, changing nothing but the preset id in the request.






Are you 18 or older?
These are unretouched results produced by the API. Confirm your age to view them.
Eleven presets
Pass feature=<id> with the job. Omit it and the request falls back to undress. An unknown id is rejected with the valid list, so a typo fails loudly instead of returning the wrong image.
Four calls, start to finish
Send the photo
A multipart POST with the image, the preset and a consent confirmation. You get a job id back immediately.
Track it
Poll the job endpoint or subscribe to the WebSocket for live progress events as the work runs.
Collect the result
A finished job carries an artifact id. Fetch it with the same key and you get the image bytes.
Retry for free
Repeat the call with the same Idempotency-Key and you get the original job back. A retry never produces a second result.
The whole integration
One header authenticates every call. Every response is scoped to the client that owns the key — jobs, events and results included.
Your base URL is issued with your key.
curl -X POST https://api.uncloth.app/api/v1/jobs \
-H "X-API-Key: $UNCLOTH_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-F feature=bikini \
-F consent=confirmed \
-F image=@photo.jpg
# { "data": { "id": "job_...", "status": "queued" } }curl -H "X-API-Key: $UNCLOTH_KEY" \
https://api.uncloth.app/api/v1/jobs/JOB_ID
# { "data": { "status": "succeeded",
# "outputs": [ { "id": "art_..." } ] } }
curl -H "X-API-Key: $UNCLOTH_KEY" \
https://api.uncloth.app/api/v1/artifacts/ART_ID \
-o result.pngEngineered to keep answering
We run the capacity, the queue and the delivery path so your platform does not have to. These are commitments about how the service is built and operated.
Deleted in 10 minutes
Your image is removed from our systems 10 minutes after you receive the result. Nothing is kept for training, review or any other purpose.
99.9% availability target
The service level we design, operate and measure against, tracked at the API edge rather than on any one component.
Global infrastructure
Requests are served from distributed capacity, so demand in one region does not become a queue for everyone else.
Automatic scaling
Capacity follows load. A traffic spike changes throughput, never the shape of the API or the way your code has to call it.
Failover by default
Any single component can be drained or replaced without an interruption you have to handle. Work in flight is recovered, not lost.
Per-key isolation
A key sees only its own jobs, events and results. Responses never expose internal identifiers or infrastructure detail.
Idempotent by contract
The Idempotency-Key header makes retries safe. A repeat returns the original job instead of doing the work twice.
Durable queueing
Accepted work is recorded before it starts and recovered afterwards. A restart anywhere in the path does not drop your job.
Strict input validation
JPEG, PNG and WebP up to 20 MiB, verified by content and not just by the name or declared type of the file.
Common questions
How do I authenticate?
An X-API-Key header on REST calls. On the WebSocket the key travels in the first message after connecting, so it never appears in a URL or a proxy log.
What happens if a request times out?
Repeat it with the same Idempotency-Key. You get the original job back, and no second result is produced.
Which formats and sizes are accepted?
JPEG, PNG and WebP up to 20 MiB. The file's actual content is verified, so a renamed or mislabelled file is rejected.
Can I run several presets on one photo?
Yes. Each preset is its own job, so submit one job per preset with the same source image and track them independently.
Do I have to poll?
No. Connect to the WebSocket, authenticate, and you receive a snapshot of your recent jobs followed by live updates. Polling stays available as a fallback.
Is consent enforced?
Yes. A create call without consent=confirmed is rejected at the API boundary. It is a required field and a declaration you are accountable for.
What does it cost?
Pricing depends on volume and is quoted with access. Tell us about your platform and expected throughput and we will come back with numbers.
Do you keep my images?
Source images and results are held in private storage and served only to the key that created them. Retention terms are agreed as part of access.
Tell us what you are building
Access is granted per integration. Describe your platform, the volume you expect and how you collect consent from the people in the images, and we will send back credentials and a base URL.
No public sign-up. No self-serve keys.
