API Documentation

Quick Start: Generate Your First Image in 3 Steps

Step 1: Sign Up and Get Your API Key

Create a free account at imagify.ca/register. You'll receive 10 free credits to get started. No credit card required. Once logged in, go to your dashboard settings to copy your API key.

Step 2: Make Your First Request

Use this cURL command to generate your first image. Replace YOUR_API_KEY with your actual API key:

curl -X POST https://api.imagify.ca/api/images/generate \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A futuristic city at sunset with neon lights",
    "size": "1024x1024",
    "style": "standard"
  }'

Step 3: View Your Image

The API will return a JSON response with an image URL. The response looks like this:

{
  "success": true,
  "image": {
    "id": "abc123...",
    "url": "https://cdn.imagify.ca/images/abc123.png",
    "prompt": "A futuristic city at sunset with neon lights",
    "size": "1024x1024",
    "style": "standard",
    "createdAt": "2026-01-15T10:30:00Z"
  },
  "credits_remaining": 9
}

Open the URL in your browser to view your generated image. The image URL is permanent and will not expire.

Authentication

The API supports two authentication methods:

  • JWT Token: Use for web dashboard access (when logged in through the website)
  • API Key: Use for programmatic access (recommended for applications)

API Key (Recommended)

Get your API key from your dashboard settings. Include it in the X-API-Key header:

X-API-Key: <your-api-key>

JWT Token

For web dashboard access, use the Bearer token:

Authorization: Bearer <your-jwt-token>

Generate Image

Generate a new image using DALL-E 3. This is the main endpoint you'll use.

Endpoint

POST https://api.imagify.ca/api/images/generate

Request Body

{
  "prompt": "A futuristic city at sunset",
  "size": "1024x1024",
  "style": "standard"
}

Full Parameter Reference

ParameterTypeRequiredDescription
promptstringYesText description of the image you want to generate. Maximum 1000 characters. Be specific and descriptive for best results. See prompt engineering tips below.
sizestringNoImage dimensions. Options: "1024x1024" (square, best for general use and social media), "1792x1024" (landscape, best for banners, headers, wide images), "1024x1792" (portrait, best for mobile, Pinterest, tall images). Default: "1024x1024"
stylestringNoImage style. "vivid" produces more saturated, dramatic, and stylized images with enhanced colors and contrast. "standard" produces more natural, realistic images that look closer to photographs. Default: "standard"

Prompt Limit: Your prompt can be up to 1000 characters. To make the most of it, be specific about subject, style, lighting, composition, and details. Avoid redundant words. See the prompt engineering section below for tips.

Response

Successful response (200 OK):

{
  "success": true,
  "image": {
    "id": "abc123def456...",
    "url": "https://cdn.imagify.ca/images/abc123def456.png",
    "prompt": "A futuristic city at sunset",
    "size": "1024x1024",
    "style": "standard",
    "createdAt": "2026-01-15T10:30:00Z"
  },
  "credits_remaining": 9
}

The image URL is permanent and will not expire. You can use it directly in your applications, store it, or download it.

Code Examples

Complete, copy-pasteable examples for generating images in different programming languages. Each example generates an image and saves or displays the result.

Python (using requests)

import requests
import json

API_KEY = "YOUR_API_KEY"
url = "https://api.imagify.ca/api/images/generate"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

data = {
    "prompt": "A futuristic city at sunset with neon lights",
    "size": "1024x1024",
    "style": "standard"
}

response = requests.post(url, headers=headers, json=data)
result = response.json()

if result.get("success"):
    image_url = result["image"]["url"]
    print(f"Image generated: {image_url}")
    
    # Download and save the image
    img_response = requests.get(image_url)
    with open("generated_image.png", "wb") as f:
        f.write(img_response.content)
    print("Image saved as generated_image.png")
else:
    print(f"Error: {result.get('error')}")

Python (using aiohttp for async)

import aiohttp
import asyncio
import aiofiles

