API reference · Prepress · v1 preview

The Prepress API.

REST in, files out. One API key, one credit balance, and a set of endpoints that turn raw customer artwork into press-ready files, previews and mockups for every technique you run. Everything heavy is a job; everything is JSON.

Start here

One base URL, nine things it does.

All requests go to https://api.designmint.intuio.io/v1. The API does one job: take an image and hand back something a press, a marketplace or a customer can use. It groups into image services (fix the artwork), validation (check it against a technique), previews (mockups and scenes) and pipelines (the whole chain in one call).

EndpointCreditsWhat it does
POST /images/upscale5 / imageRaise a low-res upload to print resolution.
POST /images/sharpen5 / imageRecover edge detail on soft artwork.
POST /images/remove-background5 / imageIsolate the artwork on transparency.
POST /images/vectorize8 / imageTrace to clean SVG — logos, lettering, illustration.
POST /images/quantize8 / imageReduce to N spot colours, palette returned.
POST /images/validate8 / imageDPI, bleed and technique checks, each with a fix.
POST /mockups8 / imageArtwork on a product photo, per placement.
POST /scenes12 / imageA mockup placed in a lifestyle scene.
POST /pipelines/{technique}25 / runPrep → separations → press-ready files, end to end.
v1 preview. The endpoints, fields and responses on this page are the intended contract. Details may change before the API is generally available; the shapes will not.
Authentication

A bearer key, per project.

Every request carries an API key as a bearer token. Keys are issued when you buy a credit block and live in your account; each key is its own project with its own credit balance and rate limit. Keys starting dm_test_ run against the sandbox — same responses, watermarked outputs, no credits charged.

request
bash
1curl https://api.designmint.intuio.io/v1/account/credits \2  -H "Authorization: Bearer dm_live_9f3a…c21e"
Keep keys server-side. If one leaks, rotate it from the account page — the old key stops working immediately and in-flight jobs finish on the new one.
Requests & jobs

Send a file, get a job.

Inputs are either a public or signed source_url in a JSON body, or the file itself as multipart/form-data under file. PNG, JPEG, WebP, SVG, PDF, PSD, AI, EPS and CDR are accepted, up to 50 MB.

Processing endpoints are asynchronous: they answer 202 with a job. Poll GET /jobs/{id} or register a webhook and wait for job.completed. Outputs are signed URLs, valid for 24 hours — copy them into your own storage.

POST /images/upscale → 202
json
1{2  "job": {3    "id": "job_01J9KQ7M3Z",4    "status": "queued",5    "endpoint": "images.upscale",6    "credits": 5,7    "created_at": "2026-09-02T09:14:07Z"8  }9}
HeaderTypeDescription
AuthorizationrequiredBearer dm_live_… or dm_test_….
Idempotency-KeyoptionalAny unique string. Retries with the same key return the original job instead of charging twice. Kept 24 h.
X-Credits-ChargedresponseCredits deducted by this call. 0 on sandbox keys.
X-RateLimit-RemainingresponseRequests left in the current minute.
Credits & limits

One currency, one limit.

Every call is priced in credits — 1 credit = $0.01 — bought in one-time blocks with rollover. Credits are charged when a job completes; failed jobs are not charged. Rate limits are the same on every block: 300 requests a minute per key. Short bursts queue rather than drop; past the limit you get 429 with a Retry-After header, and the client library backs off for you.

GET/account/credits

The live balance, the blocks it came from, and the key's limit.

200
json
1{2  "balance": 8412,3  "blocks": [4    { "id": "blk_growth_0421", "credits": 10400, "remaining": 8412, "expires_at": "2027-03-01T00:00:00Z" }5  ],6  "rate_limit": { "per_minute": 300, "remaining": 297 }7}
Image endpoints

Fix the artwork before the press does.

Five single-purpose services. Each takes one image, returns one job, and hands back one output. Chain them yourself, or let a pipeline do it.

POST/images/upscale5 credits

Raise resolution to a target DPI at a target print size. The model favours edges and lettering over texture, so logos stay crisp.

FieldTypeDescription
source_urlstringPublic or signed URL of the image (or send multipart file).
target_dpiint · 300Resolution to reach at print_width_mm.
print_width_mmnumberPhysical width the artwork will print at. Drives the scale factor.
max_scalenumber · 4Upper bound on enlargement; the response reports what was achieved.
request
bash
1curl -X POST https://api.designmint.intuio.io/v1/images/upscale \2  -H "Authorization: Bearer $DM_KEY" \3  -H "Idempotency-Key: order-1042-front" \4  -H "Content-Type: application/json" \5  -d '{6    "source_url": "https://cdn.yourshop.com/uploads/logo-500px.png",7    "target_dpi": 300,8    "print_width_mm": 2809  }'
job.completed → result
json
1{2  "output": { "url": "https://files.designmint.intuio.io/…/logo-3307px.png", "format": "png" },3  "width": 3307,4  "height": 1417,5  "dpi": 300,6  "scale": 6.6,7  "warnings": []8}
POST/images/sharpen5 credits

