Migrate from the OpenAI Image API to PixelFireman | PixelFireman
MIGRATION GUIDE

Migrate from the OpenAI image API to PixelFireman

You are already generating images with OpenAI (DALL·E 3 or gpt-image-1). PixelFireman is a standard REST image API with Bearer auth, so for most integrations you change the base URL and one response-reading line. This page maps every request parameter and response field, calls out what is different, and gives you a working before/after example.

The short version: keep your prompt, point at https://pixelfireman.com/v1/images, send your pf_live_ key, and read data.image instead of data.data[0].url. Branch on format (url vs svg) and read creditsUsed to track spend.

Why switch

Request parameter mapping

OpenAI’s POST /v1/images/generations maps to PixelFireman’s POST /v1/images:

OpenAIPixelFiremanNotes
promptpromptSame. Keep your prompt text as-is.
model (e.g. "dall-e-3", "gpt-image-1"), (omit)PixelFireman picks the engine. The model field here means your own trained style model id, not an OpenAI model name. Drop the OpenAI model string.
size ("1024x1024", "1024x1792", "1792x1024")size ("1024x1024", "1024x1536", "1536x1024")Same WIDTHxHEIGHT string format. Use PixelFireman’s nearest ratio. Max 2048×2048. Credits scale with megapixels.
n, (not supported)One image per call. Loop the request n times client-side.
quality ("standard"/"hd"), (not supported for photos)No photo quality switch. (draw mode accepts quality: "high" for richer SVG only.)
style ("vivid"/"natural"), (fold into the prompt)Express style in the prompt text, e.g. “natural lighting, muted colours”.
response_format ("url"/"b64_json"), (always a URL or SVG)No base64 option. Read format + image (see below) and download the URL if you need bytes.
, (none)mode ("auto"/"generate"/"draw")New. generate = photo, draw = flat SVG vector, auto = server picks. Defaults to auto.

Authentication mapping

Both use a Bearer header, so this line barely changes:

OpenAIPixelFireman
Authorization: Bearer sk-...Authorization: Bearer pf_live_...
OpenAI-Organization header, (not used)

PixelFireman also accepts x-api-key: pf_live_... as an alternative. Get your key in the account dashboard.

Response field mapping

OpenAI nests the result under data[]. PixelFireman returns a flat object, read image directly and lead on creditsUsed for billing.

OpenAIPixelFiremanNotes
data[0].urlimage (when format === "url")Flat, not an array. One image per call.
data[0].b64_json, (none)No base64. Fetch the image URL to get bytes.
data[0].revised_prompt, (none)Not returned.
, (billed on your OpenAI invoice)creditsUsedWhat this call cost you, in credits. Read this to track spend.
, (none)usage.creditsLeftYour remaining balance after the call.
, (none)format ("url"/"svg")Always branch on this before using image.
, (none)engine, costInformational. cost is our internal provider cost in USD, not your price, you pay in credits. Safe to ignore.

Before / after: a working example

The same “generate and save a PNG” task, in Node 18+ fetch.

BEFORE OpenAI
import fs from "node:fs";
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const r = await openai.images.generate({
  model: "dall-e-3",
  prompt: "a red fox sitting in autumn leaves",
  size: "1024x1024",
  n: 1,
});

const url = r.data[0].url;
const img = await fetch(url);
const buf = Buffer.from(await img.arrayBuffer());
fs.writeFileSync("output.png", buf);
console.log("Saved output.png");
AFTER PixelFireman
import fs from "node:fs";

const API_KEY = process.env.PF_API_KEY;

const res = await fetch(
  "https://pixelfireman.com/v1/images", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    prompt: "a red fox sitting in autumn leaves",
    mode: "generate",
    size: "1024x1024",
  }),
});

if (!res.ok) {
  const e = await res.json().catch(() => ({}));
  throw new Error(`HTTP ${res.status}: ${e.error}`);
}

const data = await res.json();
console.log("credits used:", data.creditsUsed,
            "left:", data.usage.creditsLeft);

if (data.format === "url") {
  const img = await fetch(data.image);
  const buf = Buffer.from(await img.arrayBuffer());
  fs.writeFileSync("output.png", buf);
} else {
  fs.writeFileSync("output.svg", data.image);
}
console.log("Saved output");

The real changes: no SDK, the endpoint URL, read data.image (not data.data[0].url), and branch on data.format. Everything else is your existing prompt and size.

Unsupported features & how to handle them

OpenAI featureOn PixelFiremanWhat to do
n > 1 (batch)Not supportedLoop the request. Respect the limits: 120 requests/min and 6 concurrent per key.
b64_json responseNot supportedFetch the returned image URL to get bytes.
Image edits / inpainting (/images/edits)Different endpointUse POST /v1/images/edit with images[] (data URIs or https URLs). Costs more credits per megapixel. See the API docs.
Variations (/images/variations)Not supportedRe-prompt, or train a custom style model for a consistent look.
quality: "hd", styleNot supported for photosFold intent into the prompt text.
Streaming / partial imagesNot supportedSingle response per call.

Error handling mapping

Both return a JSON body on error. OpenAI nests it under error.message; PixelFireman returns a flat { "error": "..." }. Status codes line up closely:

StatusOpenAIPixelFiremanHandling
400Invalid requestMissing prompt or size over 2048×2048 capFix the body. Do not retry unchanged.
401Bad API keyInvalid or missing keyCheck the Authorization header. No credits charged.
402, (billing via plan)Out of credits (noCredits: true)Top up in the dashboard. May include creditsNeeded.
429Rate limitRate (120/min) or concurrency (6) limitBack off and retry; a Retry-After header is set.
400/451Content policy (content_policy_violation)Moderation block, 451 (moderated: true)Reword the prompt and retry. The message starts with Blocked:.
500Server errorServer errorRetry with exponential backoff. No credits charged on failure.

A migration-friendly read: OpenAI code that checks res.ok and reads err.error.message should read err.error (a string) on PixelFireman. Billing never happens on a failed, blocked, or unauthorised request.

Quality tradeoffs, stated plainly

PixelFireman photo generation runs on FLUX.1 [schnell], a different model from DALL·E 3 / gpt-image-1. Honest expectations:

The goal is not “identical output”, it is generating images for the same publishing workload at a lower cost.

Pricing at a glance

PackPriceImage creditsPer 1,000
Starter$101,400~$7.14
Plus$253,750~$6.67
Pro$508,000~$6.25

A 1024×1024 image is 1 credit; credits scale with megapixels (rounded up, min 1). Best rate ($0.00625 / image) is on the $50 Pro pack. Prepaid, no subscription, credits never expire. The 6× comparison is against OpenAI’s standard $0.04 image rate (DALL·E 3, 1024×1024, standard quality, as of October 2026).

Ready to switch?

Grab a pf_live_ key, change your base URL to https://pixelfireman.com/v1/images, and read data.image. The full reference, including async video and custom models, is in the API docs.

Get an API key