ideogram-sdk-patterns
Provides standardized, type-safe wrappers and retry logic for interacting with the Ideogram API.
Install
mkdir -p .claude/skills/ideogram-sdk-patterns && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7953" && unzip -o skill.zip -d .claude/skills/ideogram-sdk-patterns && rm skill.zipInstalls to .claude/skills/ideogram-sdk-patterns
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Apply production-ready Ideogram API patterns for TypeScript and Python.Key capabilities
- →Create type-safe client wrappers for REST API
- →Validate API responses using Zod schemas
- →Manage multi-tenant API key isolation
- →Automate image downloading to prevent data loss
How it works
It provides a singleton client wrapper that handles authentication, request retries for transient errors, and runtime response validation to ensure API consistency.
Inputs & outputs
When to use ideogram-sdk-patterns
- →Implement Ideogram API integrations
- →Refactor existing SDK usage
- →Establish team coding standards for Ideogram
About this skill
Ideogram SDK Patterns
Overview
Production-ready patterns for Ideogram's REST API. Since Ideogram has no official SDK, these patterns provide type-safe wrappers, retry logic, response validation, and multi-tenant support for the api.ideogram.ai endpoints.
Prerequisites
- Completed
ideogram-install-authsetup - Familiarity with async/await and fetch API
- Understanding of Ideogram response lifecycle (URLs expire)
Instructions
Step 1: Singleton Client with Auto-Download
// src/ideogram/client.ts
import { writeFileSync, mkdirSync } from "fs";
import { join } from "path";
const API_BASE = "https://api.ideogram.ai";
let instance: IdeogramClient | null = null;
export function getIdeogramClient(): IdeogramClient {
if (!instance) {
const key = process.env.IDEOGRAM_API_KEY;
if (!key) throw new Error("IDEOGRAM_API_KEY not set");
instance = new IdeogramClient(key);
}
return instance;
}
export class IdeogramClient {
constructor(private apiKey: string) {}
async generate(prompt: string, options: {
model?: string;
style_type?: string;
aspect_ratio?: string;
negative_prompt?: string;
magic_prompt_option?: string;
num_images?: number;
seed?: number;
} = {}) {
const response = await fetch(`${API_BASE}/generate`, {
method: "POST",
headers: { "Api-Key": this.apiKey, "Content-Type": "application/json" },
body: JSON.stringify({
image_request: {
prompt,
model: options.model ?? "V_2",
style_type: options.style_type ?? "AUTO",
aspect_ratio: options.aspect_ratio ?? "ASPECT_1_1",
magic_prompt_option: options.magic_prompt_option ?? "AUTO",
negative_prompt: options.negative_prompt,
num_images: options.num_images ?? 1,
seed: options.seed,
},
}),
});
return this.handleResponse(response);
}
async describe(imagePath: string) {
const form = new FormData();
const file = new Blob([await import("fs").then(fs => fs.readFileSync(imagePath))]);
form.append("image_file", file, "image.png");
const response = await fetch(`${API_BASE}/describe`, {
method: "POST",
headers: { "Api-Key": this.apiKey },
body: form,
});
return this.handleResponse(response);
}
async downloadImage(url: string, outputDir: string, filename?: string): Promise<string> {
mkdirSync(outputDir, { recursive: true });
const imgResponse = await fetch(url);
if (!imgResponse.ok) throw new Error(`Download failed: ${imgResponse.status}`);
const buffer = Buffer.from(await imgResponse.arrayBuffer());
const outPath = join(outputDir, filename ?? `ideogram-${Date.now()}.png`);
writeFileSync(outPath, buffer);
return outPath;
}
private async handleResponse(response: Response) {
if (!response.ok) {
const body = await response.text();
throw new IdeogramApiError(response.status, body);
}
return response.json();
}
}
export class IdeogramApiError extends Error {
constructor(public status: number, public body: string) {
super(`Ideogram ${status}: ${body}`);
this.name = "IdeogramApiError";
}
get isRateLimited() { return this.status === 429; }
get isSafetyRejected() { return this.status === 422; }
get isAuthError() { return this.status === 401; }
}
Step 2: Retry with Exponential Backoff
export async function withRetry<T>(
operation: () => Promise<T>,
config = { maxRetries: 3, baseDelayMs: 1000, maxDelayMs: 30000 }
): Promise<T> {
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
try {
return await operation();
} catch (err: any) {
if (attempt === config.maxRetries) throw err;
// Only retry on 429 (rate limit) or 5xx (server error)
const status = err.status ?? err.response?.status;
if (status && status !== 429 && status < 500) throw err;
const delay = Math.min(
config.baseDelayMs * Math.pow(2, attempt) + Math.random() * 500,
config.maxDelayMs
);
console.warn(`Ideogram retry ${attempt + 1}/${config.maxRetries} in ${delay.toFixed(0)}ms`);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error("Unreachable");
}
// Usage: await withRetry(() => client.generate("a sunset"));
Step 3: Response Validation with Zod
import { z } from "zod";
const ImageResultSchema = z.object({
url: z.string().url(),
prompt: z.string(),
resolution: z.string(),
is_image_safe: z.boolean(),
seed: z.number(),
style_type: z.string().optional(),
});
const GenerateResponseSchema = z.object({
created: z.string(),
data: z.array(ImageResultSchema).min(1),
});
export function validateGenerateResponse(raw: unknown) {
return GenerateResponseSchema.parse(raw);
}
Step 4: Python Client
# ideogram_client.py
import os, requests, hashlib, time
from pathlib import Path
class IdeogramClient:
BASE_URL = "https://api.ideogram.ai"
def __init__(self, api_key: str | None = None):
self.api_key = api_key or os.environ.get("IDEOGRAM_API_KEY", "")
if not self.api_key:
raise ValueError("IDEOGRAM_API_KEY required")
def generate(self, prompt: str, model="V_2", style_type="AUTO",
aspect_ratio="ASPECT_1_1", **kwargs) -> dict:
resp = requests.post(f"{self.BASE_URL}/generate", headers=self._headers(),
json={"image_request": {"prompt": prompt, "model": model,
"style_type": style_type, "aspect_ratio": aspect_ratio,
"magic_prompt_option": kwargs.get("magic_prompt", "AUTO"),
**{k: v for k, v in kwargs.items() if k != "magic_prompt"}}})
resp.raise_for_status()
return resp.json()
def download(self, url: str, output_dir: str = "./images") -> str:
Path(output_dir).mkdir(parents=True, exist_ok=True)
resp = requests.get(url)
resp.raise_for_status()
path = f"{output_dir}/ideogram-{int(time.time())}.png"
Path(path).write_bytes(resp.content)
return path
def _headers(self):
return {"Api-Key": self.api_key, "Content-Type": "application/json"}
Step 5: Multi-Tenant Factory
const tenantClients = new Map<string, IdeogramClient>();
export function getClientForTenant(tenantId: string): IdeogramClient {
if (!tenantClients.has(tenantId)) {
const apiKey = getTenantApiKey(tenantId); // from your secret store
tenantClients.set(tenantId, new IdeogramClient(apiKey));
}
return tenantClients.get(tenantId)!;
}
Error Handling
| Pattern | Use Case | Benefit |
|---|---|---|
| Singleton | Shared client across modules | Single connection, consistent config |
| Retry wrapper | Rate limits and transient errors | Automatic recovery from 429/5xx |
| Zod validation | Response validation | Catches API changes at parse time |
| Auto-download | Image persistence | Prevents URL expiry data loss |
| Multi-tenant | SaaS platforms | Per-customer API key isolation |
Output
- Type-safe client singleton with generate and describe methods
- Retry logic with exponential backoff and jitter
- Runtime validation for API responses
- Auto-download to prevent URL expiration issues
Resources
Next Steps
Apply patterns in ideogram-core-workflow-a for real-world usage.
When not to use it
- →When direct fetch calls are sufficient for simple scripts
Prerequisites
Limitations
- →Requires manual implementation of retry logic for specific status codes
- →API keys must be managed per tenant
How it compares
Unlike raw fetch requests, this pattern provides built-in error handling for rate limits and type-safe response parsing.
Compared to similar skills
ideogram-sdk-patterns side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| ideogram-sdk-patterns (this skill) | 0 | 27d | Caution | Intermediate |
| copilot-sdk | 7 | 4mo | Review | Intermediate |
| llm-application-dev | 3 | 4mo | Review | Intermediate |
| mcp-builder | 136 | 3mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
copilot-sdk
github
Build agentic applications with GitHub Copilot SDK. Use when embedding AI agents in apps, creating custom tools, implementing streaming responses, managing sessions, connecting to MCP servers, or creating custom agents. Triggers on Copilot SDK, GitHub SDK, agentic app, embed Copilot, programmable agent, MCP server, custom agent.
llm-application-dev
skillcreatorai
Building applications with Large Language Models - prompt engineering, RAG patterns, and LLM integration. Use for AI-powered features, chatbots, or LLM-based automation.
mcp-builder
anthropics
Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node/TypeScript (MCP SDK).
langchain
zechenzhangAGI
Framework for building LLM-powered applications with agents, chains, and RAG. Supports multiple providers (OpenAI, Anthropic, Google), 500+ integrations, ReAct agents, tool calling, memory management, and vector store retrieval. Use for building chatbots, question-answering systems, autonomous agents, or RAG applications. Best for rapid prototyping and production deployments.
unit-testing-test-generate
sickn33
Generate comprehensive, maintainable unit tests across languages with strong coverage and edge case focus.
generate-subsystem-skills
llama-farm
Generate specialized skills for each subsystem in the monorepo. Creates shared language skills and subsystem-specific checklists for high-quality AI code generation.