Recovers edge detail on soft or over-compressed artwork. Fields: source_url, optional strength (0–1, default 0.5).

POST/images/remove-background5 credits

Isolates the subject on transparency. Returns a PNG with alpha and the detected bounding box, so you can place it on a print area straight away.

FieldTypeDescription
source_urlstringThe image.
modelogo | photo · autoHint for the matting model. logo keeps hard edges; photo keeps hair and soft edges.
padding_mmnumber · 0Transparent margin added around the subject.
POST/images/vectorize8 credits

Traces raster artwork to clean SVG. Best on logos, lettering and flat illustration; photos are rejected with unprocessable and a hint to quantize first.

FieldTypeDescription
source_urlstringThe image — ideally already background-removed.
modelogo | illustration · logologo: fewer, smoother paths. illustration: keeps detail.
max_colorsint · 8Colour cap for the trace. Each colour becomes one path group.
job.completed → result
json
1{2  "output": { "url": "https://files.designmint.intuio.io/…/logo.svg", "format": "svg" },3  "paths": 14,4  "colors": ["#C2532F", "#0F1620", "#FFFFFF"],5  "viewbox": [0, 0, 1200, 514]6}
POST/images/quantize8 credits

Reduces the artwork to N spot colours and returns the palette — the step before screen separations or embroidery thread mapping.

FieldTypeDescription
source_urlstringThe image.
colorsint · 4Number of colours to keep (1–12).
palettestring[]Optional fixed palette (hex). The artwork is mapped onto it instead of auto-picked.
ditherboolean · falseDither gradients. Off for screen print, on for sublimation.
Validate

Know before the press knows.

POST/images/validate8 credits

Checks an image against a technique and a print area and returns every issue with a concrete fix. This is the one synchronous endpoint — it answers 200 directly, so it can sit inside a checkout.

FieldTypeDescription
source_urlstringThe image.
techniquedtg | dtf | screen | embroidery | sublimation | uv | htv | laserWhat it will be printed with.
print_area{ width_mm, height_mm }The area the artwork must fit.
bleed_mmnumber · 3Required bleed inside the area.
placement{ x_mm, y_mm, width_mm }Where the customer put it. Omit to validate at full area.
200
json
1{2  "ok": false,3  "dpi_at_size": 96,4  "issues": [5    { "code": "low_dpi", "severity": "error", "detail": "96 dpi at 280 mm; dtg needs 300",6      "fixes": [ { "action": "upscale", "endpoint": "/images/upscale" },7                 { "action": "reduce_size", "max_width_mm": 90 } ] },8    { "code": "outside_bleed", "severity": "warning", "detail": "artwork within 1.2 mm of the edge",9      "fixes": [ { "action": "nudge", "dx_mm": 0, "dy_mm": 2 } ] }10  ]11}
Issue codeSeverityMeaning
low_dpierrorResolution at the placed size is under the technique minimum.
outside_bleedwarningArtwork sits inside the bleed margin.
too_many_colorserrorColour count exceeds the technique (screen / embroidery).
thin_lineswarningStrokes below the technique minimum (embroidery, laser).
unsupported_techniqueerrorThe product rule set does not allow this technique here.
Mockups & scenes

Show it on the product.

POST/mockups8 credits

Places artwork on a product photo at a placement, with the garment's shading and fabric texture applied. Product slugs come from your catalog or ours.

FieldTypeDescription
artwork_urlstringThe (ideally background-removed) artwork.
productstringProduct slug, e.g. gildan-5000 or your own catalog id.
colorstringColourway slug, e.g. black.
placementfront | back | left-sleeve | …Print area to place on.
size{ width_mm, x_mm, y_mm }Physical size and position inside the area. Defaults to centred at max width.
viewsstring[] · ["front"]Which product views to render.
job.completed → result
json
1{2  "outputs": [3    { "view": "front", "url": "https://files.designmint.intuio.io/…/front.png", "width": 2000, "height": 2000 }4  ],5  "product": "gildan-5000", "color": "black", "placement": "front"6}
POST/scenes12 credits

Drops a mockup into a lifestyle scene — a person, a shelf, a desk — for listings and social. Takes a mockup_url (or the same fields as /mockups) plus a scene preset or a short prompt.

Pipelines

The whole chain, one call.

A pipeline runs prep, validation and output for a technique in one job: clean the artwork, check it, then produce exactly the files that technique's press expects. It is what the DesignMint studio calls on every order.

POST/pipelines/{technique}25 credits

technique is one of dtg, dtf, screen, embroidery, sublimation, uv, htv, laser.

