Saving AI Generated Images to Imgwire
AI image-generation APIs often return temporary URLs or base64 image data. Save those results to Imgwire when your app needs durable hosting, transformations, presets, and CDN delivery.
This tutorial uses the OpenAI Node SDK for generation and @imgwire/node for storage.
Install packages
yarn add openai @imgwire/node
Set server-only environment variables:
OPENAI_API_KEY=...
IMGWIRE_API_KEY=sk_...
Do not put either key in browser code, mobile bundles, or public static files.
Generate and upload an image
Current OpenAI GPT image models return base64-encoded image data through the Images API. Convert that data to a Buffer, then upload the buffer to Imgwire.
import OpenAI from 'openai';
import { ImgwireClient } from '@imgwire/node';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY!,
});
const imgwire = new ImgwireClient({
apiKey: process.env.IMGWIRE_API_KEY!,
});
export async function generateAndSaveImage(prompt: string) {
const response = await openai.images.generate({
model: 'gpt-image-2',
prompt,
size: '1024x1024',
quality: 'medium',
output_format: 'png',
});
const generated = response.data?.[0];
if (!generated?.b64_json) {
throw new Error('OpenAI did not return image data.');
}
const imageBuffer = Buffer.from(generated.b64_json, 'base64');
const image = await imgwire.images.upload({
file: imageBuffer,
fileName: 'generated-image.png',
mimeType: 'image/png',
purpose: 'ai generated image',
customMetadata: {
source: 'openai',
model: 'gpt-image-2',
prompt,
},
});
return {
imageId: image.id,
previewUrl: image.url({
preset: 'medium',
format: 'auto',
quality: 'auto',
}),
};
}
The returned imageId is the durable application value. Store it with your generated image record, user project, document, or gallery item.
Use URL ingestion for temporary assets
Some AI providers return a temporary asset URL instead of base64 data. In that case, let Imgwire fetch the URL directly:
const image = await imgwire.images.uploadViaUrl({
url: temporaryAssetUrl,
purpose: 'ai generated image',
customMetadata: {
source: 'ai-provider',
workflow: 'prompt-to-image',
prompt,
},
});
const deliveryUrl = image.url({
width: 1200,
format: 'auto',
quality: 'auto',
});
Upload-by-URL is useful when the provider URL is short-lived and your app wants Imgwire to preserve the generated image before that URL expires.
Store useful metadata
Use customMetadata for details your app may need later:
customMetadata: {
source: 'openai',
model: 'gpt-image-2',
workflow: 'blog-hero-generator',
user_id: user.id,
}
Avoid storing secrets, private prompts, or sensitive user data in image metadata unless your application policy allows it.
Render generated images
Generated images usually need multiple render sizes. Store the ID, then generate variants for each surface:
const image = await imgwire.images.retrieve(imageId);
const cardUrl = image.url({
width: 640,
height: 360,
resizing_type: 'cover',
gravity: 'attention',
format: 'auto',
quality: 'auto',
});
const ogUrl = image.url({
width: 1200,
height: 630,
resizing_type: 'cover',
gravity: 'attention',
format: 'jpeg',
quality: 85,
});
Use format=auto for browser display and explicit format=jpeg when a downstream consumer requires a fixed content type.
Best practices
- Generate and upload AI images from a backend, worker, or queue.
- Store the Imgwire image ID with the generation record.
- Capture source, model, and workflow metadata for debugging and moderation.
- Use
uploadViaUrlwhen a provider returns a temporary public URL. - Use
format=auto&quality=autofor public previews and explicit transforms for social images.
Related pages
- Backend Quickstart
- AI Photo App with Expo & React Native
- Generating Social & OpenGraph Images with Imgwire
- Transformations API Overview
Last updated at: May 8, 2026