Halloween sale · up to 40% off your first month + bonus credits, claimable daily

Claim it

Official BytePlus partnerBuilt on BytePlus, ByteDance's official AI platform

API

How to store and serve AI-generated video for your app

Where to keep the videos your app generates with an AI video API: copy outputs on the webhook, store them in S3, R2 or B2 and serve them over a CDN, with dated costs.

KreatorFlow6 min read
Glowing film frames streaming out of server racks in a dark data centre toward a city at dusk
On this page
  1. Short answer
  2. How to store and serve generated video, step by step
  3. What 10,000 clips cost to store and serve each month
  4. Why can't I just use the API's output URL?
  5. How do I copy a finished video into my own storage?
  6. How do I download an output from the command line?
  7. How should I serve the videos to users?
  8. How much storage does AI video need?
  9. Where should I store AI-generated video?
  10. Who runs the models behind the API?
  11. Frequently asked questions

Short answer

Treat an AI video API's output link as a download, not hosting. When a KreatorFlow video job finishes, fetch the file once from GET /v1/jobs/{id}/output with your API key, copy it into your own object storage (Amazon S3, Cloudflare R2 or Backblaze B2) and serve it through a CDN with long cache headers. As of October 2026 that costs a few dollars a month for most apps.

Updated:

How to store and serve generated video, step by step

  1. 1

    Listen for job.completed

    Pass a webhook_url when you create the job. When it finishes, KreatorFlow posts a signed job.completed event. Keep polling GET /v1/jobs/{id} as a fallback.

  2. 2

    Download the output once

    Fetch GET /v1/jobs/{id}/output with your API key. The endpoint streams the file privately (Cache-Control: private, no-store) and supports range requests: it is a download for your server, not a link for your users.

  3. 3

    Write it to your bucket

    Put the file into S3, R2, B2 or any S3-compatible store under a stable key such as videos/{job_id}.mp4, with the content type and a long-lived Cache-Control header.

  4. 4

    Serve it through a CDN

    Point a CDN at the bucket (CloudFront, Cloudflare or the provider's own) and give your app the CDN URL. Files never change once written, so edges can cache them for a year.

  5. 5

    Track and clean up

    Keep the job id, prompt and CDN URL in your database, delete files your users remove, and add a lifecycle rule for drafts that were never published.

What 10,000 clips cost to store and serve each month

Example: 50 GB stored and about 500 GB delivered a month (5-second clips at an assumed 8 Mbps, 10 plays each). Published list prices, US regions, before tax. Request fees are left out because this traffic stays inside each provider's free request allowance.

OptionHow it chargesMonthly cost for the example
Cloudflare R2 with Cloudflare's CDN$0.015 per GB-month (first 10 GB free), egress free$0.60
Backblaze B2 with a CDN$6.95 per TB-month, egress free up to 3x stored, then $0.01 per GB$3.85
Amazon S3 with the CloudFront Pro plan$15 a month flat (50 TB transfer, 50 GB of S3 included), then $0.023 per GB-month$15.00
Supabase Pro (Storage and its CDN)$25 a month with 100 GB storage and 250 GB cached egress, then $0.03 per GB$32.50

Sources, as checked:

Why can't I just use the API's output URL?

Because it is not built for your viewers. A finished KreatorFlow job returns providerOutputUrl and, when that link has a time limit, providerOutputExpiresAt. GET /v1/jobs/{id}/output streams the file to whoever holds your API key and marks the response private and not cacheable. That suits a server copying the file once, not an app page that thousands of people open.

KreatorFlow's developer docs say it plainly: developers fetch completed outputs with their API key and store them in their own storage. Most AI video APIs work the same way: generation links are a delivery step with limits, so production apps keep their own copy.

How do I copy a finished video into my own storage?

Do it on the webhook, once, on your server. The event's type is job.completed and its data.job carries the job id. Download the file from the output endpoint and write it to your bucket with the right headers. Save the CDN URL, not the API link, in your database.

R2, S3 and B2 all speak the S3 API, so the same code works with each: only the endpoint, keys and bucket name change.

Node.js: copy the output to S3, R2 or B2 on job.completed

// Node.js 18+: when the job.completed webhook arrives (signature already verified), copy the video into your bucket. import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; // Works with Amazon S3, Cloudflare R2 and Backblaze B2: all three speak the S3 API. const s3 = new S3Client({ region: "auto", endpoint: process.env.S3_ENDPOINT }); export async function onJobCompleted(event) { if (event.type !== "job.completed") return null; const job = event.data.job; const res = await fetch(`https://kreatorflow.ai/v1/jobs/${job.id}/output`, { headers: { Authorization: `Bearer ${process.env.KREATORFLOW_API_KEY}` }, }); if (!res.ok) throw new Error(`output ${res.status}`); await s3.send(new PutObjectCommand({ Bucket: process.env.S3_BUCKET, Key: `videos/${job.id}.mp4`, Body: Buffer.from(await res.arrayBuffer()), ContentType: res.headers.get("content-type") ?? "video/mp4", CacheControl: "public, max-age=31536000, immutable", })); return `${process.env.CDN_BASE_URL}/videos/${job.id}.mp4`; }

How do I download an output from the command line?

The output endpoint takes the same Bearer key as every other /v1 call. Use -L so redirects are followed.

curl: download a finished job

curl -L -o clip.mp4 -H "Authorization: Bearer $KREATORFLOW_API_KEY" https://kreatorflow.ai/v1/jobs/JOB_ID/output

How should I serve the videos to users?

Through a CDN in front of the bucket. Write each file once under a key that never changes (videos/{job_id}.mp4) and send Cache-Control: public, max-age=31536000, immutable so edge caches keep it. If a user edits a video, write a new key instead of overwriting the old one.

Serve MP4 (H.264 video with AAC audio) for the widest playback support, add a poster image for the player, and use preload="none" or "metadata" on pages that list many clips, so browsers do not download every video up front. For private videos, keep the bucket private and hand out short-lived signed URLs from your server.

  • Stable keys: videos/{job_id}.mp4 and posters/{job_id}.jpg
  • Long cache headers on files that never change
  • Signed URLs for private content
  • A lifecycle rule for unpublished drafts

How much storage does AI video need?

File size is bitrate times length. At an assumed average of 8 megabits per second, a 5-second clip is about 5 MB, so 10,000 clips take about 50 GB. Your real bitrate depends on resolution and motion: check the Content-Length header of a few downloads and use your own figure.

Delivery usually costs more than storage. If each clip is watched 10 times a month, those 50 GB turn into about 500 GB of delivery a month, which is why free or flat-rate egress matters more than the price per stored gigabyte.

Where should I store AI-generated video?

Any object store with a CDN in front works. The real difference is how each one charges for delivery, so choose by your traffic, not only by the storage price. The table prices the same example on each provider's published rates as of 17 October 2026, in US dollars before tax.

Who runs the models behind the API?

KreatorFlow is an official BytePlus partner. Built on BytePlus, ByteDance's official AI platform. Generation and storage are separate jobs: the API makes the video, and your storage keeps and serves it.

Frequently asked questions

Do AI video API output links expire?

Often, yes. On KreatorFlow a finished job reports providerOutputExpiresAt whenever its output link has a time limit, and the output endpoint is a private download that needs your API key. Copy the file into your own storage when the job completes.

What is the cheapest way to store and serve AI video?

For the example on this page (50 GB stored, about 500 GB delivered a month), Cloudflare R2 comes out lowest at about $0.60 a month on published prices checked on 17 October 2026, because its egress is free. Run your own numbers: the cheapest option depends on how often each video is watched.

Can I play the KreatorFlow output URL directly in my app?

Not for your users. GET /v1/jobs/{id}/output needs your API key and answers with Cache-Control: private, no-store, so it is meant for your server to download the file once, not for public playback.

Should I store videos in my database?

No. Keep the file in object storage and only the metadata in your database: job id, prompt, duration, resolution, storage key and CDN URL.

How large is a 5-second AI video?

It depends on the bitrate. At an assumed 8 Mbps, 5 seconds is about 5 MB. The Content-Length header of your own downloads gives the real figure.

Do I need a CDN for AI-generated video?

For anything public, yes. A CDN caches the file close to viewers, cuts load times and keeps your bucket's egress bill down. Files written once under a fixed key can be cached for a year.

How do I keep generated videos private?

Keep the bucket private and have your server issue short-lived signed URLs to the user who is allowed to watch. Never put your KreatorFlow API key in a browser or mobile app.

Generate with the API, store on your terms

Create video jobs on the KreatorFlow API, copy finished files to your own bucket on the webhook and serve them from your CDN.

More guides