Skip to content

Chat Images and Files ​

Local implementation, not enabled in production

The generic attachment extension requires a coordinated gateway, Widget, workbench and SDK release, private R2 storage and a configured malware scanner. Complete real-engine acceptance before enabling customer uploads. Existing text chat and customer-directory releases are separate.

Supported Files ​

Each file must be 1 byte to 10 MiB. PNG, JPEG and WebP can be previewed after scanning. PDF, UTF-8 TXT, ZIP, DOC/DOCX, XLS/XLSX and PPT/PPTX are download-only. SVG, HTML, executables and macro-specific extensions are not accepted. Extension/signature checks are a type gate, not malware scanning or full Office container validation. The scanner must reject encrypted content, macro alerts, broken media and exceeded archive limits.

Integration ​

Use an authenticated, participant-bound Widget session or scoped Workbench session. Directory tokens must first be exchanged for a conversation session. No platform Key belongs in browser code.

CallerUpload raw bytesDownload scanned attachment
WidgetPOST /v1/apps/bot/widget/uploads?filename=receipt.pdfGET /v1/apps/bot/widget/attachments/{id}
Workbench / merchant server / administratorPOST /v1/conversations/{id}/uploads?filename=receipt.pdfGET /v1/conversations/{id}/attachments/{attachmentId}

Send Authorization: Bearer <credential> and Content-Type: application/octet-stream, not multipart. Server Keys need conversation:write for uploads and conversation:read for downloads. Tenant and conversation authorization still apply.

The upload returns HTTP 201 with data.storage_key, filename, mime_type, byte_size and scan_status: pending. Send that descriptor in the existing message endpoint's attachments array, with a stable client_message_id. An upload alone does not create a message or enqueue message-attachment scanning. Preserve the descriptor and message ID when retrying a lost message response.

Uploads do not yet have an Idempotency-Key contract. Retrying a lost upload response can create another object; unattached uploads are cleaned after seven days. Progress reaching 100% means transfer completion, not delivery or scan approval. Existing Widget/Key limits apply; honor Retry-After.

Access and Retention ​

Pending and blocked files cannot be downloaded. Missing scanners, errors or hash mismatches never produce a clean verdict. Up to eight failed attempts are made by the existing scheduled scanner; exhausted files remain isolated for operator investigation. Scans are not guaranteed to finish immediately.

Downloads recheck tenant, session, public-message recipient visibility and expiration. Internal notes and their files never reach the customer. Binary responses are private, no-store, attachment downloads with nosniff. Uploaded files are not publicly accessible R2 objects.

Messages may specify attachment expires_at. Expiration denies reads before scheduled object cleanup; otherwise the tenant conversation retention policy applies. Conversation deletion removes associated objects. Unattached objects are retained seven days for retry. Cleanup requires the scheduled task to run. Arbitrary file URLs are never fetched; existing external image import retains an exact HTTPS origin allowlist.

SDK and Operations ​

The confirmed SDK delivery exposes browser ./upload: uploadOpen4XAttachment({url,token,file,signal,onProgress}), using short-lived credentials only. The server client exposes uploadAttachment(conversationId,filename,blob) and downloadAttachment(conversationId,attachmentId). A public npm release is not implied.

Bind a private MEDIA_BUCKET. Deploy services/conversation-scanner behind authenticated HTTPS, configure CONVERSATION_SCANNER_URL and secret CONVERSATION_SCANNER_TOKEN. Staging additionally requires a tenant allowlist. Keep ClamAV private, pin image digests, update definitions, reject encrypted/over-limit content and validate with real harmless fixtures and standard antivirus test samples. See ClamAV configuration. Adapter mocks do not certify real-engine behavior. Storage/scanning prices and SLA require separate agreement.

AI Integration Prompt ​

text
Inspect this project's Open4X chat integration and add file uploads using the current attachment guide and OpenAPI.
Confirm that the target environment enables attachments. Use short-lived session credentials in the browser, never a server API Key.
Upload raw bytes, retain the descriptor, then send it with a stable client_message_id. Add progress, cancellation, retry and scan states.
Only preview clean PNG/JPEG/WebP; download other clean files. Never expose internal notes or unauthorized attachments.
Cancel requests and clear blobs when identity changes. Test limits, isolation, retry, duplicates, expiration and scanning failures.
Use local mocks unless real-environment testing has been explicitly authorized. Never upload customer files or deploy production without approval.