async def generate_image():
    API_KEY = "YOUR_API_KEY"
    url = "https://api.imagify.ca/api/images/generate"
    
    headers = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json"
    }
    
    data = {
        "prompt": "A futuristic city at sunset with neon lights",
        "size": "1024x1024",
        "style": "standard"
    }
    
    async with aiohttp.ClientSession() as session:
        async with session.post(url, headers=headers, json=data) as response:
            result = await response.json()
            
            if result.get("success"):
                image_url = result["image"]["url"]
                print(f"Image generated: {image_url}")
                
                # Download and save the image
                async with session.get(image_url) as img_response:
                    async with aiofiles.open("generated_image.png", "wb") as f:
                        await f.write(await img_response.read())
                print("Image saved as generated_image.png")
            else:
                print(f"Error: {result.get('error')}")

# Run the async function
asyncio.run(generate_image())

Node.js (using axios)

const axios = require('axios');
const fs = require('fs');
const https = require('https');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://api.imagify.ca/api/images/generate';

axios.post(url, {
  prompt: 'A futuristic city at sunset with neon lights',
  size: '1024x1024',
  style: 'standard'
}, {
  headers: {
    'X-API-Key': API_KEY,
    'Content-Type': 'application/json'
  }
})
.then(response => {
  const imageUrl = response.data.image.url;
  console.log('Image generated:', imageUrl);
  
  // Download and save the image
  https.get(imageUrl, (res) => {
    const fileStream = fs.createWriteStream('generated_image.png');
    res.pipe(fileStream);
    fileStream.on('finish', () => {
      console.log('Image saved as generated_image.png');
    });
  });
})
.catch(error => {
  console.error('Error:', error.response?.data?.error || error.message);
});

Node.js (using native fetch)

const fs = require('fs');
const https = require('https');

const API_KEY = 'YOUR_API_KEY';
const url = 'https://api.imagify.ca/api/images/generate';

async function generateImage() {
  try {
    const response = await fetch(url, {
      method: 'POST',
      headers: {
        'X-API-Key': API_KEY,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        prompt: 'A futuristic city at sunset with neon lights',
        size: '1024x1024',
        style: 'standard'
      })
    });
    
    const result = await response.json();
    
    if (result.success) {
      const imageUrl = result.image.url;
      console.log('Image generated:', imageUrl);
      
      // Download and save the image
      https.get(imageUrl, (res) => {
        const fileStream = fs.createWriteStream('generated_image.png');
        res.pipe(fileStream);
        fileStream.on('finish', () => {
          console.log('Image saved as generated_image.png');
        });
      });
    } else {
      console.error('Error:', result.error);
    }
  } catch (error) {
    console.error('Error:', error.message);
  }
}

generateImage();

PHP (using cURL)

<?php
$apiKey = 'YOUR_API_KEY';
$url = 'https://api.imagify.ca/api/images/generate';

$data = [
    'prompt' => 'A futuristic city at sunset with neon lights',
    'size' => '1024x1024',
    'style' => 'standard'
];

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'X-API-Key: ' . $apiKey,
    'Content-Type: application/json'
]);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$result = json_decode($response, true);

if ($result && isset($result['success']) && $result['success']) {
    $imageUrl = $result['image']['url'];
    echo "Image generated: $imageUrl
";
    
    // Download and save the image
    $imageData = file_get_contents($imageUrl);
    file_put_contents('generated_image.png', $imageData);
    echo "Image saved as generated_image.png
";
} else {
    echo "Error: " . ($result['error'] ?? 'Unknown error') . "
";
}
?>

Ruby

require 'net/http'
require 'json'
require 'uri'

api_key = 'YOUR_API_KEY'
url = URI('https://api.imagify.ca/api/images/generate')

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request['X-API-Key'] = api_key
request['Content-Type'] = 'application/json'
request.body = {
  prompt: 'A futuristic city at sunset with neon lights',
  size: '1024x1024',
  style: 'standard'
}.to_json

response = http.request(request)
result = JSON.parse(response.body)

