API

Sending the bytes

POST /api/uploads gives you a sessionUri. The bytes go to Google Cloud Storage directly — not through KAIROS — so a broadcast-sized file is not passing through anybody’s API. Small files can go in one PUT. Anything large should be chunked, so a dropped connection costs one chunk rather than the whole upload.

PUT <sessionUri>
Content-Range: bytes 0-16777215/734003200      # 16 MiB, a multiple of 256 KiB

308 Resume Incomplete
Range: bytes=0-16777215                        # what GCS ACTUALLY kept — resume from here

PUT <sessionUri>
Content-Range: bytes 16777216-33554431/734003200
...
200 OK                                         # the last chunk answers 200 or 201

On a 308, trust the Range header rather than your own byte count. It says how much was actually kept, which is not always how much you sent. Resuming from your own offset leaves a hole, and the upload then succeeds with a corrupt file — which is a far worse day than a failed upload.

Chunk sizes must be a multiple of 256 KiB, except the last one. 16 MiB is a good default.

Lost track after a crash? Ask, do not guess:

PUT <sessionUri>
Content-Range: bytes */734003200               # no body: "how much do you have?"

308 Resume Incomplete
Range: bytes=0-50331647                        # continue from 50331648

A session lasts a week. After that, ask for a new one — the old path is dead and nothing was created, so there is nothing to clean up.

Something here wrong or missing? Tell us — it is the kind of bug nobody reports.Back to KAIROS

KAIROS needs one cookie to keep you signed in, and remembers your light/dark choice. May we also measure which adverts bring people here, and which parts of the app get used? Those set a Google advertising cookie and a PostHog one, and refusing changes nothing about the product.

Privacy