diff --git a/integration/inputs-and-outputs.mdx b/integration/inputs-and-outputs.mdx index 2275585..8fd85c4 100644 --- a/integration/inputs-and-outputs.mdx +++ b/integration/inputs-and-outputs.mdx @@ -37,8 +37,8 @@ The simplest method if your files are already hosted somewhere publicly accessib ``` - Pre-signed URLs work when the URL itself grants access to the file. Magic Hour - cannot forward your browser session, cookies, or custom authorization headers. + Pre-signed URLs work when the URL itself grants access to the file. Magic Hour cannot forward your + browser session, cookies, or custom authorization headers. ### URL Requirements @@ -387,8 +387,9 @@ When a job completes successfully, the response includes download URLs: ### Download URL Expiration - **24-Hour Expiration**: Download URLs expire after 24 hours. Download files promptly or request - fresh URLs using the GET endpoint. + **Temporary URLs**: Download URLs are signed for 24 hours, but GET can return a still-valid cached + URL. Use each download's `expires_at` for its remaining validity. If a URL expires, retrieve the + same completed project using GET for a current URL; do not create another generation. To get fresh download URLs for an existing project: @@ -411,7 +412,8 @@ const downloadUrl = status.downloads[0].url; ### Streaming Downloads -For production applications, use streaming downloads to handle large files efficiently: +The Python example streams response chunks. The Node.js example buffers the complete file in memory +before writing; it is not a memory-efficient streaming implementation. @@ -516,20 +518,23 @@ Some APIs generate multiple files (e.g., multiple images): ```python Python # Download all outputs +status_response = client.v1.image_projects.get(id="project_id") for i, download in enumerate(status_response.downloads): filename = f"output_{i+1}.png" filepath = f"outputs/{filename}" - download_file(download.url, filepath) - print(f"Downloaded: {filename}") + if download_file(download.url, filepath): + print(f"Downloaded: {filename}") ``` ```javascript Node.js // Download all outputs +const statusResponse = await client.v1.imageProjects.get({ id: "project_id" }); for (const [i, download] of statusResponse.downloads.entries()) { const filename = `output_${i + 1}.png`; const filepath = `outputs/${filename}`; - await downloadFile(download.url, filepath); - console.log(`Downloaded: ${filename}`); + if (await downloadFile(download.url, filepath)) { + console.log(`Downloaded: ${filename}`); + } } ``` @@ -544,6 +549,8 @@ The SDK's `generate()` function can download files automatically: ```python Python result = client.v1.ai_image_generator.generate( image_count=1, + model="z-image-turbo", + resolution="640px", aspect_ratio="16:9", style={"prompt": "Cool image", "tool": "ai-anime-generator"}, name="AI Image Generated by Magic Hour", @@ -552,22 +559,39 @@ result = client.v1.ai_image_generator.generate( download_directory="." ) -# Print where files were saved -paths = getattr(result, "downloaded_paths", None) or [] -print(f"✅ Downloaded to: {paths}" if paths else "✅ Done (no downloaded_paths returned by SDK)") +if result.status != "complete": + raise RuntimeError(f"Project {result.id}: {result.status}; {result.error}") + +paths = result.downloaded_paths or [] +if not paths: + raise RuntimeError(f"Project {result.id} completed, but no files were downloaded. Retrieve this same project ID to retry the download.") +print(f"✅ Downloaded to: {paths}") ``` ```javascript Node.js -const result = await client.v1.aiImageGenerator.generate({ - imageCount: 1, - aspectRatio: "16:9", - style: { prompt: "Mountain sunset", tool: "ai-anime-generator" }, - waitForCompletion: true, - downloadOutputs: true, // Auto-download - downloadDirectory: ".", // Where to save -}); +const result = await client.v1.aiImageGenerator.generate( + { + imageCount: 1, + model: "z-image-turbo", + resolution: "640px", + aspectRatio: "16:9", + style: { prompt: "Mountain sunset", tool: "ai-anime-generator" }, + }, + { + waitForCompletion: true, + downloadOutputs: true, // Auto-download + downloadDirectory: ".", // Where to save + } +); -// Files are already downloaded +if (result.status !== "complete") { + throw new Error(`Project ${result.id}: ${result.status}; ${JSON.stringify(result.error)}`); +} +if (!result.downloadedPaths?.length) { + throw new Error( + `Project ${result.id} completed, but no files were downloaded. Retrieve this same project ID to retry the download.` + ); +} console.log(`Downloaded to: ${result.downloadedPaths}`); ``` @@ -628,7 +652,7 @@ result2 = client.v1.ai_clothes_changer.create(assets={"image_file_path": file_pa **Permanent Storage**: Generated files are stored indefinitely in Magic Hour cloud storage. -**Download URL Expiration**: Download URLs expire after 24 hours for security, but you can request fresh URLs anytime. +**Download URL Expiration**: Use each download's `expires_at`; retrieving a project does not guarantee another full 24 hours. If a URL expires, retrieve that same available, completed project for current URLs rather than generating again. **Web Dashboard**: All generated content appears in your [magichour.ai/my-library](https://magichour.ai/my-library?utm_source=docs&utm_medium=referral&utm_campaign=inputs-and-outputs) dashboard.