API Get key

StaglightTools

Metadata Remover

Removes location, device, editing and AI model data from the file.

Price
2 crper run
Usual time
≈ 10 s
Model id
edit.clean

Playground

Playground

File *

Sign in to upload a file.

Sign up to run it

Change the settings: the price and the code follow. You need an account to run it.

edit.clean

No example of this model yet. These are its real settings.

# 0. Upload your file first and put the id it prints in params.
curl -s -X POST https://staglight.ai/api/v1/uploads \
  -H "Authorization: Bearer $STAGLIGHT_API_KEY" -F file=@your-file | jq -r .id

# 1. Create the job. It is charged once and refunded if it fails.
JOB_ID=$(curl -s -X POST https://staglight.ai/api/v1/jobs \
  -H "Authorization: Bearer $STAGLIGHT_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "op": "edit.clean",
    "params": {
      "file": "med_your_upload_id"
    },
    "max_credits": 2
  }' | jq -r .id)

# 2. Poll until it finishes. Each call waits up to 30 seconds.
while :; do
  JOB=$(curl -s "https://staglight.ai/api/v1/jobs/$JOB_ID?wait=30" -H "Authorization: Bearer $STAGLIGHT_API_KEY")
  case "$(echo "$JOB" | jq -r .status)" in queued|running) ;; *) break ;; esac
done

# 3. Download the result from outputs[0].download_url.
echo "$JOB" | jq '.outputs[0].download_url // .data'
import os, uuid, requests

BASE = "https://staglight.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['STAGLIGHT_API_KEY']}"}

# 0. Upload your file first and put the id it prints in params.
with open("your-file", "rb") as f:
    print(requests.post(f"{BASE}/uploads", headers=HEADERS, files={"file": f}, timeout=300).json()["id"])

# 1. Create the job. It is charged once and refunded if it fails.
r = requests.post(f"{BASE}/jobs", timeout=60,
                  headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
                  json={
                    "op": "edit.clean",
                    "params": {
                      "file": "med_your_upload_id"
                    },
                    "max_credits": 2
                  })
r.raise_for_status()
job = r.json()

# 2. Poll until it finishes. Each call waits up to 30 seconds.
while job["status"] in ("queued", "running"):
    job = requests.get(f"{BASE}/jobs/{job['id']}", headers=HEADERS,
                       params={"wait": 30}, timeout=60).json()

# 3. Download the result from outputs[0].download_url.
print(job["outputs"][0]["download_url"] if job["outputs"] else job["data"] or job["error"])
// Node 18 or newer. Save as run.mjs: top-level await needs a module.
const BASE = "https://staglight.ai/api/v1";
const headers = { Authorization: `Bearer ${process.env.STAGLIGHT_API_KEY}` };

// 0. Upload your file first and put the id it prints in params.
// const form = new FormData(); form.append('file', yourFile);
// const { id } = await (await fetch(`${BASE}/uploads`, { method: 'POST', headers, body: form })).json();

// 1. Create the job. It is charged once and refunded if it fails.
let res = await fetch(`${BASE}/jobs`, {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json", "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({
    "op": "edit.clean",
    "params": {
      "file": "med_your_upload_id"
    },
    "max_credits": 2
  }),
});
if (!res.ok) throw new Error((await res.json()).error.message);
let job = await res.json();

// 2. Poll until it finishes. Each call waits up to 30 seconds.
while (job.status === "queued" || job.status === "running") {
  job = await (await fetch(`${BASE}/jobs/${job.id}?wait=30`, { headers })).json();
}

// 3. Download the result from outputs[0].download_url.
console.log(job.outputs[0]?.download_url ?? job.data ?? job.error);
{
  "id": "job_19a2b3c4d5e6f7a8b9c0d1",
  "op": "edit.clean",
  "status": "queued",
  "credits": 2,
  "title": "",
  "params": {
    "file": "med_your_upload_id"
  },
  "progress": null,
  "outputs": [],
  "data": null,
  "error": null,
  "run_id": null,
  "source": "api",
  "created_at": "2026-11-06T12:00:00Z",
  "finished_at": null,
  "eta_seconds": 10
}

What it costs

2 cr per run. The settings do not change the price.

The playground shows the exact price for your settings. A job is charged once when it is accepted, and refunded if it fails. The price is checked again with your file before it runs.

Parameters

NameTypeDefaultAllowed
filerequiredFile media id
keep_ai_noteKeep the AI-generated note boolean false

Send these inside params. Files are media ids from POST /api/v1/uploads. View documentation

More models