Download File / Folder

Download files from your shard node by specifying the path as a query parameter. Folders can only be downloaded as zip archives.

GET /fso

FSO stands for "file system object" - in this case, a file or folder

Important Notes

  • • All paths must start with / (absolute paths only)
  • • Folders can only be downloaded as zip archives (use /fsos endpoint)

Headers

Header Type Required Description
x-user-api-key string Yes Your authentication API key
Content-Type application/octet-stream Optional MIME type for binary data

Query Parameters

Parameter Type Required Description
path string Yes Absolute path of the file to download (must start with /)

Example Request

func DownloadFile(pathOnShard string, localFilePath string) {
    url := fmt.Sprintf("%s/fso?path=%s", SHARD_NODE_URL, url.QueryEscape(pathOnShard))
    req, err := http.NewRequest(http.MethodGet, url, nil)
    if err != nil {
        panic(fmt.Errorf("could not create download request: %w", err))
    }

    req.Header.Set("x-user-api-key", API_KEY)
    req.Header.Set("Content-Type", "application/octet-stream") // optional

    client := http.DefaultClient
    resp, err := client.Do(req)
    if err != nil {
        panic(fmt.Errorf("error downloading file: %w", err))
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        body, _ := io.ReadAll(resp.Body)
        panic(fmt.Sprintf("Download failed with status %d: %s", resp.StatusCode, string(body)))
    }
    
    file, err := os.Create(localFilePath)
    if err != nil {
        panic(fmt.Sprintf("Could not create file on local disk %w", err))
    }
    defer file.Close()
    
    _, err = io.Copy(file, resp.Body)
    if err != nil {
        panic(fmt.Sprintf("Could not copy resp body into disk %w", err))
    }
}
async function downloadFile(pathOnShard: string, localFilePath: string): Promise<void> {
    const url = `${SHARD_NODE_URL}/fso?path=${encodeURIComponent(pathOnShard)}`;
    const res = await fetch(url, {
        method: 'GET',
        headers: { 
            'x-user-api-key': API_KEY,
            'Content-Type': 'application/octet-stream'
        }
    });

    if (res.status !== 200) {
        const body = await res.text();
        throw new Error(`Download failed with status ${res.status}: ${body}`);
    }

    const data = await res.arrayBuffer();
    await fs.promises.writeFile(localFilePath, new Uint8Array(data));
}

Response Status Codes

Code Status Description
200 Success File downloaded successfully
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API key
404 Not Found File doesn't exist at path
5xx Server Error Internal server error - check response body for details

Download Multiple Files/Folders as Zip

Download multiple files or folders as a single zip archive by specifying paths in the request.

GET /fsos

Download multiple FSOs (file system objects) as a zip archive

Query Parameters

Parameter Type Required Description
paths string Yes List of absolute paths to download separated by null terminator (\x00)
archiveName string No Name for the resulting zip file (default: "archive.zip")

Example Request

func DownloadFilesAsZip(paths []string, localZipPath string) {
	pathsParam := strings.Join(paths, "\x00")

	url := fmt.Sprintf("%s/fsos?paths=%s",
		SHARD_NODE_URL,
		url.QueryEscape(pathsParam))

	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		panic(fmt.Errorf("could not create download zip request: %w", err))
	}

	req.Header.Set("x-user-api-key", API_KEY)

	client := http.DefaultClient
	resp, err := client.Do(req)
	if err != nil {
		panic(fmt.Errorf("error downloading zip file: %w", err))
	}
	defer resp.Body.Close()

	if resp.StatusCode != http.StatusOK {
		body, _ := io.ReadAll(resp.Body)
		panic(fmt.Sprintf("Download zip failed with status %d: %s", resp.StatusCode, string(body)))
	}

	file, err := os.Create(localZipPath)
	if err != nil {
		panic(fmt.Sprintf("Could not create zip file on local disk: %w", err))
	}
	defer file.Close()

	_, err = io.Copy(file, resp.Body)
	if err != nil {
		panic(fmt.Sprintf("Could not copy zip data to disk: %w", err))
	}
}
async function downloadFilesAsZip(paths: string[], localZipPath: string): Promise<void>{
    const pathsParam = paths.join("\x00");
    const url = `${SHARD_NODE_URL}/fsos?paths=${encodeURIComponent(pathsParam)}}`;
    
    const res = await fetch(url, {
        method: 'GET',
        headers: { 'x-user-api-key': API_KEY }
    });

    if (res.status !== 200) {
        const body = await res.text();
        throw new Error(`Download zip failed with status ${res.status}: ${body}`);
    }

    const data = await res.arrayBuffer();
    await fs.promises.writeFile(localZipPath, new Uint8Array(data));
}

Response Status Codes

Code Status Description
200 Success Zip file downloaded successfully
400 Bad Request Invalid request parameters
401 Unauthorized Invalid or missing API key
404 Not Found One or more files don't exist
5xx Server Error Internal server error - check response body for details