if result['success']
  image_url = result['image']['url']
  puts "Image generated: #{image_url}"
  
  # Download and save the image
  image_uri = URI(image_url)
  image_response = Net::HTTP.get_response(image_uri)
  File.write('generated_image.png', image_response.body)
  puts "Image saved as generated_image.png"
else
  puts "Error: #{result['error']}"
end

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    apiKey := "YOUR_API_KEY"
    url := "https://api.imagify.ca/api/images/generate"
    
    data := map[string]interface{}{
        "prompt": "A futuristic city at sunset with neon lights",
        "size":   "1024x1024",
        "style":  "standard",
    }
    
    jsonData, _ := json.Marshal(data)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
    req.Header.Set("X-API-Key", apiKey)
    req.Header.Set("Content-Type", "application/json")
    
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Error:", err)
        return
    }
    defer resp.Body.Close()
    
    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    
    if success, ok := result["success"].(bool); ok && success {
        imageData := result["image"].(map[string]interface{})
        imageURL := imageData["url"].(string)
        fmt.Println("Image generated:", imageURL)
        
        // Download and save the image
        imgResp, _ := http.Get(imageURL)
        defer imgResp.Body.Close()
        
        file, _ := os.Create("generated_image.png")
        defer file.Close()
        
        io.Copy(file, imgResp.Body)
        fmt.Println("Image saved as generated_image.png")
    } else {
        fmt.Println("Error:", result["error"])
    }
}

Prompt Engineering Tips

Writing effective prompts is key to getting great results. Follow this structure and learn from these examples.

Prompt Structure

The best prompts follow this structure:

Subject + Style + Lighting + Composition + Details

Example Prompts with Explanations

Example 1: Product Photography

"Coffee mug product, professional product photography, white background, studio lighting, clean composition, e-commerce image, high quality"

Why it works: Clear subject (coffee mug), specific style (professional product photography), defined setting (white background), lighting specified (studio), composition noted (clean), use case mentioned (e-commerce), quality requested.

Example 2: Landscape

"Mountain landscape at sunset, professional photography style, golden hour lighting, wide angle composition, dramatic clouds, high detail"

Why it works: Subject (mountain landscape), time of day (sunset), style (professional photography), lighting (golden hour), composition (wide angle), atmospheric details (dramatic clouds), detail level specified.

Example 3: Character Design

"Fantasy warrior character, 32-bit pixel art style, front view, soft ambient lighting, centered composition, detailed armor, game asset"

Why it works: Subject (fantasy warrior), art style (32-bit pixel art), view angle (front view), lighting (soft ambient), composition (centered), details (armor), use case (game asset).

Example 4: Abstract Design

"Abstract geometric pattern, modern minimalist style, vibrant colors, even lighting, centered composition, clean lines, high contrast"

Why it works: Subject (abstract pattern), style (modern minimalist), color specification (vibrant), lighting (even), composition (centered), design elements (clean lines), visual quality (high contrast).

Example 5: Social Media Post

"Motivational quote card design, Instagram style, modern minimalist, bright natural lighting, clean typography area, engaging visual, high quality"

Why it works: Use case (quote card), platform style (Instagram), design style (modern minimalist), lighting (bright natural), composition element (typography area), engagement factor, quality specified.

Common Mistakes to Avoid

❌ Too Vague

"A dog"

Better: "A golden retriever puppy playing in a sunny park, professional photography, natural lighting, high quality"

❌ Too Long and Rambling

"I want to see a picture of a futuristic cyberpunk cityscape with neon lights and flying cars and detailed architecture and multiple characters and complex lighting and cinematic composition and..."

Better: "Futuristic cyberpunk cityscape, neon lights, flying cars, detailed architecture, cinematic lighting, wide angle composition"

❌ Contradictory Instructions

"8-bit pixel art character in realistic 3D style"

Better: "8-bit pixel art character sprite, retro game style, front view"

❌ Missing Key Details

"A warrior"

