SynthID Removal API for Images

Use the SynthID removal API to process generated images before you review and deliver them. Upload individual assets or batches with your ChatGPTWatermarks.com balance, then check each result before publication.

Quick start

  1. Start by signing in, buying credits and creating an API key under API access, and set SYNTHID_API_KEY on your computer or server to hold the key.
  2. Put the downloadable Python helper or Node.js helper in your project. The helpers depend solely on built-in libraries. You can also share https://chatgptwatermarks.com/developers/synthid-api/ with your AI agent.
  3. Take an example below, save it in the same directory, set your image paths and run it. You will need Python 3.10+ or Node.js 22+. The function works with a single path or a list containing up to 20 paths.

Each of the 20 files in a batch can reach 15 MiB, and the helper manages their uploads and confirmations.

Allow 1 credit for each image, or 0.5 credits each when you upload 5 or more. Requests through the API use image credits and do not use your free website allowance.

Python

import os
from synthid_client import upload_images, wait_for_batch, download_result

options = {"origin": "https://chatgptwatermarks.com", "api_key": os.environ["SYNTHID_API_KEY"]}
# One path or a list of up to 20 paths; 15 MiB per image.
batch = upload_images(["image.png", "photo.jpg"], **options)
# Save these if your application needs to resume later.
print("Operation:", batch["id"], "Retry key:", batch["idempotencyKey"])
batch = wait_for_batch(batch, **options)
for item in batch["items"]:
    if item["state"] != "ready":
        print("Not ready:", item["ordinal"], item.get("code") or item["state"])
        continue
    if item.get("warning"):
        print(item["warning"])
    download_result(item["downloadUrl"], f"result-{item['ordinal'] + 1}.png", **options)

# Or download all ready images in one archive:
# download_result(batch["zipUrl"], "results.zip", **options)

Node.js

import { uploadImages, waitForBatch, downloadResult } from "./synthid-client.mjs";

const options = { origin: "https://chatgptwatermarks.com", apiKey: process.env.SYNTHID_API_KEY };
// One path or a list of up to 20 paths; 15 MiB per image.
let batch = await uploadImages(["image.png", "photo.jpg"], options);
// Save these if your application needs to resume later.
console.log("Operation:", batch.id, "Retry key:", batch.idempotencyKey);
batch = await waitForBatch(batch, options);
for (const item of batch.items) {
  if (item.state !== "ready") {
    console.log("Not ready:", item.ordinal, item.code || item.state);
    continue;
  }
  if (item.warning) console.warn(item.warning);
  await downloadResult(item.downloadUrl, "result-" + (item.ordinal + 1) + ".png", options);
}

// Or download all ready images in one archive:
// await downloadResult(batch.zipUrl, "results.zip", options);

The upload function returns only after file confirmation. The wait function then checks status until each item is ready or terminal. Inspect warnings and items marked failed or not started. Use new filenames or an empty output directory; downloads will not overwrite existing files.

Keep a review step in image delivery

An automated completion signal tells you that a downloadable result is available. For images containing small text, faces or fine artwork, keep a review step before the file is published or sent to a customer.

  1. Keep your source image alongside the returned result during review. Compare text, face details and edges at the image's original size rather than relying only on a thumbnail.
  2. Surface quality warnings in your own interface. A warning result is available for download and is charged as completed processing, so do not silently discard it or resubmit it in a loop.
  3. Let reviewers choose individual files when only part of a set is ready to use. The ZIP option is convenient for collecting the currently ready outputs into one download.

Review the downloaded image before delivery; completion does not guarantee that every visible mark or provenance signal has been removed.

One image with cURL

For one image, use a direct multipart form-data request. The response gives you a URL for the image's status. A retry of this request must keep its idempotency key.

curl "https://chatgptwatermarks.com/api/v1/images" \
  -H "Authorization: Bearer $SYNTHID_API_KEY" \
  -H "Idempotency-Key: my-upload-0001" \
  -F "image=@image.png;type=image/png"

# Poll the returned statusUrl with the same API key.
curl "https://chatgptwatermarks.com/api/v1/images/IMAGE_ID" \
  -H "Authorization: Bearer $SYNTHID_API_KEY"

# Once state is ready, download the returned downloadUrl.
curl "https://chatgptwatermarks.com/api/v1/images/IMAGE_ID/download" \
  -H "Authorization: Bearer $SYNTHID_API_KEY" -o result.png

Image credits and API keys

The masked panel shown after key creation offers both a plain-key copy and a SYNTHID_API_KEY=… entry for your environment file. Reveal or mask the secret with Show/Hide as needed. Keep the value private in server configuration rather than exposing it to browser code. You cannot retrieve it after this initial display; replace any lost key and revoke its old record.

