Track Upload Progress with Subscriptions
After you upload a file to the pre-signed S3 URL, the platform continues processing it asynchronously.
Use subscribeUserFeed to receive real-time upload events instead of polling.
For the general event schema, see Subscription Event Format.
Feed and Category
Upload events are delivered on:
subscribeUserFeed
They use:
category: "upload"
Event Names
Upload processing emits a sequence of events such as:
uploadScanneduploadTypeCheckeduploadConvertinguploadFlatteneduploadTagsParseduploadPdfMetaExtracteduploadCompleteduploadFailed
Upload Event Payload
Upload payloads use this base shape:
{
"version": "1.0",
"eventId": "evt...",
"timestamp": "2026-04-24T10:38:36.822Z",
"level": "INFO",
"event": "uploadCompleted",
"category": "upload",
"groupId": null,
"userId": "usr...",
"requestId": null,
"batchId": null,
"error": null,
"data": {
"id": "tmp...",
"key": "upload/usr.../tmp....pdf",
"code": "UPLOADOK"
}
}
data.code preserves the lower-level processing code during migration and compatibility.
Subscription Operation
subscription SubscribeUserFeed {
subscribeUserFeed {
userId
data
}
}
JavaScript Example
const parseEnvelope = (payload) => {
const raw = payload?.data;
if (!raw) return null;
return typeof raw === 'string' ? JSON.parse(raw) : raw;
};
const handleUserFeed = ({ data }) => {
const wrapper = data?.subscribeUserFeed;
const event = parseEnvelope(wrapper);
if (event?.category !== 'upload') return;
switch (event.event) {
case 'uploadCompleted':
console.log('upload complete', event.data.id, event.data.key);
break;
case 'uploadFailed':
console.error('upload failed', event.data.code, event.data.key);
break;
default:
console.log('upload progress', event.event, event.data.code);
}
};
When to Use This
This is most useful when you want to:
- show a progress drawer or upload status timeline
- detect asynchronous validation failures after the S3 PUT succeeded
- react immediately when a template or uploaded asset is ready