Airi

Storage

Store your videos and serve them over a CDN with links that expire. You pay for what they occupy and what gets downloaded — no minimums, no monthly fee.

How it works #

Uploading a file is three calls: declare what you are about to upload, send the bytes straight to storage using the URLs we return, and complete the upload. The bytes never pass through our API — they go from the browser or your server to the bucket, with no middleman to pay for and no bottleneck.

To download, you ask for a signed URL. It is not a permanent address: it is a permission with an expiry and, if you want, with country or bandwidth restrictions. Mint one per viewer; it is served from a CDN, not from our API.

If you would rather see it than read it, the demo does exactly this with a file of yours and hands back both links to the same object — signed and unsigned — with the status code each one answers.

Why downloads do not go through us

Video is the most expensive traffic there is. Serving it from a specialised CDN costs less than serving it from any API, and that saving is exactly what the per-GB price passes on to you.

Uploading a file #

Declare the file with its size. Depending on the size we answer with a single upload or a multipart plan — you do not choose, the server does.

1. Declare
curl -X POST https://kms.airi.live/v1/storage/files \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{
    "name": "movie.mp4",
    "sizeBytes": 734003200,
    "contentType": "video/mp4",
    "customId": "movie-1234"
  }'

The response carries the file and the instructions. If mode is single, PUT to upload.url with the same Content-Type you declared. If it is multipart, cut the file into upload.partBytes chunks and PUT each one.

2. Upload (multipart)
# One part per URL. Keep the ETag from each response.
for part in "${parts[@]}"; do
  curl -X PUT --data-binary @part-$i.bin "$url" -D headers.txt
  etag=$(grep -i '^etag:' headers.txt | tr -d '"\r' | cut -d' ' -f2)
done
3. Complete
curl -X POST https://kms.airi.live/v1/storage/files/$ID/complete \
  -H "Authorization: Bearer $TOKEN" \
  -H 'content-type: application/json' \
  -d '{"parts":[{"partNumber":1,"etag":"a54..."},{"partNumber":2,"etag":"7b1..."}]}'

If something breaks mid-upload

Upload URLs expire after an hour. POST /v1/storage/files/{id}/parts issues fresh ones, free and as often as needed — it covers both resuming and retrying a single part. An upload that is never completed is cleaned up after 24 hours and costs nothing.

Serving the video #

Mint one signed URL per viewer, with the shortest expiry the use allows. Anyone holding the URL can download until it expires, so the expiry is your real control.

example
curl "https://kms.airi.live/v1/storage/files/$ID/url?expiresSeconds=600" \
  -H "Authorization: Bearer $TOKEN"

# { "url": "https://...", "expiresAt": "2026-08-02T12:34:56.000Z" }

Per-link restrictions

Every URL can carry its own conditions, and all of them are enforced at the CDN edge: whoever fails them never downloads anything, so you are never billed for it either.

ParameterEffect
expiresSeconds60 seconds to 7 days. One hour by default.
directory=trueThe permission covers the whole folder rather than one file. Required for HLS and DASH — see below.
countriesComma-separated ISO codes. Only those countries can play.
blockedCountriesComma-separated ISO codes that are refused.
speedLimitKbpsDelivery cap in KB/s, so one viewer cannot take all your bandwidth.
speedLimitAfterSecondsSeconds served uncapped before the limit applies, so playback still starts instantly.
example
curl "https://kms.airi.live/v1/storage/files/$ID/url\
?expiresSeconds=600&countries=US,CA&speedLimitKbps=4000&speedLimitAfterSeconds=5" \
  -H "Authorization: Bearer $TOKEN"

IP locking

Not offered yet. On the network we use it is a whole-zone setting rather than a per-link option, so enabling it would force every customer to supply the viewer's IP on every request. It arrives when an account can have its own CDN zone.

The delivery network #

There is nothing to buy and nothing to configure: the CDN comes with the storage. Every signed URL you issue already points at the network, and the bytes leave from whichever point of presence suits the request. That network has over 250 Tbps of capacity, so the peak on your premiere is a problem that was solved before you had it.

We serve from ten locations: Frankfurt, Paris, São Paulo, Chicago, Dallas, Los Angeles, Miami, Hong Kong, Singapore and Tokyo. Few of them, each very large, picked for throughput rather than proximity.

Why ten and not three hundred

A general-purpose CDN spreads hundreds of small nodes to shave milliseconds, because its load is tiny responses where latency is everything. Video is the opposite: large objects, long connections, and what decides the experience is sustained throughput. Ten high-egress nodes serve that better than three hundred small ones, and cost considerably less to run — that saving is exactly what shows up on your bill as $0.008 per GB everywhere in the world, with no regional surcharge.

The practical consequence is that you do not have to think about delivery at all. You can build an on-demand catalogue, a live channel, or whatever you have in mind, without sizing bandwidth, negotiating transit or reserving capacity up front.

What you pay for #

ItemPrice
Storage$0.015 per GB per month
Delivery$0.008 per GB served

Storage is charged once a day, on whatever was active at that moment. A file uploaded and deleted the same day never pays anything; one deleted today stops counting tomorrow. Delivery is charged a day later, when the CDN publishes what it served.

No minimums, no minimum file size, no commitment. A GB stored for half a month costs half.

Compared with S3 + CloudFront #

The usual way to assemble store-and-serve yourself is S3 plus CloudFront. These are their public list prices in N. Virginia — their cheapest region — against ours, checked on 2 August 2026. The comparison for the whole platform, encoding and DRM included, is on the front page.

ItemS3 + CloudFrontAiri
Storage$0.023 per GB per month$0.015
Delivery — North America and Europe$0.085 per GB$0.008
Delivery — Asia, India, South America, Oceania$0.109 – $0.120 per GB$0.008
HTTPS requests$0.0100 per 10,000Included
Regional surchargeUp to 41% more outside NA/EUNone

The request line is not a detail in video: an HLS stream is hundreds of requests per viewer-hour. At an average segment size of 1.5 MB, serving 500 TB a month is around 350 million requests — roughly $340 just to count them, before a byte moves. We do not count them.

Where they come out cheaper than us

CloudFront includes 1 TB of transfer and 10 million requests free every month, permanently. We have no free tier: we bill from the first GB. The crossover sits at roughly 1.1 TB served per month — about 858 hours of 1080p — and below that AWS is cheaper. Above it the gap opens quickly, because what dominates a video bill is delivery.

Listing, finding and deleting #

example
# List, cursor-paginated
curl "https://kms.airi.live/v1/storage/files?limit=50" -H "Authorization: Bearer $TOKEN"

# Find by your own identifier
curl "https://kms.airi.live/v1/storage/files?customId=movie-1234" -H "Authorization: Bearer $TOKEN"

# How much you store, and what the month will cost
curl "https://kms.airi.live/v1/storage/usage" -H "Authorization: Bearer $TOKEN"

# Delete
curl -X DELETE "https://kms.airi.live/v1/storage/files/$ID" -H "Authorization: Bearer $TOKEN"

The customId is yours: put the identifier your own database uses and look files up by it instead of storing ours. It is unique while the file exists — deleting frees it again.

Deleting is permanent and billed up to the day you do it. If storage does not respond, the request fails and the file is not marked deleted: a visible error beats an invoice that quietly stops counting bytes which still exist.

Permissions #

`storage:read`
List, view details, check usage and mint signed URLs.
`storage:write`
Upload, complete uploads and delete.

Create separate credentials for whatever only reads. The backend handing links to your viewers has no need to delete anything, and a credential with fewer permissions is one that leaks with fewer consequences.