Allow 1 credit for each image, or 0.5 credits each when you upload 5 or more. Processing uses credits only when your completed image is ready to download. Unfinished images that fail or are canceled do not consume credits; completed results with quality warnings use the agreed credits.

The credit amount comes from the service without any pricing parameter in your upload request.

The image credits in your account cover requests made with your API key. Your server or automation tool's secret store should hold your keys. API keys cannot be used to sign in or approve payments. Create up to five active API keys through Account, where you can also revoke them. A revoked key cannot make new requests, but existing jobs stay accessible to another active key on its account.

Processing at half a credit each begins only after 5 or more uploads are valid and their credits reserved. No images are processed if fewer qualify, and the credit holds are released. The credit amount per completed image stays fixed after processing begins, even if other images fail or are canceled.

Your available credits combine purchases and eligible bonuses, drawing on purchased credits before bonuses.

Retries and interrupted uploads

The helpers use one newly generated Idempotency-Key for each operation and reuse it for up to three retries of transient failures. For resuming after a restart, provide the original file list and idempotencyKey in Node.js options or idempotency_key in Python. Use the original contents, names and order of files.

Upload errors expose the original retry key as error.idempotencyKey in Node.js or error.idempotency_key in Python, along with the operation ID/status URL when known. Look for individual transfer failures in error.items. The helper reports incomplete uploads after independent transfers have finished. Address the cause and resume before the original ten-minute upload window closes; files already confirmed are skipped.

The server returns 409 for changed metadata. The existing operation is reused by identical retries, even after an API-key change. These idempotency records remain for seven days. Start a new operation for rejected items or terminal failures; retries neither restart them nor repeat completed charges.

Raw HTTP: one image or a batch

POST /api/v1/images handles creation for both one image and a batch. Pass a JSON files array of 1–20 entries; one-image and multiple-image responses have the same batch structure. The helpers above carry out the sequence for you.

POST /api/v1/images
Authorization: Bearer YOUR_API_KEY
Idempotency-Key: my-upload-0001
Content-Type: application/json

{
  "files": [
    { "filename": "image.png", "contentType": "image/png", "sizeBytes": 123456 },
    { "filename": "photo.jpg", "contentType": "image/jpeg", "sizeBytes": 234567 }
  ]
}
  1. Look through ordered items for not_started outcomes. Only images that fit your available balance and the queue's capacity are admitted.
  2. Upload each admitted file with PUT to its entry in uploads, using the supplied content type. Storage URL requests must not include your API key. Use at most two simultaneous file transfers.
  3. Use your API key to POST to each confirmUrl after its upload. Confirmation reserves the charge after validating the file. Processing can start after the admitted uploads are confirmed. The upload window for completion is ten minutes.
  4. Request status updates from the batch statusUrl. Download individual ready images via downloadUrl, or collect all ready images with zipUrl.

Use the created operation with the existing batch status, confirmation, cancellation and ZIP routes. An image's status URL accepts DELETE to cancel or delete it. Send POST to cancel unfinished items at /api/v1/batches/BATCH_ID/cancel. A completed result's deletion does not undo payment.

Polling and downloads

Set your polling interval from pollAfterSeconds: usually 15 seconds in the queue and 5 during processing. A zero value means you should stop polling and review each item. Status and download URLs use the base origin https://chatgptwatermarks.com and require an API key. Processing speed and file retention are unaffected by polling.

Download finished results before their one-hour window ends. ZIP streams all images currently ready without retaining an extra archive. The processing pipeline focuses on quality without certifying the removal of every provenance signal. No webhook support is included in this version.

n8n, Make and Zapier

When sending one image, use an HTTP request step using a secret Bearer credential and POST multipart/form-data to /api/v1/images. Map your file's binary content to image. Supply the record's stable ID for Idempotency-Key and allow the tool to generate the multipart boundary. A pricing field is unnecessary.

Multiple images use JSON creation followed by each file's PUT and confirmation. Multipart uploads in n8n need an n8n Binary File field. Select HTTP's multipart file field in Make. Zapier can use an action with binary multipart uploads, or the JSON flow plus a separate binary PUT. Add a delay before checking status, then write ready downloads as binary files. This workflow works without a dedicated connector.

Limits and errors

Errors return a stable code and readable error. HTTP status codes indicate: 400 invalid input, 401 invalid or revoked key, 402 insufficient balance, 409 conflicting idempotency data or unfinished work, 410 expiry, 429 rate/concurrency limit, and 503 unavailable processing capacity. Helper error reports use codes and do not log credentials or signed URLs.

Fetch availableCredits, creditsPerImage and bulkCreditsPerImage through GET /api/v1/account, which also keeps legacy cent fields for older clients. See all request and response schemas when you download the OpenAPI specification.