Skip to content

One-time results (delete on download)

By default the web Studio saves every variant to your FluidGhost Drive. The API can do the opposite: run a job whose results never touch your Drive and exist only as one-time download links that delete the moment you download them. This guide covers that flow end to end.

When to use it

Reach for ephemeral delivery when you want the result and nothing else — no archive, no cleanup, no footprint in your Drive. You uniquify a photo, pull it into your pipeline, and the link is spent. If you'd rather keep a browsable history, use drive delivery instead (see Delivery modes).

How it works

Add delivery: ephemeral to the job. Three rules govern the result's lifetime:

  1. Delete on successful download. Each variant's downloadUrl streams the bytes and, only after a fully successful transfer, deletes the object. The link is one-time.
  2. Interrupted downloads survive. If the connection drops mid-transfer, the object is not deleted — you can retry within the hour. Deletion is gated on a complete download, so a half-download never costs you the result.
  3. One-hour fallback. Anything never downloaded is purged after one hour, whichever comes first. Nothing lingers even if you never fetch it.

For a multi-copy job, each variant gets its own link and deletes on its own download — grabbing variant 0 doesn't affect variants 1 and 2.

Job (delivery: ephemeral)
├── variant 0 → downloadUrl ──(successful GET)──▶ bytes returned, object deleted
├── variant 1 → downloadUrl ──(never fetched)───▶ purged at T+1h
└── variant 2 → downloadUrl ──(GET drops mid-stream)─▶ kept; retry OK until T+1h

Submit an ephemeral job

bash
API="https://api-ghost.fluidvip.com/api"

curl -s -X POST "$API/jobs" \
  -H "Authorization: Bearer $FLUIDGHOST_KEY" \
  -F "[email protected]" \
  -F "recipeId=full-refresh" \
  -F "copies=3" \
  -F "delivery=ephemeral"
json
{ "jobId": "8f3c…", "statusUrl": "/jobs/8f3c…" }

Poll GET /jobs/{id} as usual. For ephemeral jobs, each completed variant carries a downloadUrl instead of a persistent url:

json
{
  "jobId": "8f3c…",
  "status": "completed",
  "progress": { "done": 3, "total": 3 },
  "variants": [
    { "index": 0, "status": "completed", "fileName": "IMG_4827.JPG", "downloadUrl": ".../jobs/8f3c…/download/0", "expiresAt": "2026-07-03T15:04:00Z" },
    { "index": 1, "status": "completed", "fileName": "IMG_4828.JPG", "downloadUrl": ".../jobs/8f3c…/download/1", "expiresAt": "2026-07-03T15:04:00Z" },
    { "index": 2, "status": "completed", "fileName": "IMG_4829.JPG", "downloadUrl": ".../jobs/8f3c…/download/2", "expiresAt": "2026-07-03T15:04:00Z" }
  ]
}

expiresAt is the one-hour fallback deadline for that variant.

Download each variant

Fetch the downloadUrl with your API key. A 200 returns the bytes; on success the object is deleted server-side.

bash
curl -s "$API/jobs/8f3c…/download/0" \
  -H "Authorization: Bearer $FLUIDGHOST_KEY" \
  -o IMG_4827.JPG

The response sets Content-Disposition with the variant's device-authentic fileName, so a browser or curl -OJ names the file correctly.

What you get back

StatusMeaningWhat to do
200Bytes streamed; object deleted on completion.You're done.
410 GoneAlready downloaded (or expired).The result is spent — resubmit the job if you need it again.
404 not_foundNo such job/variant, or not yours.Check the id; results also 404 after the 1h purge.

Handle retries correctly

Because deletion is gated on a successful transfer, a dropped download is safe to retry:

python
import requests

def fetch_once(url, key, path):
    with requests.get(url, headers={"Authorization": f"Bearer {key}"}, stream=True) as r:
        if r.status_code == 410:
            raise RuntimeError("already downloaded — result is spent")
        r.raise_for_status()
        with open(path, "wb") as f:
            for chunk in r.iter_content(1 << 16):
                f.write(chunk)   # object is deleted only after this completes

# a network blip raises before completion → the object still exists → retry is fine

Do not retry on a 410 — that means a previous download already completed and consumed the result. Only retry on network errors or 5xx.

Notes & limits

  • Cost is the same as drive delivery — you pay per variant for the uniquify compute, not for storage. Ephemeral just skips the Drive write.
  • No history. Ephemeral results don't appear in your Drive or the dashboard. GET /jobs still lists the job itself while it's live, but the bytes are gone once downloaded or expired.
  • Keep the ids. Once you have a downloadUrl, download promptly — there's no way to re-issue a link for a purged result. If you need durability, use drive.

FluidGhost API — part of the Fluidvip ecosystem.