Skip to main content

Blog

Save AI-Generated Files: From PiAPI Output URL to Durable Storage

PiAPI developer tools illustration

A completed generation task gives your application a result, but a provider-hosted URL is not your permanent media library. If users need to reopen, edit, or download a result later, copy the file into storage you control and track that copy independently from generation.

1. Read the output for the model you used

Fetch the saved task ID and require data.status to be completed before extracting files. The shape of data.output varies by model and task type. Use the relevant Get Task example; do not assume every response has one top-level image or video URL.

For example, the documented Kling response contains a works array with video resources. Other models use different fields. Store the task ID, model, task type, completion time, and selected resource index with your application job so a later retry can recover the same result.

2. Copy promptly; check retention by service

PiAPI’s Output Storage documentation describes different retention rules for different services and hosting locations. Some entries specify short retention periods; others defer to a provider’s CDN. The page also includes legacy services. Do not apply one entry’s lifetime to every current model or treat an undocumented lifetime as unlimited.

Start a background copy after completion, using a webhook or polling workflow. Persist the job before acknowledging the callback. A useful application state sequence is shown below; these storage states belong to your application, not the PiAPI task API.

generation completed → copy queued → downloading → verified → saved
                                      ↘ copy failed → retry copy

3. Verify the bytes before marking the file saved

Download from the result URL without forwarding your PiAPI API key. Restrict allowed destinations, validate redirects, and set size and time limits. Check HTTP status, actual byte count, expected media type, and basic file readability. A 200 response containing an HTML error page is not a saved video.

Write to a temporary object, calculate a checksum, and publish the final object only after validation succeeds. Use a stable key based on the task ID and resource index. Record the object key, byte count, checksum, and save time; serve your own controlled URL according to your access policy.

4. Retry storage separately from generation

If copying fails, keep the generation marked completed and retry the copy while the source remains available. Use a durable unique record so duplicate events cannot create duplicate media entries. If the URL is no longer readable, refetch the task and inspect the current output; this does not guarantee an expired file can be restored. Test duplicate events, partial downloads, and unavailable URLs before rollout.

References: Output Storage, Kling Get Task, and Webhooks. This is an application storage pattern, not a promise of archival retention by PiAPI.