Quick start
- Use Account to sign in, get credits and create an API key under API access, then put the key in a
SYNTHID_API_KEYenvironment variable on your computer or server. - Place the downloadable Python helper or Node.js helper in your project. Both helpers run with built-in libraries alone. To get setup help, share https://geminiwatermarks.com/developers/synthid-api/ with your AI agent.
- Put an example below in the same folder, replace its image paths and execute it. These examples require Python 3.10+ or Node.js 22+. Supply a single path or a list of no more than 20 paths to this function.
Send as many as 20 images, each no larger than 15 MiB; the helper takes care of transferring and confirming them.
Processing an image takes 1 credit, or 0.5 credits each when you upload 5 or more. Images submitted 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://geminiwatermarks.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://geminiwatermarks.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 when confirmation of the files is complete. The wait function checks until all items reach ready or another terminal outcome. Look over warnings along with failed and not-started outcomes. Downloads preserve existing files, so select a fresh directory or different destination names.
Organize results from an image collection
When a batch represents a set of assets, preserve the connection between each source record and its returned item. That mapping is more useful than assuming every file in a collection will finish with the same outcome.
- Store the original file order and map each returned ordinal to your asset identifier. Give downloaded files distinct destination names so two similarly named sources do not collide.
- Check which items were admitted before transferring data. Balance and queue capacity can leave some files unstarted; adding funds later does not automatically start those items.
- Choose separate downloads when your application needs to update individual asset records, or a ZIP when a person needs the ready collection. Download outputs within one hour of each completion.
Keep the original files until you have checked the results and saved your chosen outputs. Review quality warnings before using an image; processing does not guarantee removal of every provenance signal.
One image with cURL
Upload one file with a direct multipart form-data request. An image status URL comes back in the response. Keep the original idempotency key for any retry of the request.
curl "https://geminiwatermarks.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://geminiwatermarks.com/api/v1/images/IMAGE_ID" \
-H "Authorization: Bearer $SYNTHID_API_KEY"
# Once state is ready, download the returned downloadUrl.
curl "https://geminiwatermarks.com/api/v1/images/IMAGE_ID/download" \
-H "Authorization: Bearer $SYNTHID_API_KEY" -o result.pngImage credits and API keys
Processing an image takes 1 credit, or 0.5 credits each when you upload 5 or more. Credits are spent only when your completed image is ready to download. Processing failures and cancellations before readiness do not use credits; completed results with quality warnings use the agreed credits.
Leave pricing out of upload requests; credit usage is assigned automatically by the service.
API keys grant access to processing with your account's image credits. Save API keys in server storage or your automation tool's secret store. A key provides neither sign-in nor payment permissions. Use Account to issue or revoke keys, with five active keys allowed. Revocation prevents further requests without removing accepted jobs from other active keys on the same account.
Half-credit uploads need 5 or more valid images with sufficient credits reserved before processing starts. If that minimum is not met, nothing processes and reserved credits return to availability. Once started, the upload keeps its credit amount per completed image despite subsequent failures or cancellations.
Eligible bonuses join your purchased credits for processing, and purchases are used before bonus credits.
Retries and interrupted uploads
The helpers make one Idempotency-Key for each operation and reuse it for up to three retries of transient failures. When restarting an interrupted operation, pass the original file list and idempotencyKey in Node.js options or idempotency_key in Python. Leave each file's contents, name and position unchanged.
Upload errors make the retry key available as error.idempotencyKey in Node.js or error.idempotency_key in Python, along with the operation ID/status URL when known. Errors for individual files are available in error.items. The helper waits for independent transfers to finish before reporting an incomplete upload. Fix the problem, then resume during the original ten-minute upload window; files already confirmed are skipped.
Changing the metadata leads to HTTP 409. Replacing an API key does not stop identical retries from reusing their existing operation. Idempotency data is kept for seven days. Items that failed terminally or were rejected must use a new operation; retries neither restart them nor repeat completed charges.
Raw HTTP: one image or a batch
POST /api/v1/images creates operations with either a single image or a batch. Use a JSON files array of 1–20 entries; one-image and multiple-image responses have the same batch structure. Using the helpers automates the steps below.
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 }
]
}- Examine ordered
itemsfornot_startedoutcomes. Both prepaid balance and queue capacity limit which images are admitted. - Submit each admitted file with PUT to its entry in
uploads, using the supplied content type. Do not pass the API key when calling the storage URL. The maximum simultaneous transfer count is two. - Make a POST request with your API key to each
confirmUrlafter the file transfer. Confirmation verifies the file and holds its charge. The admitted uploads must be confirmed before processing starts. Do this before the ten-minute window closes. - Use polling on the batch
statusUrl. Get separate ready images usingdownloadUrl, or collect all ready images withzipUrl.
Existing routes for batch status, confirmation, cancellation and ZIP all act on the operation created by the creation endpoint. Use DELETE on an image's status URL to cancel processing or delete the result. Use POST for unfinished-item cancellation at /api/v1/batches/BATCH_ID/cancel. No completed charge is reversed by deleting the result.
Polling and downloads
Wait according to pollAfterSeconds: usually 15 seconds in the queue and 5 during processing. Stop polling on zero, then look at every item. Status and download URLs are resolved relative to https://geminiwatermarks.com and require an API key. Polling cannot accelerate a job or lengthen its retention window.
Complete each image download within one hour of completion. ZIP includes ready images in a stream, without storing an additional archive. Quality-focused processing does not establish that a downloaded image is free of all provenance signals. This API version does not include webhooks.
n8n, Make and Zapier
Start a one-image upload with an HTTP request step using a secret Bearer credential and POST multipart/form-data to /api/v1/images. Send the binary file under image. Choose a stable record ID for Idempotency-Key and allow the tool to generate the multipart boundary. There is no need to send a price field.
Submit several images using the JSON creation flow and per-file PUT/confirmation described above. In n8n multipart requests, use an n8n Binary File field. Use Make's HTTP multipart file field for the upload. For Zapier, use binary multipart-capable actions or JSON creation followed by a separate binary PUT. Follow a delay with a status request and save each ready download in binary form. No specialized connector is required.
Limits and errors
- Upload at most 20 JPEG, PNG or WebP images per batch, each no larger than 15 MiB and 20 megapixels. Files must have no animation or unnormalized EXIF rotation. Single-file multipart requests have a 16 MiB total request limit, which is not an overall batch-size limit.
- An account's website and API uploads share a limit of one unfinished batch, with up to 200 outstanding images admitted to the processing queue.
- Across its API keys, an account may send six creation requests and 120 other API requests each minute. Repeated attempts also count. Use the delay specified by
Retry-Afterwith 429 and 503 responses. - Finish uploads within ten minutes; processing admission lasts six hours and each completed result is downloadable for one hour. Batch access lasts for two hours past the processing deadline.
Each error supplies a stable code and readable error. Use these HTTP status meanings: 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. Credentials and signed URLs stay out of the helpers' code-based error reports.
Your GET /api/v1/account response includes availableCredits, creditsPerImage and bulkCreditsPerImage, plus backward-compatible cent fields. To inspect the full request and response definitions, download the OpenAPI specification.