Better: "Fantasy warrior character, front view, detailed armor, sword in hand, game asset style"

Troubleshooting & Common Errors

401 Unauthorized - API Key Issues

Problem: Your API key is missing, incorrect, or invalid.

How to fix:

  • Verify you're using the correct header: X-API-Key (not Authorization)
  • Check that your API key is copied correctly from your dashboard (no extra spaces)
  • Ensure your API key hasn't been regenerated (if you regenerated it, use the new key)
  • Make sure you're logged into the correct account
// JavaScript - Proper error handling
try {
  const response = await fetch('https://api.imagify.ca/api/images/generate', {
    method: 'POST',
    headers: {
      'X-API-Key': 'YOUR_API_KEY', // Make sure this is correct
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ prompt: 'test' })
  });
  
  if (response.status === 401) {
    console.error('Authentication failed. Check your API key.');
  }
  
  const data = await response.json();
} catch (error) {
  console.error('Request failed:', error);
}

402 Payment Required - Out of Credits

Problem: You've used all your credits.

How to fix: Purchase more credits from your dashboard or visit imagify.ca/pricing. Credits never expire, so you can buy in bulk.

// Python - Handling 402 error
import requests

response = requests.post(url, headers=headers, json=data)

if response.status_code == 402:
    print("Out of credits. Please purchase more at imagify.ca/pricing")
    print(f"Credits remaining: {response.json().get('credits', 0)}")
else:
    result = response.json()

400 Bad Request - Invalid Prompt

Problem: Your prompt violates content policy, is empty, or exceeds 1000 characters.

What's not allowed:

  • Violent, harmful, or illegal content
  • Hate speech or discriminatory content
  • Sexually explicit content
  • Requests to generate images of real people without consent
  • Copyrighted characters or brands (use generic descriptions instead)

How to fix: Revise your prompt to be appropriate and under 1000 characters. Be descriptive but concise.

429 Too Many Requests - Rate Limited

Problem: You've exceeded the rate limit of 100 requests per 15 minutes per IP address.

How to handle: Implement exponential backoff. Wait and retry with increasing delays.

// JavaScript - Exponential backoff for rate limits
async function generateWithRetry(prompt, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(url, { /* ... */ });
      
      if (response.status === 429) {
        const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
        const delay = Math.min(retryAfter * 1000, Math.pow(2, i) * 1000);
        console.log(`Rate limited. Waiting ${delay}ms before retry...`);
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }
      
      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 1000));
    }
  }
}
# Python - Exponential backoff for rate limits
import time
import requests

def generate_with_retry(prompt, max_retries=3):
    for i in range(max_retries):
        try:
            response = requests.post(url, headers=headers, json={'prompt': prompt})
            
            if response.status_code == 429:
                retry_after = int(response.headers.get('Retry-After', 60))
                delay = min(retry_after, 2 ** i)
                print(f"Rate limited. Waiting {delay}s before retry...")
                time.sleep(delay)
                continue
            
            return response.json()
        except Exception as e:
            if i == max_retries - 1:
                raise e
            time.sleep(2 ** i)
    return None

Timeout Issues

Expected response times: Image generation typically takes 10-30 seconds. Complex prompts or high server load may take up to 60 seconds.

Retry strategy: Set your timeout to at least 90 seconds. If a request times out, retry once. If it times out again, the server may be experiencing issues.

// JavaScript - Proper timeout handling
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 90000); // 90 second timeout

try {
  const response = await fetch(url, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(data),
    signal: controller.signal
  });
  clearTimeout(timeoutId);
  // Process response
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Request timed out. The server may be busy. Please try again.');
  }
}

Best Practices & Webhooks

Image URL Handling

Image URLs are permanent. The URLs returned by the API do not expire. You can:

  • Store the URL in your database for later use
  • Use the URL directly in your applications (no need to download immediately)
  • Share the URL with others
  • Download the image at any time

However, for production applications, consider downloading and hosting images on your own CDN for better performance and reliability.

