Uploading files
This documentation describes the file upload process. To understand how to use uploaded files in messages, refer to the Message Exchange documentation, specifically the section about sending messages with attachments.
The Moveo WebSocket API provides a secure and efficient way to upload files during chat sessions. This feature allows users to share documents, images, and other file types with agents or AI assistants. The process involves a two-step approach:
- First, requesting a secure, time-limited URL for uploading the file
- Then, using that URL to upload the file directly to our storage system
This approach ensures secure file handling while maintaining optimal performance. The API supports various file types and includes built-in validation, size limits, and error handling to ensure reliable file transfers.
File uploads can only be performed within an active WebSocket session
.Sending an attachment to the session
File uploads are a part of sending attachment in an message to the server. Once a file is successfully uploaded, it can be included in messages using the attachments
field in the message:send
event. Here's how the two processes work together:
-
Upload the File Follow the File Upload Process to obtain a secure
download_url
. This process involves:- Requesting a presigned URL using the
session:file:upload:request
event - Uploading the file to the provided URL
- Receiving a
upload_url
that can be used to access the file
- Requesting a presigned URL using the
-
Include in Message Once you have the
upload_url
, you can include it in your message using theattachments
field. The attachment should follow the format described in the Sending and receiving messages documentation.
The url
field in the attachment should be the upload_url
received from the upload process. Other URLs are not supported.
Example of sending a message with an uploaded file:
{
"event": "message:send",
"data": {
"input": {
"text": "Please find the attached document",
"attachments": [
{
"type": "file",
"mime_type": "application/pdf",
"url": "https://storage.example.com/upload-url",
"title": "Important Document"
}
]
},
"session_id": "session_123",
"timestamp": 1744036886028
}
}
Prerequisites
Before attempting to upload files, ensure that:
- You have an active WebSocket session
- You have the correct
session_id
from your active session
File Upload Process
1. Request Upload URL
The session:file:upload:request
event is used to request a presigned URL for file upload. This is the first step in the file upload process, where you provide the necessary metadata about the file you want to upload.
Field | Type | Required | Description |
---|---|---|---|
file_id | string | Yes | Unique identifier for the file |
session_id | string | Yes | Unique identifier for the conversation session |
original_name | string | Yes | Original filename of the file |
file_type | string | Yes | Type of the file (e.g., "pdf", "jpg") |
{
"event": "session:file:upload:request",
"data": {
"file_id": "123e4567-e89b-12d3-a456-426614174000",
"session_id": "session_123",
"original_name": "document.pdf",
"file_type": "pdf"
}
}
Server Responses
Success Response (session:file:upload:request:success
)
The server responds with a success event containing the URLs needed for file upload and download.
Field | Type | Required | Description |
---|---|---|---|
upload_url | string | Yes | URL for uploading the file |
download_url | string | Yes | URL for accessing the uploaded file |
file_id | string | Yes | Unique identifier for the file |
file_name | string | Yes | Processed filename of the file |
{
"event": "session:file:upload:request:success",
"data": {
"upload_url": "https://storage.example.com/presigned-url",
"download_url": "https://storage.example.com/download-url",
"file_id": "123e4567-e89b-12d3-a456-426614174000",
"file_name": "document_123.pdf"
}
}
Error Response (session:file:upload:request:error
)
If the request fails, the server responds with an error event containing details about the failure.
Field | Type | Required | Description |
---|---|---|---|
error.code | string | Yes | Error code for programmatic handling |
error.message | string | Yes | Human-readable error message |
{
"code": "invalid_file_type",
"message": "Invalid file type"
}
2. Upload File to Presigned URL
Once you receive the presigned URL, upload the file using a PUT request. The file should be sent as-is, without any additional processing or parsing.
HTTP PUT Request
curl -X PUT \
-H "Content-Type: <file-mime-type>" \
--data-binary @<path-to-file> \
https://storage.example.com/presigned-url
Headers:
Content-Type
: Must match the file's MIME type- No additional headers are required as the presigned URL includes all necessary authentication
Body:
- Send the raw file bytes as the request body
- Do not encode or transform the file
- Do not wrap the file in any additional data structure
Example Request
curl -X PUT \
-H "Content-Type: application/pdf" \
--data-binary @document.pdf \
https://storage.example.com/presigned-url
3. Response Handling
The upload endpoint will respond with:
Success (200 OK):
HTTP/1.1 200 OK
Error Responses:
// Invalid file type
{
"code": "invalid_file_type",
"message": "Invalid file type"
}
// File too large
{
"code": "file_too_large",
"message": "File size exceeds 10MB limit"
}
// Invalid request
{
"code": "invalid_request",
"message": "Invalid request format"
}
Important Notes
-
File Format
- Send the file in its original format
- Do not encode the file (no base64, no form-data)
- Do not compress the file
- Do not modify the file content
-
Content-Type
- Must match the actual file type
- Common MIME types:
{
"application/pdf": ".pdf",
"image/jpeg": ".jpg, .jpeg",
"image/png": ".png",
"image/gif": ".gif",
"application/msword": ".doc",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
"application/vnd.ms-powerpoint": ".ppt",
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
"application/zip": ".zip",
"application/x-rar-compressed": ".rar"
}
-
File Size
- Maximum size: 10MB
- No minimum size limit
- Consider implementing chunked uploads for large files
-
Retry Logic
- Implement retry logic for failed uploads
- Maximum 3 retry attempts
- 1-second delay between retries
- If all retries fail, request a new presigned URL
Common Issues and Solutions
-
Invalid Content-Type
- Ensure the Content-Type header matches the actual file type
- Do not use generic types like application/octet-stream
- Solution: Verify file type before upload and set correct Content-Type
-
File Corruption
- Send the file in its original format
- Do not modify or transform the file content
- Ensure proper binary transfer
- Solution: Validate file integrity before and after upload
-
Timeout Issues
- Implement proper timeout handling
- Consider implementing progress tracking
- Handle network interruptions gracefully
- Solution: Use appropriate timeout values and implement retry logic
-
Authentication Errors
- Ensure the presigned URL is used within its validity period
- Do not modify the presigned URL
- Request a new URL if the current one expires
- Solution: Implement URL expiration checks and refresh logic
Example Upload Flow
- Get Presigned URL
{
"event": "session:file:upload:request",
"data": {
"file_id": "123e4567-e89b-12d3-a456-426614174000",
"session_id": "session_123",
"original_name": "document.pdf",
"file_type": "pdf"
}
}
- Receive Presigned URL
{
"event": "session:file:upload:request:success",
"data": {
"upload_url": "https://storage.example.com/presigned-url",
"download_url": "https://storage.example.com/download-url",
"file_id": "123e4567-e89b-12d3-a456-426614174000",
"file_name": "document_123.pdf"
}
}
- Upload File
curl -X PUT \
-H "Content-Type: application/pdf" \
--data-binary @document.pdf \
https://storage.example.com/presigned-url
- Handle Response
- Success: Proceed with using the download_url
- Failure: Implement retry logic or request new presigned URL
This documentation provides detailed information about the file upload process, including proper handling of file data and common issues to avoid.