API reference · Prepress

The Prepress API.

JSON in, files out. One API key, one credit balance, and seven tools that turn raw customer artwork into clean vectors, print-resolution PNGs, cut-outs and AI product photos. Every result comes back in the response itself.

Start here

One base URL, seven tools.

All requests go to https://api.designmint.intuio.io — no version prefix. Send a JSON body with a public image URL; the answer is the finished result, in the same response: a PNG or JPEG, an SVG inside JSON, or a streamed layout. There is nothing to poll.

RouteReturnsWhat it does
POST /vectorizeJSON · SVGTrace an image to an editable SVG, one path per colour.
POST /upscalePNGEnlarge an image 2× or 4×, alpha and colour profile kept.
POST /remove-bgPNGCut the subject out onto a transparent background.
POST /ai/imagePNGEdit a picture from a prompt, or make new artwork it inspires.
POST /ai/sceneJPEGThe product photo in a described setting, left blank for printing.
POST /ai/lifestylePNGThe product worn or used by a person in a simple, real scene.
POST /ai/templateNDJSON streamA layout of Fabric.js objects for a theme, streamed as it is written.
GET /creditsJSONYour balance and the blocks it is spent from. Free.
GET /healthJSONWhether the service is up. No key needed.
Each call's price is under Credits & limits. Every new account gets 500 free credits for 30 days once its email is verified.
Authentication

A bearer key, on your server.

Every route except GET /health needs an API key as a bearer token: Authorization: Bearer dm_live_…. Create keys in the console. A key is dm_live_ and 32 hex characters, and it is shown once — when you create it or roll it — so store it straight away. A key can carry an expiry date and an IP allowlist of addresses or CIDR ranges.

A missing, wrong, revoked or expired key gets a 401; a key used from an address its allowlist doesn't allow gets a 403. The console's playground calls these same routes as you, signed in, from the same balance.

request
bash
1curl https://api.designmint.intuio.io/remove-bg \2  -H "Authorization: Bearer $DM_KEY" \3  -H "Content-Type: application/json" \4  -d '{"imageUrl":"https://example.com/logo.png"}' \5  -o logo-cutout.png
Keep keys on your server. Browsers may only call the API from the console itself (CORS), so a key in front-end code fails — and leaks. If a key does leak, roll it on the console's API keys page: it gets a new secret and the old one stops working within 30 seconds.
Requests & responses

Send a URL, get the file back.

Every call but the two reads is a POST with a JSON body (Content-Type: application/json, up to 1 MB). Images go in by URL: imageUrl must be a public http(s) address. Private and internal addresses are refused, and so is any redirect to one. An image can be up to 30 MB and 8192 px on a side (8K). The image tools work on it at full size; the AI routes (and ai: true) give it to the model at most 2048 px on a side.

The result is the response body: the picture's bytes for the image and AI routes, JSON for vectorize and the reads, a stream for templates. An AI call takes up to 100 s; an image tool can take minutes when the engine is busy (up to 15). Give your HTTP client a generous timeout: Node's built-in fetch gives up after 5 minutes without an answer (pass an undici Agent({ headersTimeout: 0, bodyTimeout: 0 }) as dispatcher for big jobs).

HeaderSent onDescription
AuthorizationrequestBearer dm_live_… — on every route but GET /health.
Content-Typerequestapplication/json on every POST.
X-Credits-Chargedpaid callsCredits this call cost; 0 when it failed after being charged. Not sent on calls refused before (401, 402, 403, 429).
X-Credits-Remainingpaid callsYour balance after the call.
X-RateLimit-Limitkeyed callsCalls a minute your account may make, all its keys together (every call past the key check).
X-RateLimit-Remainingkeyed callsCalls left in the current minute.
X-RateLimit-Resetkeyed callsSeconds until the minute starts over.
X-Width · X-HeightpicturesPixel size of a PNG or JPEG answer.
Retry-After429 · 503Seconds to wait before trying again.
GET/health

Answers { "ok": true } while the service is up. No key needed, so it suits an uptime check.

Credits & limits

One balance, one limit.

Every call is priced in credits — 1 credit = $0.01. The price is taken up front and refunded if the call fails or you disconnect before it finishes: failed calls are never charged. A balance that can't cover a call gets a 402 — Not enough credits: this call costs 5 and the balance is 4 — and nothing is taken.

