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

RuleValue
Per message≤ 4 attachments
Image≤ 10 MB
Video / file≤ 50 MB

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:
// ValueListenable<double> per upload
final progress = ClarioDesk.attachmentUploadProgress(localId);

Sending

await ClarioDesk.sendMessage(
  ticketId,
  'see screenshot',
  attachments: [OutgoingAttachment.file(path)],
);
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:
refreshAttachmentUrl(attachmentId)
Video playback is external in v1. An in-app HLS player would ship a heavy native dependency to every host, so video uses external/system playback. The in-app image viewer is a lightweight, zero-dependency zoomable view.

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.