Caching Strategies

  • Cache generated images: If you generate the same or similar images frequently, cache the results to save credits
  • Cache prompts: Store successful prompts and their results for reuse
  • CDN caching: If hosting images yourself, use a CDN to cache frequently accessed images

Batch Generation Patterns

When generating multiple images, use these patterns:

// JavaScript - Batch generation with rate limit handling
async function generateBatch(prompts) {
  const results = [];
  const delay = 1000; // 1 second between requests to avoid rate limits
  
  for (const prompt of prompts) {
    try {
      const result = await generateImage(prompt);
      results.push(result);
      await new Promise(resolve => setTimeout(resolve, delay));
    } catch (error) {
      console.error(`Failed to generate: ${prompt}`, error);
      results.push({ error, prompt });
    }
  }
  
  return results;
}

Cost Optimization Tips

  • Reuse prompts: If you need variations, generate once and edit the image rather than regenerating
  • Use appropriate sizes: Don't generate 1792x1024 if you only need 1024x1024 - it costs the same but uses more bandwidth
  • Test with standard style first: Standard style is often sufficient and generates faster than vivid
  • Buy credits in bulk: 500 credits cost $0.30/image vs $0.50/image for 10 credits (40% savings)
  • Cache results: Don't regenerate the same image multiple times

Migration Guides

Coming from OpenAI API Directly?

Imagify simplifies the OpenAI DALL-E 3 API. Here's a side-by-side comparison:

OpenAI API (Direct)

fetch('https://api.openai.com/v1/images/generations', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk-...',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    model: 'dall-e-3',
    prompt: 'A city',
    n: 1,
    size: '1024x1024',
    quality: 'standard',
    style: 'vivid'
  })
})

Imagify API (Simplified)

fetch('https://api.imagify.ca/api/images/generate', {
  method: 'POST',
  headers: {
    'X-API-Key': 'your-key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    prompt: 'A city',
    size: '1024x1024',
    style: 'vivid'
  })
})

Key differences:

  • Simpler authentication (X-API-Key header instead of Bearer token)
  • No need to specify model (always DALL-E 3)
  • No "n" parameter (always generates 1 image)
  • Simpler parameter names (size and style instead of size, quality, and style)
  • Built-in error handling and retry logic
  • Credit system instead of direct billing

Coming from Stable Diffusion?

Imagify uses DALL-E 3, which has different characteristics:

  • Better prompt understanding: DALL-E 3 understands natural language better than Stable Diffusion
  • No negative prompts: DALL-E 3 doesn't support negative prompts - focus on describing what you want
  • Fixed sizes: Only 3 size options (1024x1024, 1792x1024, 1024x1792) vs Stable Diffusion's flexibility
  • Higher quality out-of-the-box: Less need for prompt engineering to get good results
  • Built-in safety: Content filtering is automatic, no need to configure
  • Simpler API: Fewer parameters to manage

If you're used to Stable Diffusion's prompt style, you may need to adjust. DALL-E 3 works better with natural language descriptions rather than technical keywords.

Get Image History

Retrieve your generated images with pagination.

Endpoint

GET https://api.imagify.ca/api/images/history?page=1&limit=20

Query Parameters

ParameterTypeDefaultDescription
pagenumber1Page number (1-indexed)
limitnumber20Items per page (max 100)

Error Responses

401 Unauthorized

{
  "error": "Authentication required"
}

402 Payment Required

{
  "error": "Insufficient credits",
  "credits": 0,
  "message": "Please purchase more credits to continue"
}

400 Bad Request

{
  "error": "Prompt is required"
}

429 Too Many Requests

{
  "error": "Rate limit exceeded",
  "message": "Please try again later"
}

Rate Limits

API requests are limited to 100 requests per 15 minutes per IP address. This limit applies to all endpoints.

If you exceed the rate limit, you'll receive a 429 Too Many Requests response. Implement exponential backoff (see troubleshooting section) to handle rate limits gracefully.