Skip to content

Uploads

const { contentId } = await qrati.upload({
eventId: 'evt_123',
file,
caption: 'Optional caption',
onProgress: ({ loaded, total, percent }) => { /* ... */ },
});

upload() does three things in order, hidden behind that one await:

  1. create — asks Qrati for a presigned S3 URL for this file
  2. PUT — uploads the file bytes directly to S3, reporting progress
  3. complete — tells Qrati the upload finished, so it can be processed

type and the S3 content type are detected automatically from the file (magic-byte sniffing, not just the browser-reported MIME type). You can override either — see the API Reference for the full UploadParams shape.

If the S3 PUT fails, the SDK automatically tells Qrati the upload failed (fail()) before rethrowing — no orphaned “pending” record left behind. If the final complete() call itself fails, the SDK calls abort() as cleanup (this is safe even if complete() actually succeeded server-side but the response was lost — abort() on an already-completed upload is a no-op).

try {
await qrati.upload({ eventId, file });
} catch (error) {
// error is a QratiApiError (with .status and .body) if the platform
// rejected the request, or a plain Error for a network/S3-level failure.
}

Client-side, before any request is made: 25MB for images, 250MB for videos (matching the server-side limit — failing fast here saves a wasted round-trip on an oversized file).

If you want to drive each step yourself — e.g. to show your own multi-stage progress UI, or because the PUT happens somewhere upload() can’t reach — the low-level API maps 1:1 to the underlying platform routes:

const { contentId, key, uploadUrl } = await qrati.uploads.create({
eventId,
fileName: file.name,
fileSize: file.size,
rawContentType: file.type,
type: 'IMAGE',
});
// ...PUT the file to uploadUrl yourself...
await qrati.uploads.complete({ contentId, key });
// or, on failure:
await qrati.uploads.fail({ contentId });
// or, to cancel before any bytes are sent:
await qrati.uploads.abort({ contentId, key });

HEIC→JPEG preview conversion and blurhash/duration extraction aren’t part of the SDK — both exist in qrati-connect-ts only to render a preview in its UI, not to make the upload succeed. Pass dimension/blurhash/colors /duration yourself if your own UI computes them; otherwise the platform’s own processing pipeline fills them in after upload.