ProImageTools

AI Studio

One API for every
image and video model.

Stop wiring up a new SDK for every provider. One key, one request shape, one catalogue — image, video, audio and text models behind a single REST endpoint, with an async queue and webhooks that tell you when the work is done.

Start free — 50 credits Read the API

No card required. The free plan stays free.

POST /v1/generate.php
curl -X POST https://api.proimagetools.com/v1/generate.php \
  -H "Authorization: Bearer pit_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"model":"flux-dev",
      "params":{"prompt":"a red fox in snow"},
      "webhook_url":"https://you.example/hook"}'
response
{
  "success": true,
  "id": 4821,
  "status": "queued",
  "credits_charged": 2,
  "credits_remaining": 3496,
  "eta_seconds": 6
}
Models routed from
  • FLUX
  • Stable Diffusion
  • Google
  • OpenAI
  • Runway
  • Kling
  • Bytedance
  • + open source

Why it exists

The plumbing is already built.

Generation is the easy part. Queues, retries, refunds, idempotency and archival are what actually take the month. They ship with the key.

One catalogue, one contract

Every model exposes the same request shape and a machine-readable parameter schema. Fetch /v1/models.php, pick a slug, send it. Swapping models is changing a string, not rewriting an integration.

Async by default

Submissions return immediately with a job id and an ETA. Poll /v1/status.php or supply a webhook_url and be told — redelivered up to five times with backoff if your endpoint blinks.

Failures cost nothing

A job that fails is refunded automatically — enforced at the state transition and written to an append-only ledger, not left to a support ticket. Reconciled against your balance every night.

Fair, priority queueing

Capacity is shared and finite — position in line is the thing worth paying for. Your plan sets queue priority and how many jobs run at once, dispatched so that one busy account cannot starve another.

Keys that behave

Header-only authentication — a key in a URL or request body is rejected outright, so it never lands in browser history, a Referer header, or an access log. Label and rotate keys from the panel.

Safe to retry

Send an Idempotency-Key and a repeated submission returns the original job instead of billing you twice. Omit it and identical prompts create genuinely separate jobs — which is what you want for seed variations.

How it works

Three calls, start to finish.

  1. 1

    Browse the catalogue

    GET /v1/models.php returns every published model with its credit cost, typical runtime and parameter schema. Models above your plan stay visible and are flagged locked, so you always see what an upgrade buys.

  2. 2

    Submit a job

    POST /v1/generate.php validates your parameters against that schema, prices the job server-side, charges credits inside a transaction and queues it. You get an id back in milliseconds.

  3. 3

    Collect the output

    Take the webhook, or poll GET /v1/status.php?id=… until done. Finished assets are archived and served from a stable URL of ours — not a provider link that expires underneath you.

The API

Boring on purpose.

Plain REST over HTTPS, JSON in and out, bearer auth. No SDK to install, no streaming protocol to learn, nothing that will not work from a shell script.

GET /v1/models.php

The catalogue, filtered to what your plan can call.

POST /v1/generate.php

Queue a generation. Returns an id, the cost and an ETA.

GET /v1/status.php

Job state and, once finished, the output URLs.

GET /v1/account.php

Balance, plan entitlements, live rate and queue position.

Poll until done
curl -H "Authorization: Bearer pit_live_xxx" \
  "…/v1/status.php?id=4821"

{
  "success": true,
  "id": 4821,
  "status": "success",
  "done": true,
  "output": ["…/assets/2026/08/143022.jpg"],
  "wait_seconds": 3,
  "credits_charged": 2,
  "refunded": false
}

Typed errors

Every failure carries a stable codeinsufficient_credits, rate_limit, queue_depth, model_requires_upgrade — so retry logic can branch on it. Rate limit and queue depth are deliberately separate: one means slow down, the other means wait for the jobs you already have.

Webhooks that cannot point inward

Delivery targets must be publicly reachable http(s). Private and loopback ranges are rejected, so a webhook URL can never be turned into a request against internal infrastructure.

A playground for the awkward part

Every model's parameters are runnable from the browser in the panel. Get the call right there, then copy it into code.

Credits, priority, concurrency

Each model publishes its own credit cost. A plan grants credits every month — and, more importantly, buys a better place in the queue and more jobs running at once. Top-up packs stack on top and never expire. See full pricing.

  • Free — 1 job, 5/min50 cr/mo
  • Starter — 2 jobs, 20/min900 cr/mo
  • Pro — 4 jobs, 60/min3,500 cr/mo
  • Business — 8 jobs, 200/min14,000 cr/mo

Questions

The things people ask first.

What is a credit worth?

It depends on the model, and each model tells you before you call it. A fast image model costs a credit or two; a long video clip costs considerably more. Cost is computed server-side from the model's price and your parameters — asking for four samples costs four times one, and a thirty-second clip costs six times a five-second one. A cost supplied by the client is never trusted.

What happens when a generation fails?

You are refunded automatically. The refund is enforced at the moment the job is marked failed, keyed so it can only happen once, and written to an append-only ledger. A nightly reconciliation checks that ledger against your balance and repairs any drift — so a missed refund is something we catch, not something you report.

Do credits expire?

Plan credits are granted monthly and do not roll over. Credits bought as top-up packs never expire and sit on top of your monthly allowance.

What am I actually paying for on a plan?

Credits, queue priority and concurrency. Capacity is shared and finite, so priority is the part that matters under load — it decides whether your job runs now or after everybody else's. Concurrency decides how many of yours run at the same time.

Can I use my own webhook endpoint?

Yes. Pass webhook_url on submission and you get a POST when the job finishes, retried up to five times with backoff if delivery fails. The URL has to be publicly reachable over http(s); private and loopback addresses are rejected.

Get a key and send one request.

Free account, 50 credits, no card. If it does not fit in an afternoon, it is not the API we meant to build.

Start free Sign in