Skip to Content
ProvidersStability AI (Stable Diffusion)

Stability AI (Stable Diffusion)

Category: AI Image Generation
Integration type: Platform-level API key
External API: Stability AI REST API v2beta


Purpose

Stability AI provides Stable Diffusion image generation — a powerful open-weight model family with more stylistic control than DALL-E or Gemini. It is particularly well-suited for:

  • Illustrations and digital art styles (DALL-E leans photorealistic)
  • Consistent visual styles across a content series using image prompting
  • Lower cost image generation at scale
  • Image-to-image transformations (style transfer, upscaling, background removal)

The platform uses Stability AI’s hosted API (Stable Image Core, Stable Diffusion 3, and SDXL) rather than self-hosting the models.


Config Structure

Platform config (env vars)

STABILITY_AI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx STABILITY_AI_BASE_URL=https://api.stability.ai STABILITY_AI_DEFAULT_ENGINE=stable-image-core # See model options below

Model Options

Model / EngineAPI endpointBest forCost/image
stable-image-core/v2beta/stable-image/generate/coreFast, high quality, general use$0.003
sd3-large/v2beta/stable-image/generate/sd3Highest quality, longer prompts$0.065
sd3-medium/v2beta/stable-image/generate/sd3Balanced quality/cost$0.035
sd3-large-turbo/v2beta/stable-image/generate/sd3Fast, good quality$0.040
SDXL 1.0/v1/generation/{engine-id}/text-to-imageCustom styles, older API$0.002

stable-image-core is the default — fast, cheap, and produces excellent results for blog and social content.


Integration Pattern

Image generation tool (packages/tools/src/stability-ai.ts)

