Endpoints
Overview of the endpoints provided by vs3.
The following endpoints are provided by the storage instance. Storage endpoints are not directly accessible from the client, but they are used behind the scenes by the client SDKs.
All endpoints can be called directly from the server using the storage.api object.
/upload-url
POST /upload-url creates a presigned upload URL and returns the resolved object key.
Request Body
{
fileInfo: {
name: string;
size: number;
contentType: string;
};
metadata: TMetadata; // required when metadataSchema is configured
expiresIn?: number;
acl?: "public-read" | "private";
encryption?: S3Encryption;
}Response
{
presignedUrl: string;
key: string;
uploadHeaders?: Record<string, string>;
}uploadHeaders is present when the adapter requires additional headers (for example certain encryption modes).
Example
const res = await storage.api.uploadUrl({
body: {
fileInfo: {
name: "avatar.png",
size: 156_000,
contentType: "image/png",
},
metadata: { userId: "u_1" },
encryption: { type: "SSE-S3" },
},
});
await fetch(res.presignedUrl, {
method: "PUT",
body: file,
headers: res.uploadHeaders,
});Validation and Hooks
Processing order:
- middleware chain
- file name/size/type checks
- metadata parsing and validation
- custom content validators
beforeUploadhook- key generation
- presigned URL generation
afterUploadhook
Common Errors
METADATA_VALIDATION_ERRORFILE_TOO_LARGEFILE_TYPE_NOT_ALLOWEDINVALID_FILENAMECONTENT_VALIDATION_ERRORFORBIDDEN(hook or middleware rejection)
/download-url
POST /download-url checks key validity and object existence, then returns a presigned URL.
Request Body
{
key: string;
expiresIn?: number;
encryption?: S3Encryption;
}Metadata is not required on this endpoint.
Response
{
presignedUrl: string;
downloadHeaders?: Record<string, string>;
}Example
const res = await storage.api.downloadUrl({
body: {
key: "uploads/u_1/avatar.png",
expiresIn: 60,
},
});
const fileResponse = await fetch(res.presignedUrl, {
headers: res.downloadHeaders,
});Hook and Existence Flow
Processing order:
- middleware chain
- key validation
beforeDownloadhook- object existence check
- presigned URL generation
afterDownloadhook
If the object does not exist, the endpoint returns NOT_FOUND.
Common Errors
NOT_FOUNDINVALID_FILE_INFOor key validation errorsFORBIDDEN(hook or middleware rejection)
/multipart
Multipart uploads split large files into parts, upload parts in parallel, then finalize.
/multipart/create
Starts a multipart session.
Request body:
{
fileInfo: {
name: string;
size: number;
contentType: string;
};
metadata: TMetadata; // required when metadataSchema is configured
acl?: "public-read" | "private";
encryption?: S3Encryption;
}Response:
{
uploadId: string;
key: string;
}This endpoint runs the same upload validation pipeline as /upload-url and executes beforeUpload.
/multipart/presign-parts
Presigns one or more part uploads.
Request body:
{
key: string;
uploadId: string;
parts: Array<{ partNumber: number }>;
encryption?: S3Encryption;
}Response:
{
parts: Array<{
partNumber: number;
presignedUrl: string;
uploadHeaders?: Record<string, string>;
}>;
}/multipart/complete
Finalizes the multipart session after all parts are uploaded.
Request body:
{
key: string;
uploadId: string;
parts: Array<{
partNumber: number;
eTag: string;
}>;
}Response:
{
key: string;
}/multipart/abort
Best-effort cancellation/cleanup.
Request body:
{
key: string;
uploadId: string;
}Response:
{
success: true;
}End-to-End Client Sequence
- Call
/multipart/create. - Call
/multipart/presign-partsfor next batch. - Upload each part with
PUTto returned URLs. - Call
/multipart/completewith part numbers and ETags. - On failure, attempt
/multipart/abort.
Common Multipart Errors
MULTIPART_UPLOAD_NOT_FOUNDfor expired/missing sessions.INVALID_PARTSwhen completion payload is invalid.MULTIPART_UPLOAD_FAILEDfor provider failures during presign/complete/abort.