ideogram-webhooks-events
Build event-driven workflows around Ideogram's synchronous API. Use when implementing async generation queues, batch processing, callback patterns, or image processing pipelines. Trigger with phrases like "ideogram webhook", "ideogram events", "ideogram async", "ideogram queue", "ideogram batch pipeline".
Allowed Tools
Provided by Plugin
ideogram-pack
Claude Code skill pack for Ideogram (24 skills)
Installation
This skill is included in the ideogram-pack plugin:
/plugin install ideogram-pack@claude-code-plugins-plus
Click to copy
Instructions
Ideogram Events & Async Patterns
Overview
Ideogram's API is synchronous -- each call blocks until the image is generated (5-15 seconds). For production applications, wrap it in async patterns: job queues for batch generation, callbacks for downstream processing, and pipelines for image post-processing. This skill covers BullMQ queue patterns, callback handlers, and asset processing pipelines.
Prerequisites
IDEOGRAMAPIKEYconfigured- Redis for BullMQ job queue
- Storage for generated images (S3, GCS, or R2)
- Understanding of Ideogram models and style types
Instructions
Step 1: Job Queue for Async Generation
import { Queue, Worker } from "bullmq";
import { writeFileSync, mkdirSync } from "fs";
import { join } from "path";
interface GenerationJob {
prompt: string;
style: string;
aspectRatio: string;
model: string;
callbackUrl?: string;
metadata?: Record<string, string>;
}
const connection = { host: "localhost", port: 6379 };
const imageQueue = new Queue("ideogram-generation", { connection });
// Enqueue a generation job
async function submitGeneration(job: GenerationJob) {
return imageQueue.add("generate", job, {
attempts: 3,
backoff: { type: "exponential", delay: 2000 },
removeOnComplete: 100,
removeOnFail: 50,
});
}
// Worker processes jobs with concurrency limit
const worker = new Worker("ideogram-generation", async (job) => {
const { prompt, style, aspectRatio, model, callbackUrl, metadata } = job.data;
// Call Ideogram API (synchronous, blocks 5-15s)
const response = await fetch("https://api.ideogram.ai/generate", {
method: "POST",
headers: {
"Api-Key": process.env.IDEOGRAM_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({
image_request: {
prompt,
model: model || "V_2",
style_type: style || "AUTO",
aspect_ratio: aspectRatio || "ASPECT_1_1",
magic_prompt_option: "AUTO",
},
}),
});
if (response.status === 429) {
throw new Error("Rate limited"); // BullMQ will retry with backoff
}
if (!response.ok) {
throw new Error(`Ideogram API error: ${response.status}`);
}
const result = await response.json();
const image = result.data[0];
// Download immediately (URLs expire)
const imgResp = await fetch(image.url);
const buffer = Buffer.from(await imgResp.arrayBuffer());
const outputDir = "./generated";
mkdirSync(outputDir, { recursive: true });
const filePath = join(outputDir, `${image.seed}.png`);
writeFileSync(filePath, buffer);
// Fire callback if provided
if (callbackUrl) {
await fetch(callbackUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
event: "generation.completed",
jobId: job.id,
prompt,
seed: image.seed,
resolution: image.resolution,
filePath,
metadata,
}),
});
}
return { seed: image.seed, filePath, resolution: image.resolution };
}, {
connection,
concurrency: 5, // Stay under 10 in-flight limit
});
worker.on("failed", (job, err) => {
console.error(`Job ${job?.id} failed:`, err.message);
});
Step 2: Callback Handler
import express from "express";
const app = express();
app.use(express.json());
app.post("/callbacks/ideogram", async (req, res) => {
const { event, jobId, seed, filePath, metadata } = req.body;
res.status(200).json({ received: true });
switch (event) {
case "generation.completed":
console.log(`Image generated: seed=${seed}, path=${filePath}`);
await processImage(filePath, metadata);
break;
case "generation.failed":
console.error(`Generation failed: job=${jobId}`);
await notifyFailure(jobId, req.body.error);
break;
}
});
Step 3: Batch Marketing Asset Generation
async function generateMarketingCampaign(
campaignName: string,
products: string[],
formats: Array<{ name: string; aspect: string; style: string }>
) {
const jobs = [];
for (const product of products) {
for (const format of formats) {
const job = await submitGeneration({
prompt: `${product}, professional ${format.name} design, high quality`,
style: format.style,
aspectRatio: format.aspect,
model: "V_2",
callbackUrl: "https://api.myapp.com/callbacks/ideogram",
metadata: { campaign: campaignName, product, format: format.name },
});
jobs.push(job);
}
}
console.log(`Submitted ${jobs.length} generation jobs for campaign: ${campaignName}`);
return jobs.map(j => j.id);
}
// Example: Generate all assets for a product launch
await generateMarketingCampaign("Q1 Launch", [
"Cloud analytics dashboard",
"Mobile payment app",
], [
{ name: "social-square", aspect: "ASPECT_1_1", style: "DESIGN" },
{ name: "story-vertical", aspect: "ASPECT_9_16", style: "DESIGN" },
{ name: "blog-hero", aspect: "ASPECT_16_9", style: "REALISTIC" },
]);
Step 4: Image Post-Processing Pipeline
import sharp from "sharp";
async function processImage(filePath: string, metadata?: Record<string, string>) {
const variants = [
{ suffix: "-og", width: 1200, height: 630 }, // Open Graph
{ suffix: "-thumb", width: 400, height: 400 }, // Thumbnail
{ suffix: "-social", width: 1080, height: 1080 }, // Instagram
];
for (const variant of variants) {
const outputPath = filePath.replace(".png", `${variant.suffix}.webp`);
await sharp(filePath)
.resize(variant.width, variant.height, { fit: "cover" })
.webp({ quality: 85 })
.toFile(outputPath);
console.log(`Created variant: ${outputPath}`);
}
}
Error Handling
| Issue | Cause | Solution |
|---|---|---|
| Rate limited | Too many concurrent jobs | Set worker concurrency to 5 |
| Content filtered | Prompt violates policy | Log and skip, notify reviewer |
| Expired URL | Worker too slow | Download in same worker step |
| Queue stalled | Redis connection lost | Configure BullMQ connection retry |
| Callback fails | Downstream service down | Fire-and-forget with retry queue |
Output
- BullMQ job queue for async generation
- Callback handler for downstream processing
- Batch generation for marketing campaigns
- Post-processing pipeline with sharp
Resources
Next Steps
For performance optimization, see ideogram-performance-tuning.