PixelAPI Documentation

Everything you need to generate AI images via a simple REST API.

Quickstart

Generate your first image in 3 steps:

  1. Sign in at pixelapi.dev/app with Google. You get 100 free credits instantly.
  2. Copy your API key from the dashboard.
  3. Make a request:
curl -X POST https://api.pixelapi.dev/v1/image/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyApp/1.0" \
  -d '{"model": "sdxl", "prompt": "A cute penguin on a beach, digital art"}'

This returns a generation_id. Poll for the result:

curl https://api.pixelapi.dev/v1/image/GENERATION_ID \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "User-Agent: MyApp/1.0"

When status is "completed", the output_url contains your image.

โš ๏ธ Important: Always set a custom User-Agent header (e.g. MyApp/1.0). Requests without a User-Agent or with default library agents (like Python's Python-urllib/3.x) may be blocked by our CDN.

Authentication

All API requests require a Bearer token in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Get your API key from the dashboard after signing in with Google.

๐Ÿ’ก Your API key starts with pk_live_. Keep it secret โ€” anyone with your key can use your credits.

Available Models

Model IDTypeCreditsSpeedBest For
sdxlImage1~8-13sHigh quality, fine details
flux-schnellImage3~25-50sArtistic styles, creative prompts
cogvideo-2bVideo25~2-5minShort video clips
upscale-4xUpscale2~10-30sEnlarge images 4x

Rate Limits

PlanRequests/minCredits/moPrice
Free20100$0
Starter601,500$9/mo
Pro1206,000$29/mo
Scale30025,000$99/mo

Rate limit headers are included in every response: X-RateLimit-Remaining, X-RateLimit-Reset.

Generate Image

POST /v1/image/generate

Submit an image generation job. Returns immediately with a generation_id to poll.

Request Body

ParameterTypeDescription
promptstringrequiredText description of the image
negative_promptstringoptionalWhat to avoid (SDXL only)
widthintoptional512โ€“1536, default 1024
heightintoptional512โ€“1536, default 1024
stepsintoptionalInference steps. SDXL: 20-50 (default 30). FLUX: 1-8 (default 4)
guidance_scalefloatoptionalPrompt adherence. Default 7.5 (SDXL), 0 (FLUX)
seedintoptionalFor reproducible results

Response

{
  "generation_id": "a1b2c3d4-...",
  "status": "queued",
  "model": "sdxl",
  "credits_used": 1.0
}

Get Generation Status

GET /v1/image/{generation_id}

Poll this endpoint until status is completed, failed, or blocked.

Response (completed)

{
  "id": "a1b2c3d4-...",
  "status": "completed",
  "output_url": "https://api.pixelapi.dev/outputs/images/2026/02/18/abc123.png",
  "model": "sdxl",
  "credits_used": 1.0,
  "created_at": "2026-02-18T10:30:00Z"
}
๐Ÿ’ก Polling tip: Poll every 2-3 seconds. SDXL typically completes in 8-13s, FLUX in 25-50s. Output URLs expire after 24 hours.

List Models

GET /v1/models

Returns all available models with their pricing and capabilities.

Account Balance

GET /v1/account/balance
{
  "credits_remaining": 97.0,
  "plan": "free",
  "email": "[email protected]"
}

Usage History

GET /v1/account/usage?limit=20

Returns your recent generation history with prompts, models, status, and output URLs.

Python Example

import requests, time

API_KEY = "your_api_key"
BASE = "https://api.pixelapi.dev"
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
    "User-Agent": "MyApp/1.0"
}

# Submit generation
resp = requests.post(f"{BASE}/v1/image/generate", json={
    "model": "sdxl",
    "prompt": "A futuristic city at sunset, cinematic lighting"
}, headers=HEADERS)
gen_id = resp.json()["generation_id"]
print(f"Submitted: {gen_id}")

# Poll for result
while True:
    time.sleep(3)
    result = requests.get(f"{BASE}/v1/image/{gen_id}", headers=HEADERS).json()
    if result["status"] == "completed":
        print(f"Done! {result['output_url']}")
        break
    elif result["status"] in ("failed", "blocked"):
        print(f"Error: {result['status']}")
        break
    print(f"  {result['status']}...")
โš ๏ธ Using urllib instead of requests? You must set the User-Agent header manually. Python's default Python-urllib/3.x is blocked by Cloudflare. See Troubleshooting.

