The DuupFlow API, step by step
Duplicate images and videos, compress, and remove AI detection from your own tools (scripts, Make, n8n, Zapier, AI agents). This page has everything you need to know — including for the AI assistant you ask your questions to.
Summary (for humans and AI assistants)
- REST API:
https://www.duupflow.com/api/v1, authenticated with the headerAuthorization: Bearer dflw_live_…. - Included at no extra cost in the Pro and Agency plans (not in Solo or the free plan). Unlimited duplications through the API.
- Images: immediate response (the file, or a zip). Videos: asynchronous (a job to poll, then download).
- Limits: 300 requests/min per key · 100 pending video jobs · images ≤ 25 MB (1–20 copies) · videos ≤ 150 MB and ≤ 120 s (1–10 copies).
- Video formats: mp4, mov, mkv, avi, webm — vertical 9:16 (Reels, TikTok, Shorts) is supported, resolution and quality preserved.
- Results downloadable for 16 h. Completion webhook: in development (for now, poll the job every 5–10 s).
- No free API trial; the monthly Pro plan has no commitment. A demo is available through Telegram support.
1. What the API does
The API gives you access, without going through the website, to the same processing as the DuupFlow dashboard:
- Duplicate an image into 1 to 20 unique copies (metadata, invisible pixel changes, device identity).
- Duplicate a video into 1 to 10 unique copies that look identical.
- Compress an image without ever making it heavier.
- Remove AI detection from an image, or enable it as an option on a duplication.
Typical uses: automate a multi-account publishing flow, plug DuupFlow into Make / n8n / Zapier (HTTP module), or let an AI agent (Claude Code, scripts) run duplications.
2. Access and pricing
| Plan | API access | Indicative price |
|---|---|---|
| Free / Solo | No | — |
| Pro | Yes, no extra cost | €99/month, or €70/month billed yearly |
| Agency | Yes, no extra cost | €249/month, or €176/month billed yearly |
- API duplications are unlimited on Pro and Agency — no monthly quota, no per-call cost.
- Guests of a Pro or Agency team can create their own keys.
- No free API trial. The monthly Pro plan has no commitment (cancel anytime). A personalised demo is available through Telegram support.
- Up-to-date prices are always on the Pricing page.
3. Quick start
- 1Switch to the Pro or Agency plan.
- 2In the dashboard, open Developers and click Generate a key.
- 3Copy the key right away: it is shown only once.
- 4Check it works with
GET /me(example below). - 5Run your first duplication.
curl -H "Authorization: Bearer dflw_live_YOUR_KEY" \
https://www.duupflow.com/api/v1/me{ "user_id": "…", "plan": "pro", "api_version": "v1" }4. Authentication and keys
- Every request sends the header
Authorization: Bearer dflw_live_…. - Up to 3 keys per account (one per integration, for example).
- A deleted key is disabled immediately and cannot be recovered.
- If the subscription drops below Pro or a payment is overdue, the API answers
403 plan_requireduntil it is resolved.
5. Duplicate an image
/api/v1/images/duplicateSynchronous — returns the result directly.| Field | Value | Default |
|---|---|---|
file | png, jpg, jpeg, webp, gif, heic, heif image — ≤ 25 MB | required |
count | Number of copies, 1 to 20 | 1 |
fundamentals | Metadata rewritten | 1 |
semi | Imperceptible pixel change | 1 |
visuals | Subtle visual shift | 0 |
reverse | Horizontal mirror | 0 |
iphone_meta | Realistic iPhone identity (Apple EXIF) | 0 |
country | ISO country code (e.g. FR, US) for location | — |
remove_ai_detection | Remove AI detection before duplicating | 0 |
Response: 1 copy → the image file directly; several copies → a zip archive. File names are neutral (no mention of DuupFlow).
curl -X POST https://www.duupflow.com/api/v1/images/duplicate \
-H "Authorization: Bearer dflw_live_YOUR_KEY" \
-F "file=@photo.jpg" \
-F "count=3" \
-F "iphone_meta=1" \
-o copies.zip6. Duplicate a video (asynchronous)
/api/v1/videos/duplicateAsynchronous — creates a job and answers 202 right away.| Field | Value | Default |
|---|---|---|
file | mp4, mov, mkv, avi, webm video — ≤ 150 MB and ≤ 120 s | required |
count | Number of copies, 1 to 10 | 1 |
packs | Comma-separated list: visual, motion, metadata_technical, pixel_magic | visual,motion,metadata_technical |
country | ISO country code for location metadata | — |
iphone_meta | Realistic iPhone metadata (.mov output, HEVC) | 0 |
remove_ai_detection | Invisible counter-watermark, different on every copy | 0 |
- visual: invisible micro-variations of brightness, contrast and colour.
- motion: subtle camera movement.
- metadata_technical: unique encoding parameters and technical metadata.
- pixel_magic: imperceptible noise for a unique fingerprint.
Original resolution and quality are preserved (4K included), and a copy is never heavier than the source. Vertical 9:16 is supported.
curl -X POST https://www.duupflow.com/api/v1/videos/duplicate \
-H "Authorization: Bearer dflw_live_YOUR_KEY" \
-F "file=@clip.mp4" \
-F "count=3" \
-F "packs=visual,motion,metadata_technical"{
"job_id": "3f1c…",
"status": "queued",
"poll_url": "https://www.duupflow.com/api/v1/jobs/3f1c…"
}7. Track a job and download
/api/v1/jobs/:idJob status and download links.status:queued→processing→completedorfailed.progress: 0 to 100;message: current step.- When
completed,result.fileslists every copy with itsurl. - When
failed,errorexplains why (unreadable file, too long…). - If the server is momentarily busy, the job is retried automatically (it goes back to
queued) — nothing to do on your side.
{
"id": "3f1c…",
"type": "videos.duplicate",
"status": "completed",
"progress": 100,
"message": "Done",
"result": {
"files": [
{ "name": "…_c01_….mp4", "bytes": 8123456, "url": "https://www.duupflow.com/api/v1/jobs/3f1c…/files/…_c01_….mp4" }
]
},
"error": null,
"created_at": "2026-10-29T10:00:00Z"
}/api/v1/jobs/:id/files/:nameDownloads one copy — with the same API key.curl -H "Authorization: Bearer dflw_live_YOUR_KEY" \
"https://www.duupflow.com/api/v1/jobs/JOB_ID/files/FILE_NAME" -o copy.mp48. Full example (video)
import time, requests
API = "https://www.duupflow.com/api/v1"
H = {"Authorization": "Bearer dflw_live_YOUR_KEY"}
# 1) Start the job
with open("clip.mp4", "rb") as f:
r = requests.post(f"{API}/videos/duplicate", headers=H,
files={"file": f}, data={"count": "3"})
r.raise_for_status()
job_id = r.json()["job_id"]
# 2) Poll until it's done
while True:
job = requests.get(f"{API}/jobs/{job_id}", headers=H).json()
if job["status"] in ("completed", "failed"):
break
time.sleep(8)
# 3) Download every copy
if job["status"] == "completed":
for f in job["result"]["files"]:
data = requests.get(f["url"], headers=H).content
open(f["name"], "wb").write(data)
else:
print("Failed:", job["error"])const API = "https://www.duupflow.com/api/v1";
const H = { Authorization: "Bearer dflw_live_YOUR_KEY" };
const form = new FormData();
form.append("file", new Blob([await fs.promises.readFile("clip.mp4")]), "clip.mp4");
form.append("count", "3");
const { job_id } = await (await fetch(`${API}/videos/duplicate`, { method: "POST", headers: H, body: form })).json();
let job;
do {
await new Promise((r) => setTimeout(r, 8000));
job = await (await fetch(`${API}/jobs/${job_id}`, { headers: H })).json();
} while (job.status === "queued" || job.status === "processing");
for (const f of job.result?.files ?? []) {
const buf = Buffer.from(await (await fetch(f.url, { headers: H })).arrayBuffer());
await fs.promises.writeFile(f.name, buf);
}In Make, n8n or Zapier: an HTTP "multipart/form-data" module to start the job, a loop with an 8 s delay on GET /jobs/:id, then one HTTP module per file to download it.
9. Compress an image
/api/v1/compressSynchronous — returns the compressed image.| Field | Value | Default |
|---|---|---|
file | png, jpg, jpeg, webp image — ≤ 25 MB | required |
level | light, balanced or strong | balanced |
The result is never heavier than the original (otherwise the original is returned). Savings are reported in the X-DuupFlow-Saved-Percent, X-DuupFlow-Original-Bytes and X-DuupFlow-Output-Bytes headers. Video compression through the API is not available yet.
curl -X POST https://www.duupflow.com/api/v1/compress \
-H "Authorization: Bearer dflw_live_YOUR_KEY" \
-F "file=@photo.jpg" -F "level=strong" -D headers.txt -o compressed.jpg10. Remove AI detection
/api/v1/ai-detectionSynchronous — returns the cleaned image.Erases AI provenance metadata (C2PA, XMP…) and invisibly retouches the pixels (grain, micro-blur, colours), keeping format and resolution. jpg, png or webp image ≤ 25 MB. For videos, use the remove_ai_detection option of /videos/duplicate.
curl -X POST https://www.duupflow.com/api/v1/ai-detection \
-H "Authorization: Bearer dflw_live_YOUR_KEY" \
-F "file=@image.png" -o cleaned.png11. Limits
| Item | Limit |
|---|---|
| Requests | 300 per minute per key |
| Pending video jobs | 100 per account |
| Image — size / copies | 25 MB / 1 to 20 copies |
| Video — size / duration / copies | 150 MB / 120 s / 1 to 10 copies |
| Video result retention | 16 hours |
| API keys | 3 per account |
| Duplications | Unlimited (Pro and Agency) |
12. Errors
Every error uses the same JSON format:
{ "error": { "code": "file_too_large", "message": "File exceeds the 150 MB limit." } }| HTTP | code | What to do |
|---|---|---|
| 400 | invalid_body · missing_file · read_failed | Send multipart/form-data with a file field. |
| 401 | missing_key · invalid_key | Check the Authorization header and that the key wasn't deleted. |
| 403 | plan_required | The account must be on Pro or Agency, payment up to date. |
| 404 | job_not_found · file_not_found | Wrong id, or result expired (16 h). |
| 413 | file_too_large | Bring the file under the limit. |
| 415 | unsupported_type · video_not_supported | Use an accepted format (file extension included). |
| 429 | rate_limited · too_many_jobs | Wait (Retry-After header) then retry. |
| 500 | processing_failed · store_failed | Retry; if it persists, contact support. |
13. Best practices
- Poll a job every 5 to 10 seconds, not more often.
- On 429 or 5xx: retry with an increasing delay (backoff).
- Keep the right extension in the uploaded file name: it determines the format.
- Download results as soon as the job completes (they expire after 16 h).
- One key per integration: if something goes wrong, you revoke one without breaking the others.
- Every call produces different copies: running the same source again gives new variants.
14. Webhooks
GET /jobs/:id.15. FAQ
| Question | Answer |
|---|---|
| Can everything be automated without using the website? | Yes. Once the key is created, everything goes through the API. |
| Is there a per-call cost or a quota? | No. The API is included in Pro and Agency, unlimited duplications. Only the technical limits apply (section 11). |
| Does it work with Make, n8n, Zapier? | Yes, through their HTTP module (multipart/form-data). |
| Are vertical 9:16 videos supported? | Yes, and the original resolution is preserved. |
| Can a copy be heavier than the original? | No, the bitrate is capped at the source's. |
| Can I target a "creator" (workspace) through the API? | No, the API works at account level. Creators are managed in the dashboard. |
| Can I save presets? | Just send the same parameters on every call from your script. |
| How long are files kept? | Video results 16 h. Uploaded files are deleted after processing. |
| Can I test before buying? | No free API trial; the monthly Pro plan has no commitment, and a demo is available through support. |
| Is there a webhook? | In development; for now, poll GET /jobs/:id. |
| Is AI detection removal guaranteed? | No, no tool can guarantee it (see section 10). |
| Where can I get help? | Telegram support: t.me/DuupFlow_Support. |