AI API for Indie Hackers, Packs From $5
Ship an AI feature on a small budget. Buy a pack from $5, call the API from your backend, and pay only for what you generate.
API calls need credits. Packs from $5.
curl -X POST https://api.picxstudio.com/v1/images/generate \
-H "Authorization: Bearer $PICX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"prompt":"a beautiful sunset over the ocean, cinematic lighting","model":"gemini-3.1-flash-image-preview","size":"2K","aspect_ratio":"16:9"}'Example response
{
"id": "img_abc123def456",
"url": "https://cdn.picxstudio.com/generated/abc123.png",
"model": "gemini-3.1-flash-image-preview",
"size": "2K",
"aspect_ratio": "16:9",
"credits_used": 53,
"created_at": "2026-06-17T20:00:00Z"
}import { PicX } from "picx-ai";
const picx = new PicX(process.env.PICX_API_KEY);
const asset = await picx.images.generate({
prompt: "a beautiful sunset over the ocean, cinematic lighting",
model: "gemini-3.1-flash-image-preview",
size: "2K",
aspect_ratio: "16:9",
});
console.log("Image URL:", asset.url);
console.log("Credits used:", asset.credits_used);Example response
{
"id": "img_abc123def456",
"url": "https://cdn.picxstudio.com/generated/abc123.png",
"model": "gemini-3.1-flash-image-preview",
"size": "2K",
"aspect_ratio": "16:9",
"credits_used": 53,
"created_at": "2026-06-17T20:00:00Z"
}import os
from picx import PicX
picx = PicX(os.environ["PICX_API_KEY"])
asset = picx.images.generate(
prompt="a beautiful sunset over the ocean, cinematic lighting",
model="gemini-3.1-flash-image-preview",
size="2K",
aspect_ratio="16:9",
)
print("Image URL:", asset.url)
print("Credits used:", asset.credits_used)Example response
{
"id": "img_abc123def456",
"url": "https://cdn.picxstudio.com/generated/abc123.png",
"model": "gemini-3.1-flash-image-preview",
"size": "2K",
"aspect_ratio": "16:9",
"credits_used": 53,
"created_at": "2026-06-17T20:00:00Z"
}https://mcp.picxstudio.com/
# from the terminal, once the CLI is installed
picx mcp install
picx mcp doctor- Credits never expire
- Failed generations refunded automatically
- Commercial use on every plan
- No auto-renew on crypto
An example result, and what it costs
Every response tells you the credits used, and agents can list each model’s price before spending anything.
Get API key
Ways to integrate
One key and one balance across all four.
REST API
Generate and edit images and video over HTTPS. Sync by default, webhooks when you want them.
QuickstartMCP server
Let Claude, ChatGPT, Cursor, VS Code or Codex call PicX tools directly, signed in with your account.
Connect a clientCLI
picx-cli for the terminal and for agents that shell out. Every command speaks --json.
Install the CLISDKs
Typed clients for JavaScript/TypeScript (picx-ai on npm) and Python (picx-ai on PyPI).
SDK examples
A weekend build, then a launch checklist
A cover image generator in Next.js with TypeScript. Paste these files into an app and it runs once your key has credits.
Install the SDK
One package. It reads the key from the environment.
terminalnpm install picx-aiAdd your key
Buy a pack on the credits page, then create a key on the keys page. A new key has 0 credits until you do.
.env.local# .env, server only. Never send this key to the browser. PICX_API_KEY=pxsk_your_keyCheck the price before you spend
The price comes from the live catalog, so a repricing never breaks your math.
lib/picx.tsimport { PicX } from "picx-ai"; export const picx = new PicX(process.env.PICX_API_KEY); export const MODEL = "gemini-3.1-flash-image-preview"; export const SIZE = "1K" as const; // Read the live price, and refuse early if the balance can't cover it. export async function canAfford() { const [models, account] = await Promise.all([ picx.models.listAll({ type: "image" }), picx.account.me(), ]); const price = models.find((m) => m.id === MODEL)?.credits[SIZE]; const balance = account.credits?.balance ?? 0; return { price, balance, ok: typeof price === "number" && balance >= price }; }Add the backend route
The key stays on your server. The browser only ever talks to this route.
app/api/generate/route.tsimport { randomUUID } from "node:crypto"; import { PicXInsufficientCreditsError } from "picx-ai"; import { MODEL, SIZE, canAfford, picx } from "@/lib/picx"; export async function POST(req: Request) { const { prompt } = await req.json(); const { ok, price, balance } = await canAfford(); if (!ok) return Response.json({ error: "out_of_credits", price, balance }, { status: 402 }); try { const image = await picx.images.generate( { prompt, model: MODEL, size: SIZE, aspect_ratio: "16:9" }, // With a key, the SDK can safely retry a dropped connection. { idempotencyKey: randomUUID() }, ); return Response.json({ url: image.url, credits: image.credits_used }); } catch (err) { if (err instanceof PicXInsufficientCreditsError) { return Response.json({ error: "out_of_credits" }, { status: 402 }); } throw err; } }Add the page
The smallest UI that works. Style it later.
app/page.tsx"use client"; import { useState } from "react"; export default function Page() { const [url, setUrl] = useState<string>(); const [busy, setBusy] = useState(false); async function submit(form: FormData) { setBusy(true); const res = await fetch("/api/generate", { method: "POST", body: JSON.stringify({ prompt: form.get("prompt") }), }); const data = await res.json(); setUrl(data.url); setBusy(false); } return ( <form action={submit}> <input name="prompt" required placeholder="Describe your cover image" /> <button disabled={busy}>{busy ? "Working..." : "Generate"}</button> {url && <img src={url} alt="Generated cover" />} </form> ); }Add video when you are ready
Video runs as a job: submit, keep the id, take a webhook or poll. The SDK page has the full example with the webhook route.
Launch checklist
Webhooks
- Reply 2xx within 10 seconds and do slow work later. Delivery tries 3 times, waiting 1 second and then 2.
- Deliveries can repeat. Dedupe on the
X-PicX-Deliveryheader. - Save the generation id at submit, and keep
GET /v1/generations/{id}as your fallback if a delivery never lands. - Treat the POST as a hint and read the result from the API with your key, or verify
X-PicX-Signatureon a webhook registered in the console.
Retries
- The SDKs retry 429s, 5xx and dropped connections for you, but only on GETs and on POSTs that carry an idempotency key.
- On a 429, wait for
Retry-After. - A failed generation has already been refunded. Retry it as a new request with a new key.
Idempotency
- Create one key per user action and store it before you call the API.
- A replay of a finished request returns the original result and charges nothing.
- A sync image replayed while the first call is still running gets a 503. Back off and try again.
Limits and money
- Read your limits from
GET /v1/account/tier: requests per minute and per day, concurrent jobs, and the daily credit cap. - Handle 402 with a clear message. The body gives your balance and the credits required.
- Check the balance on a schedule and top up before it reaches zero.
- Use a separate key per environment, and grant each only the scopes it needs.
Pick a model
Live from GET /v1/models. Credits are for one generation; video is priced per second.
Built for production
Webhooks
Register an endpoint, or bind one to a single job, and get a POST when it finishes.
Webhooks docsAsync polling and SSE
Video returns a job id at once. Poll GET /v1/generations/{id} or stream its events_url.
Video referenceidempotency_key
Retry a request safely. A replay returns the original generation and charges nothing.
QuickstartRefunds on failure
When a generation fails, its credits go back to your balance automatically.
Credit pricing
Rate limits
Limits apply per key. Read your exact values from GET /v1/account/tier, and honor Retry-After on a 429. Rate limit docs
What you can build
What the terms allow, in plain English.
| Use | Status | Details |
|---|---|---|
| Ads, listings and client work made with outputs | Allowed | On every plan |
| Selling prints or merchandise made with outputs | Allowed | Terms section 5 |
| An AI feature inside a different product, through the API | Allowed | Use your own key on your own backend |
| Reselling raw capacity | Allowed | See the partners page |
| A substantially similar generator built on PicX | Allowed | See the partners page |
| Sharing or reselling API keys, or transferring credits | Not allowed | Terms sections 3 and 4.1 |
Full wording in the Terms of Service.
Start at the price of a coffee
Credit packs from $5 with no plan needed, or plans from $11.99/month. Crypto only: no card, no KYC.
$5
500 credits
$9
1,000 credits
$29
3,200 credits
$59
6,500 credits
The API and MCP spend the same credits as the app. See all prices · How paying with crypto works
Developer FAQ
Do I need a subscription?
No. Packs start at $5 with no plan, and credits never expire, so a side project can sit idle for months without losing anything.
What happens to credits when a generation fails?
Credits are taken when you submit, and they go back to your balance automatically if the generation fails. The failed generation's error_message tells you why.
Can I use this inside my own app?
Yes. An AI feature inside your product, through the API, is allowed. Call PicX from your backend with your own key. Sharing or reselling API keys, or transferring credits, is not allowed.
Which models can I call, and how do I pick?
GET /v1/models lists every model id with its credit price, and it needs no key. Pass the id as model. Pick by the price at your size and by the output you want. The playground is a quick way to compare them once you have credits.
Can my agent see prices before spending?
Yes. GET /v1/models returns each model's credit price without a key, and the MCP server has the same list as the picx_list_models tool. An agent can read the price and your balance before it spends anything.
How do I pay without a card?
Pay with crypto: it is the only checkout. 18 coins are accepted, including BTC, USDT, ETH and SOL. There is no KYC and nothing renews by itself.
How do I stop a bug from draining my balance?
Packs are prepaid, so spend stops at zero and the API answers 402. Inside that, check the price and balance before each call, cap requests per user in your own app, and read the daily credit cap from GET /v1/account/tier.
Can this run on serverless?
Yes. For images on a short timeout, pass callback_url so the call returns a job id at once. Video always works that way.
Is there a startup plan?
Startups and solo builders use the same packs, plans and API. Start with a pack, and move to a plan if a monthly refill suits you better.

Ship it this weekend
Get a key, buy a pack from $5, and make your first call.