Skip to content

File Upload Events

This page documents the WebSocket endpoint used to monitor and control file upload workflows for Object Records in Catalyst.

The endpoint supports bidirectional communication. After the WebSocket connection is established, the client can request presigned upload URLs, notify the backend when uploads are complete, and receive progress and monitoring updates as the backend processes uploaded files.

WARNING

This section documents technical and service-level WebSocket APIs. It should be used as implementation reference material and not treated as end-user documentation.

Endpoint overview

This page covers the following endpoint:

  • GET /ws/object-records/uploads/<upload_id>/

GET /ws/object-records/uploads/<upload_id>/

Connects the client to an upload process identified by upload_id.

Permissions

Requires authentication.

Authentication is based on the uuid query string parameter used when establishing the WebSocket connection.

Request

Upgrade request example

text
Request Method: GET
Connection: Upgrade
Upgrade: websocket

Connection behaviour

When the connection is established, communication is bidirectional:

  • the WebSocket server sends status, progress, and result messages to the client
  • the client sends JSON messages to request upload actions or to confirm upload completion

Supported client messages

1. Request a presigned upload URL

To initiate an upload, the client sends a JSON message with the following fields:

KeyTypeNotes
typeenumrequest_presigned_url
file_namestringOriginal file name
file_sizeintegerFile size in bytes
file_typestringFile content type, for example application/zip

2. Notify the backend that a single-part upload is complete

After the client uploads a ZIP file using a previously returned single presigned URL, it must notify the backend by sending:

KeyTypeNotes
typeenumupload_complete
upload_iduuidUpload session identifier returned earlier
s3_keystringFull S3 key where the file was uploaded

3. Notify the backend that a multipart upload is complete

After the client uploads a ZIP file using multipart presigned URLs, it must notify the backend by sending:

KeyTypeNotes
typeenumcomplete_multipart_upload
partsarrayArray of uploaded part descriptors

parts array

KeyTypeNotes
part_numberintPart number, starting from 1
e_tagstringETag returned by S3 for the uploaded part

Server responses

Connection established

When the WebSocket connection is successfully opened, the server returns:

  • WebSocket upgrade status: 101 Switching Protocols
json
{
  "type": "connection_established",
  "message": "WebSocket connected successfully"
}

Presigned URL response

When the client requests a presigned upload URL, the server responds with a presigned_url_ready message.

Example response

json
{
  "type": "presigned_url_ready",
  "message": {
    "upload_id": "3c2b9b89-2f2a-497c-aa0a-1be5a8fd93c8",
    "temp_upload_id": "temp_1749545666136_csyydasgl",
    "presigned_url": "https://s3.amazonaws.com/advanced-uploader-bucket/uploads/1/0e6a1a81.zip?...",
    "fields": {},
    "s3_key": "some.domain.com/upload/1/0e6a1a81.zip",
    "is_multipart": false,
    "part_urls": [],
    "s3_upload_id": null,
    "chunk_size": null,
    "total_parts": 1
  }
}

Response fields

KeyTypeNotes
typeenumEvent type
messageobjectUpload session data

message

KeyTypeNotes
upload_iduuidInternal backend ID for this upload session
temp_upload_idstringTemporary client-side ID used to map the response to the originating request
presigned_urlstringFull S3 PUT presigned URL. For multipart uploads this is null
fieldsobjectEmpty for PUT-based uploads
s3_keystringTarget key in the S3 bucket
is_multipartbooleanIndicates whether multipart upload is required
part_urlsarrayUsed only for multipart uploads
s3_upload_idstringMultipart upload identifier used by S3
chunk_sizeintegerChunk size for multipart uploads
total_partsintegerTotal number of parts expected

message.part_urls for multipart uploads

When is_multipart is true, the part_urls array contains presigned URLs for each upload part.

KeyTypeNotes
urlstringPresigned URL for this part
partintPart number, starting from 1

Monitoring updates

After the file has been uploaded, scanned, and unpacked, the backend sends monitoring updates describing the processing state.

Monitoring update structure

KeyTypeNotes
typeenummonitoring_update
messageobjectMonitoring data

message

KeyTypeNotes
attemptintAttempt number
timestampstringISO 8601 timestamp

There may also be additional fields depending on whether the message represents a success state, an error, or an intermediate monitoring attempt.

Example: success monitoring update

json
{
  "type": "monitoring_update",
  "message": {
    "step_name": "extracting_file",
    "av-status": "clean",
    "extracted_files": 100,
    "message": "Done Extracted 100 files",
    "status": "success",
    "attempt": 10,
    "timestamp": "2025-07-10T14:30:45.123456"
  }
}