import axios from 'axios'; import FormData from 'form-data'; class StabilityAITool implements ImageGenerationTool { readonly name = 'stability-ai'; constructor( private apiKey: string, private baseUrl: string = 'https://api.stability.ai', ) {} private headers(contentType?: string) { return { Authorization: `Bearer ${this.apiKey}`, Accept: 'application/json', ...(contentType ? { 'Content-Type': contentType } : {}), }; } // ── Text-to-image (Stable Image Core / SD3) ────────────────────────────────── async generateImage(options: { prompt: string; negativePrompt?: string; aspectRatio?: '16:9' | '1:1' | '21:9' | '2:3' | '3:2' | '4:5' | '5:4' | '9:16' | '9:21'; model?: 'core' | 'sd3-large' | 'sd3-medium' | 'sd3-large-turbo'; style?: string; // Stable Image Core style presets — see below seed?: number; // 0 = random outputFormat?: 'jpeg' | 'png' | 'webp'; }): Promise<GeneratedImage[]> { const model = options.model ?? 'core'; const endpoint = model === 'core' ? `/v2beta/stable-image/generate/core` : `/v2beta/stable-image/generate/sd3`; const form = new FormData(); form.append('prompt', options.prompt); form.append('aspect_ratio', options.aspectRatio ?? '16:9'); form.append('output_format', options.outputFormat ?? 'jpeg'); if (options.negativePrompt) form.append('negative_prompt', options.negativePrompt); if (options.seed !== undefined) form.append('seed', String(options.seed)); if (model === 'core' && options.style) form.append('style_preset', options.style); if (model !== 'core') form.append('model', model); const response = await axios.post(`${this.baseUrl}${endpoint}`, form, { headers: { ...this.headers(), ...form.getHeaders(), Accept: 'image/*', // Stability returns raw image bytes }, responseType: 'arraybuffer', }); const imageBase64 = Buffer.from(response.data).toString('base64'); const mimeType = response.headers['content-type'] ?? 'image/jpeg'; return [{ provider: 'stability-ai', model: endpoint.includes('sd3') ? `sd3-${model}` : 'stable-image-core', imageBase64, mimeType, revisedPrompt: null, }]; } // ── Image-to-image ─────────────────────────────────────────────────────────── async imageToImage(options: { prompt: string; image: Buffer; strength?: number; // 0–1: how much to deviate from input image (default 0.7) negativePrompt?: string; outputFormat?: 'jpeg' | 'png' | 'webp'; }): Promise<GeneratedImage[]> { const form = new FormData(); form.append('prompt', options.prompt); form.append('image', options.image, { filename: 'input.jpg', contentType: 'image/jpeg' }); form.append('strength', String(options.strength ?? 0.7)); form.append('output_format', options.outputFormat ?? 'jpeg'); if (options.negativePrompt) form.append('negative_prompt', options.negativePrompt); const response = await axios.post( `${this.baseUrl}/v2beta/stable-image/generate/sd3`, form, { headers: { ...this.headers(), ...form.getHeaders(), Accept: 'image/*' }, responseType: 'arraybuffer', }, ); return [{ provider: 'stability-ai', model: 'sd3-image-to-image', imageBase64: Buffer.from(response.data).toString('base64'), mimeType: response.headers['content-type'] ?? 'image/jpeg', revisedPrompt: null, }]; } // ── Background removal ─────────────────────────────────────────────────────── async removeBackground(imageBuffer: Buffer): Promise<Buffer> { const form = new FormData(); form.append('image', imageBuffer, { filename: 'input.png', contentType: 'image/png' }); form.append('output_format', 'png'); const response = await axios.post( `${this.baseUrl}/v2beta/stable-image/edit/remove-background`, form, { headers: { ...this.headers(), ...form.getHeaders(), Accept: 'image/*' }, responseType: 'arraybuffer', }, ); return Buffer.from(response.data); } // ── Upscale ────────────────────────────────────────────────────────────────── async upscale(options: { image: Buffer; prompt: string; // Description of the image for guided upscaling }): Promise<Buffer> { const form = new FormData(); form.append('image', options.image, { filename: 'input.jpg', contentType: 'image/jpeg' }); form.append('prompt', options.prompt); form.append('output_format', 'jpeg'); const response = await axios.post( `${this.baseUrl}/v2beta/stable-image/upscale/conservative`, form, { headers: { ...this.headers(), ...form.getHeaders(), Accept: 'image/*' }, responseType: 'arraybuffer', }, ); return Buffer.from(response.data); } async verify(): Promise<void> { // Check account balance / API key validity const response = await axios.get(`${this.baseUrl}/v1/user/account`, { headers: this.headers('application/json'), }); if (!response.data.email) throw new Error('Stability AI verification failed'); } }

Style presets (Stable Image Core)

PresetBest for
photographicRealistic photography
digital-artDigital illustration
animeAnime/manga style
cinematicMovie-poster aesthetic
comic-bookBold lines, comic style
fantasy-artFantasy/RPG illustrations
isometricIsometric diagrams
line-artClean line drawings
low-polyLow-poly geometric style
neon-punkCyberpunk, neon aesthetic

Provider Selection Logic

The image generation service selects the provider based on use case and tenant config:

// packages/tools/src/image-generation.ts function resolveImageProvider(options: { useCase: 'blog_hero' | 'social_post' | 'illustration' | 'product'; tenantTier: 'free' | 'pro' | 'agency' | 'enterprise'; preferredProvider?: string; }): ImageGenerationTool { const preferred = options.preferredProvider ?? config.DEFAULT_IMAGE_PROVIDER; switch (preferred) { case 'stability-ai': return new StabilityAITool(config.STABILITY_AI_API_KEY); case 'dall-e': return new DallETool(config.OPENAI_API_KEY); case 'gemini': return new GeminiImageTool(config.GOOGLE_AI_API_KEY); default: // Cost-based default: Stability AI for bulk; DALL-E for premium if (options.tenantTier === 'free') return new StabilityAITool(config.STABILITY_AI_API_KEY); return new DallETool(config.OPENAI_API_KEY); } }

Test Cases

Unit tests (packages/tools/src/stability-ai.test.ts)

TestApproach
generateImage() uses /generate/core for model: 'core'Mock axios.post; assert URL
generateImage() uses /generate/sd3 for sd3-* modelsAssert endpoint path
generateImage() appends style_preset only for core modelAssert not in SD3 request
generateImage() returns image as base64Mock responseType: 'arraybuffer'; assert base64
imageToImage() appends strength to form dataAssert strength field present
removeBackground() calls remove-background endpointAssert URL
verify() throws on invalid keyMock no email in response; assert throws

© 2026 Leadmetrics — Internal use only