Skip to main content
Any message can carry attachments, on both createTicket and sendMessage, in both directions (the user sends; agent-sent media renders in the thread).

Limits

How upload works

The SDK runs a two-phase upload so bytes go straight to storage, never through the ClarioDesk API:
1

Sign

The SDK requests a presigned upload target for each file.
2

Normalize & upload

Images are normalized to JPEG client-side (this strips HEIC/EXIF and caps dimensions). The SDK then PUTs the bytes directly to Cloudflare R2, or to Cloudflare Stream for video, which transcodes to universal H.264 and produces a free poster frame.
3

Bind

On message send, the SDK binds the uploaded ids to the message. Message.attachments then carries the rendered payloads.

Progress

Each upload exposes per-tile progress so you can render a progress ring:

Sending

In React Native, pass a MediaPicker / ImageNormalizer via init({ attachments: { picker, normalizer } }), or build and upload OutgoingAttachments yourself.

Reading

Presigned GET URLs expire. If an image fails to load because its URL aged out, re-presign it:
Video playback is external in v1 on Flutter and React Native. An in-app HLS player would ship a heavy native dependency to every host, so video uses external/system playback there. The Swift SDK plays video in-app via AVPlayer (free and native on iOS). The in-app image viewer is a lightweight, zero-dependency zoomable view on all three.

iOS permission strings

The native media picker requires usage strings in your iOS app’s Info.plist: NSPhotoLibraryUsageDescription, NSCameraUsageDescription, and NSMicrophoneUsageDescription (for video). The React Native Expo config plugin can add these for you. See the RN installation guide.