CallCreditsTool
POST /vectorize8Vectorize
POST /vectorize · ai: true18Vectorize · AI
POST /upscale5Upscale
POST /upscale · ai: true15Upscale · AI
POST /remove-bg5Remove background
POST /ai/image · mode: "edit"8AI image edit
POST /ai/image · mode: "artwork"10Artworks
POST /ai/scene12Mockup scene
POST /ai/lifestyle12Lifestyle
POST /ai/template3Template
GET /credits · GET /healthfreeBalance and health checks

Credits come in one-time packs that roll over, and calls spend from the pack that expires first.

PackPriceCredits
Starter$202,000 credits · roll over for 3 months
Growth$9910,400 credits · roll over for 6 months
Scale$24927,500 credits · roll over for 12 months
Welcomefree500 credits for 30 days, once a new account’s email is verified

Your account may make 60 calls a minute, shared by all its keys; a busy account can have that raised — contact us. Past the limit you get a 429 with Retry-After, and the call isn't charged. When the service itself is busy it answers 503 with Retry-After: 30.

GET/creditsfree

Your balance and the blocks it is made of, in the order they will be spent. Free, but it counts toward the rate limit. kind is welcome, starter, growth, scale or grant; expiresAt is a Unix time in milliseconds.

200
json
1{2  "balance": 8412,3  "blocks": [4    { "id": "blk_3f9a1c2e", "kind": "welcome", "remaining": 312, "expiresAt": 1793404800000 },5    { "id": "blk_8d04b7a1", "kind": "growth", "remaining": 8100, "expiresAt": 1806537600000 }6  ]7}
Image tools

Fix the artwork before the press does.

Three single-purpose tools. Each takes one imageUrl and answers with the result.

POST/vectorize8 credits · 18 with ai

Traces an image to SVG with one path per colour, so it is easy to recolour and edit. Uploads under 2000 px are upscaled to 2000 px before the trace.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the image.
colorsint · 12Number of colours to trace, 1–32.
aiboolean · falseFirst have AI recreate a barely usable upload (small, blurry, compressed) as a clean 2K original, then trace that. Colours can shift a little.
request
bash
1curl https://api.designmint.intuio.io/vectorize \2  -H "Authorization: Bearer $DM_KEY" \3  -H "Content-Type: application/json" \4  -d '{"imageUrl":"https://example.com/logo.png","colors":6}' \5  | jq -r .svgString > logo.svg
200
json
1{ "svgString": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 2000 857\">…</svg>" }
POST/upscale5 credits · 15 with ai

Enlarges an image and answers with a PNG — alpha and colour profile kept — its size in X-Width and X-Height. The input can be at most 4.2 MP (2048 × 2048 px, in any shape) and the result at most 8192 px on a side; past either you get a 413.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the image.
scale2 | 4 · 4How many times larger.
aiboolean · falseAnswer with the AI’s clean 2K recreation of the upload instead, flattened on white (no transparency); scale and the 4.2 MP limit don’t apply.
POST/remove-bg5 credits

Cuts the subject out and answers with a PNG on a transparent background, at least 2000 px on its longest side (smaller uploads are upscaled first), colour profile kept.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the image.
request
bash
1curl https://api.designmint.intuio.io/remove-bg \2  -H "Authorization: Bearer $DM_KEY" \3  -H "Content-Type: application/json" \4  -d '{"imageUrl":"https://example.com/logo.png"}' \5  -o logo-cutout.png
AI tools

Describe it, get the picture.

Four routes on Gemini. Each answers with the finished picture; a template streams its layout. When the AI sends no picture back (it declined the prompt or the image) you get a 422; when Google rejects the request, or a template gets no text, a 502; when it is busy, a 503 with Retry-After: 30; past 100 s, a 504. None is charged.

POST/ai/image8 edit · 10 artwork

A picture and a prompt in, a PNG out. edit answers with the picture edited, at 1K. artwork makes standalone artwork the picture only inspires, at 2K, its plain border trimmed.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the picture.
promptstringWhat to change or make — at most 50 words.
mode"edit" | "artwork" · "edit"edit costs 8 credits, artwork 10.
POST/ai/scene12 credits