cURL Example

# Generate
curl -X POST https://api.pixelapi.dev/v1/image/generate \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "User-Agent: MyApp/1.0" \
  -d '{"model": "flux-schnell", "prompt": "An astronaut riding a horse on Mars"}'

# Check status (replace GENERATION_ID)
curl https://api.pixelapi.dev/v1/image/GENERATION_ID \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "User-Agent: MyApp/1.0"

Node.js Example

const API_KEY = 'your_api_key';
const BASE = 'https://api.pixelapi.dev';

async function generate(prompt, model = 'sdxl') {
  // Submit
  const res = await fetch(`${BASE}/v1/image/generate`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
      'User-Agent': 'MyApp/1.0'
    },
    body: JSON.stringify({ model, prompt })
  });
  const { generation_id } = await res.json();

  // Poll
  while (true) {
    await new Promise(r => setTimeout(r, 3000));
    const status = await fetch(`${BASE}/v1/image/${generation_id}`, {
      headers: { 'Authorization': `Bearer ${API_KEY}`, 'User-Agent': 'MyApp/1.0' }
    }).then(r => r.json());

    if (status.status === 'completed') return status.output_url;
    if (['failed', 'blocked'].includes(status.status)) throw new Error(status.status);
  }
}

generate('A magical forest with glowing mushrooms').then(console.log);

Complete Sample Script (Copy & Paste)

Save this as generate.py and run it. Zero dependencies โ€” works with Python 3.6+ out of the box.

๐Ÿ’ก Replace YOUR_API_KEY with your actual API key from the dashboard.
#!/usr/bin/env python3
"""
PixelAPI โ€” Generate an AI image in seconds.
Usage: python generate.py
"""
import json, os, sys, time, urllib.request, urllib.error

# โ”โ”โ” PASTE YOUR API KEY HERE โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”
API_KEY = "YOUR_API_KEY"
# โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”โ”

PROMPT = "A majestic snow leopard on a Himalayan peak at golden hour, photorealistic, 8k"
MODEL  = "sdxl"       # "sdxl" (fast, 1 credit) or "flux-schnell" (artistic, 3 credits)
OUTPUT = "output.png"  # where to save the image

BASE = "https://api.pixelapi.dev"
HEADERS = {
    "Content-Type": "application/json",
    "Authorization": f"Bearer {API_KEY}",
    "User-Agent": "PixelAPI-Sample/1.0",
}

def api(method, path, body=None):
    data = json.dumps(body).encode() if body else None
    req = urllib.request.Request(f"{BASE}{path}", data=data, headers=HEADERS, method=method)
    try:
        with urllib.request.urlopen(req, timeout=120) as r:
            return r.status, json.loads(r.read())
    except urllib.error.HTTPError as e:
        return e.code, json.loads(e.read()) if e.read() else {}

# 1. Check balance
print("Checking account...", end=" ", flush=True)
code, data = api("GET", "/v1/account/balance")
if code != 200:
    print(f"FAILED ({data.get('detail', code)})")
    print("Get your API key at https://pixelapi.dev/app/")
    sys.exit(1)
print(f"OK โ€” {data['credits_remaining']} credits remaining")

# 2. Submit generation
print(f"Generating with {MODEL}...", end=" ", flush=True)
t0 = time.time()
code, data = api("POST", "/v1/image/generate", {
    "model": MODEL, "prompt": PROMPT, "width": 1024, "height": 1024,
})
if code != 200:
    print(f"FAILED ({data.get('detail', code)})")
    sys.exit(1)
gen_id = data["generation_id"]
print(f"submitted ({gen_id[:8]}...)")

# 3. Poll for result
print("Waiting", end="", flush=True)
while True:
    time.sleep(2)
    print(".", end="", flush=True)
    code, data = api("GET", f"/v1/image/{gen_id}")
    if data.get("status") == "completed":
        print(f" done! ({time.time() - t0:.1f}s)")
        break
    if data.get("status") in ("failed", "blocked"):
        print(f" {data['status']}!")
        sys.exit(1)

# 4. Download image
url = data["output_url"]
print(f"Downloading...", end=" ", flush=True)
req = urllib.request.Request(url, headers={"User-Agent": "PixelAPI-Sample/1.0"})
with urllib.request.urlopen(req) as r, open(OUTPUT, "wb") as f:
    f.write(r.read())
