Most developers who want to build image generation saas already have the core loop working: submit a prompt, get an image back. That is the easy 10%. What they do not have is the layer that turns a generator into a business — multi-tenant accounts, scoped API keys, usage metering, billing. That layer is the actual product, and it is where most builds stall.

This guide covers the SaaS layer specifically: the tenant model, the key model, metering, and billing hooks. The generation engine underneath is a separate problem, and if you have not designed its queue and worker architecture yet, read how to build an AI image generation platform first — it walks the four subsystems that everything here sits on top of.

Disclaimer

Nextjourney is not affiliated with Midjourney or Discord. There is no official Midjourney API — Midjourney has no public API — so any platform that generates Midjourney images automates Discord user accounts, which operates outside Discord's Terms of Service. That constraint applies to every implementation, yours included.

The generator is not the SaaS

A generator is a pipeline: queue a job, a worker submits it upstream, the result comes back. A SaaS is everything around that pipeline that lets a stranger hand you money without breaking your system. For a provider-specific example, compare this layer with the OpenAI Images API SaaS guide: the provider adapter changes, but tenancy, metering, and delivery remain product responsibilities:

  • Tenants — each customer org gets isolated accounts, keys, and quotas.
  • Auth — scoped API keys per tenant, not one shared secret.
  • Metering — exactly how many images each tenant consumed, idempotently counted.
  • Billing hooks — usage rolls into invoices or credit exhaustion.
  • Admin dashboard — you can see live jobs, failing accounts, and per-tenant spend.

Build those five and you have a product. Skip them and you have a demo with an API key in a .env file — impressive to exactly one person.

Build image generation SaaS: start with the tenant model

Every design decision downstream depends on how you model a tenant, so get this right before writing a single endpoint. The shape that works for image platforms is three tables: tenants, users, and api_keys, with api_keys scoped per tenant and per permission scope.

CREATE TABLE tenants (
  id            UUID PRIMARY KEY,
  name          TEXT NOT NULL,
  status        TEXT NOT NULL DEFAULT 'active',   -- active | suspended
  monthly_limit INT  NOT NULL DEFAULT 1000,
  created_at    TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE api_keys (
  id         UUID PRIMARY KEY,
  tenant_id  UUID NOT NULL REFERENCES tenants(id),
  name       TEXT NOT NULL,
  key_hash   TEXT NOT NULL UNIQUE,   -- store a hash, never the raw key
  scopes     TEXT[] NOT NULL DEFAULT '{generate}',
  revoked    BOOL NOT NULL DEFAULT FALSE,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Two details matter here. First, store a hash of the API key, never the key itself — a leaked database dump should not leak every customer's access. Second, keep monthly_limit on the tenant, not on individual keys, so limits survive key rotation. When a customer's key is compromised you rotate one row instead of renegotiating a quota.

Tenant isolation then flows through everything: rate limits are per tenant, usage records are per tenant, and the admin dashboard groups by tenant. If you design the schema this way from the start, adding a new tenant is a row insert, not a refactor.

Meter usage the way payment providers do

The classic mistake is counting usage at submission time. A job can be submitted and fail five minutes later; counting it then charges customers for images they never received. Meter on job completion, and make each ledger entry idempotent so retries never double-charge.

{
  "tenant_id": "9f3b...",
  "job_id": "job_01HZ...",
  "event": "image.completed",
  "credits": 1,
  "model": "mj-v6",
  "occurred_at": "2026-08-30T02:41:07Z"
}

A credits ledger like this — an append-only event log, not a mutable counter — gives you three things for free: exact per-tenant usage reports, a billing audit trail, and the ability to reprocess history when a pricing model changes. On every completion the worker appends an event and then checks the tenant's running total against monthly_limit. When the limit hits, the queue stops accepting that tenant's jobs with a clear 403 and a message telling them why.

The other half of metering is per-tenant rate limiting on your own API. A single customer looping on your endpoint can burn your upstream account pool in minutes. Cap concurrency per tenant (e.g., 2-4 concurrent jobs) and enforce a global queue cap so one bad tenant cannot starve everyone else.

Billing hooks and the credit model

For most image SaaS products, the sane unit is a credit — one credit per generated image (or per image at a given resolution). Customers buy credits in batches, and the metering layer decrements them on completion, which is far easier to explain than "you owe us for 1,847 GPU-seconds."

A billing hook is a webhook you fire when a tenant's balance crosses thresholds: low balance, exhausted balance, invoice due. Exhausted balance should pause the queue, not fail jobs mid-flight — let in-flight jobs finish, reject new submissions with a 402-style error, and tell the tenant exactly which endpoint to call to top up. Silent failures are how you lose trust; explicit stops are how you keep it.

If you are building the renting model, you also own subscription management, payment processor integration, and invoice generation forever. That is real scope. If your goal is the platform itself rather than the payments business around it, the honest alternative is a one-time license where customers run the stack themselves — the self-host vs API reseller comparison lays out both models side by side.

The API surface your tenants will judge you on

Tenants will not read your docs before deciding whether to integrate — they will read your auth model and error codes. The Midjourney REST API guide covers the endpoint and auth shape in depth; the SaaS-specific additions are subtle but critical:

  • Every endpoint validates the key's scopes — a read-only key cannot submit jobs.
  • 429 responses include a Retry-After header with the tenant's cooldown, not a fixed value.
  • 403 distinguishes suspended tenant from quota exhausted via an error code field.
  • Webhook deliveries are at-least-once with an idempotent consumer, and the tenant sees delivery history in the dashboard.

Get those four right and your API feels production-grade on day one. Get them wrong and your customers will find out before you do.

The build order that actually ships

When you sit down to build, resist the urge to start with the dashboard. The order that ships is:

  1. Tenant + API key schema and auth middleware
  2. Per-tenant rate limiting and the credits ledger
  3. Metering on job completion + limit enforcement in the queue
  4. Billing webhooks (low balance, exhausted, invoice)
  5. Admin dashboard last — it is reporting over data you already have

Each step is independently testable, and each one de-risks the next. The dashboard is the fun part; it is also the part with zero architectural risk, which is exactly why it belongs last.

What it costs to get there

Path Time to launch Recurring cost Ownership Risk
Build everything (engine + SaaS layer) 6-12 months VPS + upstream subs Full Upstream changes chase you forever
License the engine, build the SaaS layer Days-weeks VPS + upstream subs Full You own it
Rent a reseller API Hours Per-image fees forever None Vendor can shut down

The middle row is the one most product builders overlook: you do not have to choose between renting and rebuilding. If the engine is already production-tested source code and your job is the tenant model, metering, and billing, the timeline collapses from a year to a few weeks. The midjourney API pricing breakdown shows why the rent-everything path gets expensive fast at volume, and the deployment guide covers what running the licensed stack looks like day to day.

Skip the 6-12 month engine build

Production-tested source code — backend, frontend, REST API, admin dashboard, multi-account support. One-time license from $399, no recurring platform fees.

See pricing

The SaaS layer is where your product's value lives. Build that layer with the tenant model, honest metering, and explicit billing — and let the generation engine be something you own rather than something you spend a year reinventing.

Not affiliated with Midjourney or Discord.