Puts the product photo in the setting you describe and answers with a 2K JPEG, in the shape nearest the photo's. The product is left blank — no print, logo or text — ready for a design to go on.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the product photo.
promptstringThe setting — at most 2000 characters.
referenceUrlstring?A mood reference: only its setting, light and mood are used.
sceneUrlstring?Another colour’s (or side’s) scene to recreate for this photo. Send referenceUrl or sceneUrl, not both.
tone"gray"?Show the product in a light neutral gray, ready for recolouring.
POST/ai/lifestyle12 credits

The product photo worn or used by a person in a simple, real scene, as a 1K PNG.

FieldTypeDescription
imageUrlstringPublic http(s) URL of the product photo.
scenestring?A theme for the setting, e.g. "coffee shop".
techniquestring?The print technique on the product, e.g. "embroidery".
logoUrlstring?A logo to add as a small watermark. SVG logos work.
POST/ai/template3 credits

A theme in, a layout out: one JSON array of Fabric.js objects sized to your canvas, streamed as application/x-ndjson while the AI writes it. Collect the text and parse the array when the stream ends. An error before the first text is an ordinary status with { "detail" }; after it, the stream ends with a last line {"error":"…"} — the status is already 200, but the call is refunded all the same.

FieldTypeDescription
promptstringThe theme — at most 50 words.
widthnumberCanvas width in px.
heightnumberCanvas height in px.
fontsstring[] · []Font families the layout may use.
200 · streamed
json
1[2{"type":"rect","left":0,"top":0,"width":720,"height":1080,"fill":"#0f1620"},3{"type":"textbox","text":"Summer Market","fontFamily":"Raleway","fontWeight":"700","fontSize":64,"fill":"#f4f1ec","left":60,"top":120,"width":600}4]
Errors

Plain codes, plain messages.

Every error is JSON with one field, detail: a sentence you can log or show. A 422 for a bad body names the field, as field: message. No failed call is charged: X-Credits-Charged is 0, or absent when the call was refused before any credit was taken.

4xx / 5xx
json
1{ "detail": "Not enough credits: this call costs 5 and the balance is 4" }
StatusWhenWhat to do
400imageUrl isn’t a public http(s) URL, the download failed, the file isn’t a readable image, a prompt is over 50 words, or the body isn’t valid JSON.Check the URL opens in a browser and points straight at the image; shorten the prompt.
401No key, or a wrong, revoked or expired one.Check the Authorization header; create or roll a key in the console.
402The balance is short of the call’s price.Buy a credit pack. Nothing was taken.
403The key was used from an address its allowlist doesn’t allow.Add the address or range to the key’s allowlist.
404Unknown route.Check the path — there is no version prefix.
413Over 30 MB or 8192 px on a side, a JSON body over 1 MB, or an upscale past its limits.Send a smaller image, or a lower scale.
422A bad body (a field missing or wrong), or the AI sent no picture back.Read detail: it names the field; for no picture, reword the prompt or try another image.
429Over your account’s calls a minute (60 unless raised), all keys together.Wait Retry-After seconds, then retry.
500Anything else.Retry; if it keeps happening, tell us.
502Google rejected the AI request, a template got no text back, or the image engine is down.Retry later.
503The service is busy.Wait Retry-After (30) seconds, then retry.
504The AI or the image engine took too long.Retry, or send a smaller image.
From Node

Or skip the curl.

No client library needed: fetch in Node 18 and later does it. Read the bytes for a picture, res.json() for vectorize and the reads.

remove-bg.mjs
js
1import { writeFile } from "node:fs/promises"2​3const res = await fetch("https://api.designmint.intuio.io/remove-bg", {4  method: "POST",5  headers: {6    Authorization: `Bearer ${process.env.DM_KEY}`,7    "Content-Type": "application/json",8  },9  body: JSON.stringify({ imageUrl: "https://example.com/logo.png" }),10})11​12if (!res.ok) {13  const { detail } = await res.json()14  throw new Error(`${res.status}: ${detail}`)15}16​17await writeFile("logo-cutout.png", Buffer.from(await res.arrayBuffer()))18​19console.log(res.headers.get("X-Width"), "x", res.headers.get("X-Height"))20console.log("charged", res.headers.get("X-Credits-Charged"), "left", res.headers.get("X-Credits-Remaining"))

Questions about the API, or need a tool that isn't here yet? Write to designmint@intuio.io.