size_kb = os.path.getsize(OUTPUT) / 1024
print(f"saved to {OUTPUT} ({size_kb:.0f} KB)")

print(f"\nDone! Open {OUTPUT} to see your image.")
print(f"Image URL (valid 24h): {url}")

That's it! Run python generate.py and you'll have an AI-generated image in under 15 seconds. Change the PROMPT and MODEL variables to experiment.

Polling for Results

Image generation is asynchronous. After submitting a job:

  1. You get a generation_id immediately
  2. Poll GET /v1/image/{id} every 2-3 seconds
  3. Status progresses: queued โ†’ processing โ†’ completed

Typical completion times:

Error Handling

HTTP CodeMeaningAction
200Successโ€”
401Invalid API keyCheck your key in the dashboard
403Account blocked or CDN rejectionCheck User-Agent header; contact support
422Invalid parametersCheck request body format
429Rate limitedWait and retry; consider upgrading plan
500Server errorRetry after a few seconds

Error responses include a detail field:

{
  "detail": "Rate limit exceeded for free plan. Upgrade at https://pixelapi.dev/pricing"
}

Content Policy

PixelAPI uses automated content safety filters. Prompts and generated images are scanned for:

Blocked generations return status: "blocked" when polled. See our Acceptable Use Policy for details.

FAQ

How do I sign up?

Go to pixelapi.dev/app and click "Sign in with Google". You get 100 free credits instantly โ€” no credit card required.

๐ŸŒ Global Access: PixelAPI works worldwide via Cloudflare CDN. Fastest processing from India, Europe, USA, and APAC regions.

What's a credit?

Credits are our billing unit. Different models cost different credits per generation: SDXL = 3 credits ($0.003), FLUX Schnell = 3 credits ($0.003). Check the models table for full pricing.

Do credits expire?

Monthly credits reset on your billing cycle. Unused credits don't roll over.

How long do generated images stay available?

Output URLs are valid for 24 hours. Download images promptly or store them yourself.

Can I use the images commercially?

Yes. Images you generate are yours to use commercially, subject to our Terms of Service and the underlying model licenses.

Which model should I use?

SDXL is faster and cheaper โ€” great for most use cases, photorealistic images, and fine details. FLUX Schnell excels at artistic/creative styles and complex compositions but takes longer.

Why does FLUX take longer than SDXL?

Is there a webhook / callback option?

Not yet โ€” we use polling. Webhooks are on our roadmap.

Troubleshooting

Getting 403 Forbidden on all requests

Most common issue! Our CDN (Cloudflare) blocks requests that don't have a proper User-Agent header.

Fix: Add a custom User-Agent header to every request:

# Python (requests)
headers = {
    "Authorization": "Bearer YOUR_KEY",
    "User-Agent": "MyApp/1.0"    # โ† Add this!
}

# Python (urllib) โ€” MUST set manually
req = urllib.request.Request(url, headers={
    "Authorization": "Bearer YOUR_KEY",
    "User-Agent": "MyApp/1.0"    # โ† Without this, Cloudflare returns 403
})

# Node.js (fetch)
headers: {
    "Authorization": "Bearer YOUR_KEY",
    "User-Agent": "MyApp/1.0"   // โ† Add this!
}

Default user agents blocked by Cloudflare include: Python-urllib/3.x, python-requests/2.x (sometimes), Go-http-client, and empty user agents.

Getting 401 Unauthorized

Your API key is invalid or missing. Make sure you're using Authorization: Bearer YOUR_KEY (not X-API-Key).

Getting 429 Too Many Requests

You've hit the rate limit for your plan. Wait a few seconds and retry. Check X-RateLimit-Reset header for when the limit resets. Consider upgrading your plan.

Generation stuck in "queued" status

This can happen during high load or when the GPU is swapping models. Wait up to 2 minutes before timing out. If it stays queued beyond that, try again.

Image URL returns 404

Generated images are deleted after 24 hours. If you need the image long-term, download it immediately after generation.

Generation status is "blocked"

Your prompt was flagged by our content safety filter. Review the content policy and modify your prompt. No credits are charged for blocked generations.

Images look different from what I expected

Tips for better prompts:


Need help? Email [email protected] ยท Home ยท Dashboard