FieldTypeDescription
source_urlstringThe raw artwork.
print_area{ width_mm, height_mm }Target print area.
placement{ x_mm, y_mm, width_mm }Where and how large. Defaults to centred at max width.
productstringOptional product slug — also produces a mockup and applies the product’s rule set.
stepsstring[]Override the default chain, e.g. ["remove-background", "vectorize"]. Validation always runs.
on_failreject | best-effort · rejectreject stops on an error-severity issue; best-effort applies fixes and reports them.
request
bash
1curl -X POST https://api.designmint.intuio.io/v1/pipelines/dtf \2  -H "Authorization: Bearer $DM_KEY" \3  -H "Content-Type: application/json" \4  -d '{5    "source_url": "https://cdn.yourshop.com/uploads/logo-500px.png",6    "print_area": { "width_mm": 280, "height_mm": 350 },7    "product": "gildan-5000",8    "on_fail": "best-effort"9  }'
job.completed → result
json
1{2  "technique": "dtf",3  "steps": ["upscale", "remove-background", "validate"],4  "validation": { "ok": true, "dpi_at_size": 300, "issues": [] },5  "outputs": [6    { "role": "print",   "url": "…/front-dtf.png",  "format": "png", "dpi": 300, "mirrored": true, "white_underbase": true },7    { "role": "preview", "url": "…/front-preview.png", "format": "png" },8    { "role": "mockup",  "url": "…/front-mockup.png", "format": "png" }9  ]10}
TechniquePrint outputsNotes
dtgpng · 300 dpi · rgbTransparent background, sized to the area.
dtfpng · 300 dpi · mirroredWhite underbase layer generated.
screenseparations · pdf/x-4 per colourQuantized to the colour cap; registration marks on.
embroiderydst · pes · expStitch preview, thread palette and stitch count.
sublimationpng · mirrored · ditheredColour-managed for polyester.
uv · htv · laserpdf/x-4 · svgVector where possible; cut lines for htv and laser.
Jobs

Poll it, or be told.

GET/jobs/{id}

Status and, once complete, the result. Jobs are kept for 7 days.

200
json
1{2  "id": "job_01J9KQ7M3Z",3  "status": "completed",        // queued · processing · completed · failed4  "endpoint": "images.upscale",5  "credits": 5,6  "created_at": "2026-09-02T09:14:07Z",7  "completed_at": "2026-09-02T09:14:19Z",8  "result": { "…": "…" }9}
GET/jobs

List jobs, newest first. Filter with status, endpoint and since; page with cursor.

Webhooks

We call you when it's done.

POST/webhooks

Register an HTTPS endpoint for job.completed and job.failed. Deliveries retry with backoff for 24 hours until you answer 2xx.

FieldTypeDescription
urlstringYour HTTPS endpoint.
eventsstring[]Any of job.completed, job.failed, credits.low.
secretstringOptional. Used to sign deliveries; one is generated if omitted and returned once.
delivery · job.completed
json
1POST https://yourshop.com/hooks/designmint2DesignMint-Signature: t=1756804459,v1=8f2c…e1a034{5  "event": "job.completed",6  "job": { "id": "job_01J9KQ7M3Z", "endpoint": "pipelines.dtf", "credits": 25 },7  "result": { "…": "…" }8}
Verify the signature: HMAC-SHA256 of {t}.{raw body} with your secret must equal v1. Reject anything older than five minutes.
GET/webhooks

List registered webhooks.

DELETE/webhooks/{id}

Remove one.

Errors

Plain codes, plain messages.

4xx / 5xx
json
1{2  "error": {3    "code": "insufficient_credits",4    "message": "This call needs 25 credits; balance is 12.",5    "doc": "https://designmint.intuio.io/docs/prepress#errors"6  }7}
Status · codeWhenWhat to do
400 invalid_requestA field is missing or malformed.Read error.message; it names the field.
401 unauthorizedMissing, revoked or wrong-environment key.Check the Authorization header and key prefix.
402 insufficient_creditsBalance is below the call cost.Top up a block, or wait for credits.low to warn you first.
409 idempotency_conflictSame Idempotency-Key, different body.Use a new key for a new request.
415 unsupported_mediaFile type not accepted.Convert to PNG, JPEG, WebP, SVG, PDF, PSD, AI, EPS or CDR.
422 unprocessableThe image can’t do what was asked (e.g. vectorize a photo).Follow the hint in error.message — usually quantize or remove-background first.
429 rate_limitedOver 300 requests / minute.Honour Retry-After. The client library does this for you.
500 internalOur fault.Retry with the same Idempotency-Key; it will not double-charge.
Client library

Or skip the curl.

A small TypeScript client wraps the endpoints, waits on jobs for you, and backs off on 429. It lives in the same private @intuio scope as the SDKs.

terminal
bash
1npm i @intuio/designmint-prepress
server.ts
tsx
1import { Prepress } from "@intuio/designmint-prepress"23const prepress = new Prepress({ apiKey: process.env.DM_KEY! })45// one call, wait for the result6const job = await prepress.pipelines.run("dtf", {7  sourceUrl: upload.url,8  printArea: { widthMm: 280, heightMm: 350 },9  product: "gildan-5000",10  onFail: "best-effort",11})1213const result = await job.wait()          // polls until completed / failed14const printFile = result.outputs.find((o) => o.role === "print")1516// or: validate synchronously inside checkout17const check = await prepress.images.validate({18  sourceUrl: upload.url,19  technique: "dtg",20  printArea: { widthMm: 280, heightMm: 350 },21})22if (!check.ok) showFixes(check.issues)

Questions about the contract, or need an endpoint that isn't here yet? Write to designmint@intuio.io.