Progress updates

The backend also emits progress messages during different processing phases.

Extracting and saving files

During this phase, the backend emits periodic progress updates such as:

json
{
  "type": "progress_update",
  "message": {
    "step_name": "saving_files",
    "upload_id": "99b90581-4e29-4482-b25a-eea4d6dbe78f",
    "is_complete": false,
    "total_count": 2,
    "progress_count": 1,
    "timestamp": "2025-07-17T06:18:51.325683+00:00"
  }
}

Creating records

After antivirus scanning and file saving are completed, the backend begins creating Object Records and adding them to the target Object Class.

During this phase, the backend emits periodic progress messages such as:

json
{
  "type": "progress_update",
  "message": {
    "step_name": "creating_records",
    "upload_id": "3c2b9b89-2f2a-497c-aa0a-1be5a8fd93c8",
    "is_complete": false,
    "total_count": 120,
    "progress_count": 23,
    "timestamp": "2025-07-17T06:18:51.325683+00:00"
  }
}

Progress update fields

KeyTypeNotes
typeenumprogress_update
messageobjectProgress information

message

KeyTypeNotes
step_namestringProcessing step name
upload_iduuidUpload session ID
is_completebooleanIndicates whether the step is complete
total_countintegerTotal number of items expected
progress_countintegerNumber of processed items
timestampstringISO 8601 timestamp

Errors

ErrorResponse code / close statusMessage
Incorrect WebSocket URL pathClose: 1000 Normal Closure"type": "error", "error_code": "ERR_INCORRECT_URL", "detail":"Incorrect WebSocket URL."
upload_id is invalid, already used, or expiredClose: 1000 Normal Closure"type": "error", "error_code": "ERR_INVALID_UUID", "detail":"A valid UUID is required."
Upload ID does not match or the requesting user is not the transaction creatorClose: 1000 Normal Closure"type": "error", "error_code": "ERR_DOES_NOT_EXIST", "detail":"Not found."
File type is not application/zipClose: 1000 Normal Closure"type": "error", "error_code": "ERR_UNSUPPORTED_FILE_TYPE", "detail":"File extension “{file_type}” is not allowed. Allowed extensions are: {allowed_types}."
Missing or malformed payloadClose: 1000 Normal Closure"type": "error", "error_code": "ERR_INVALID_PAYLOAD", "detail": "Required fields: type, temp_upload_id, file_name, file_size, file_type, object_class, class_field"
File is too largeClose: 1000 Normal Closure"type": "error", "error_code": "ERR_FILE_TOO_LARGE", "detail":"Max file size is {limit} GB."
File is empty or has size less than or equal to 0 bytesClose: 1000 Normal Closure"type": "error", "error_code": "ERR_FILE_EMPTY", "detail":"File size must be larger than 0."
file_name, file_size, or file_type is nullClose: 1000 Normal Closure"type": "error", "error_code": "ERR_NULL_FIELD", "detail":"Field “{field}” may not be null."
file_name or file_type is emptyClose: 1000 Normal Closure"type": "error", "error_code": "ERR_NULL_FIELD", "detail":"Field “{field}” may not be empty."
Unexpected server error during URL generationClose: 1000 Normal Closure"type": "error", "error_code": "ERR_SERVER_ERROR", "detail": "Upload could not be initialized. Please try again later."
Unexpected S3 error during URL generationClose: 1000 Normal Closure"type": "error", "error_code": "ERR_GENERATION_ERROR", "detail": "Failed to generate presigned URL"
Invalid type value in requestClose: 1000 Normal Closure"type": "error", "error_code": "ERR_INVALID_TYPE", "detail": "Type “{type}” is not allowed. Allowed types are: [{allowed_types}]."
Request message is JSON but not an expected dictionary/objectClose: 1000 Normal Closure"type": "error", "error_code": "ERR_INVALID_TYPE", "detail": "Invalid message type. Expected a JSON object."
Multipart upload finalization failed in S3Close: 1000 Normal Closure"type": "error", "error_code": "ERR_S3_FINALIZE_FAILED", "detail": "Could not finalize multipart upload. Please try again later."
Upload marked as complete before the file is available in S3Close: 1000 Normal Closure"type": "error", "error_code": "ERR_FILE_INCOMPLETE", "detail": "Upload has not yet completed or file is not available."
Error during the handshake500 Internal Server Error

Notes

WebSocket standard close/error definitions are described in RFC 6455.