Dev.to WebDev πŸ›  Dev πŸ‘ 0 πŸ“– 3 min read

How to Generate Editable Multi-Layer Fabric.js Templates via REST API (Prisma V1.0 Tutorial)

Most image APIs give you a PNG. If your product needs designs that people keep editing, like retyping a headline, swapping a photo or translating a banner, a PNG is a dead end. This tutorial generates a complete design w

Most image APIs give you a PNG. If your product needs designs that people keep editing, like retyping a headline, swapping a photo or translating a banner, a PNG is a dead end. This tutorial generates a complete design with Prisma V1.0 and gets it back as an editable multi-layer template you can load into Fabric.js.

What comes back:

  • canvas JSON in the legacy-fabric-v1 format, with live text objects, native shapes and image objects;
  • private raster layers (PNG) and a JPEG preview;
  • your own photos, placed untouched as separate image objects (up to five).

Before you start

  • A Prisma developer workspace you own: sign in on PicStudio's Prisma page.
  • An API key with generations:write, jobs:read and assets:read. It is shown once, so keep it on your server.
  • Prisma Credits. One-time refills start at $10 for five designs, and each generation costs 500 credits.
  • Node.js 18 or later for the examples (built-in fetch).

Step 1: Submit a generation

curl --fail-with-body 'https://picstudio.aismartcontent.co/api/v1/generations' \
  -H "Authorization: Bearer $PRISMA_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: campaign-2026-001' \
  -d '{"model":"prisma-v1.0","prompt":"An original matcha campaign with a large heading and separate product photography.","name":"Matcha launch","aspect_ratio":"4:5"}'

The API answers 202 Accepted with a data envelope. Save data.job_id. Fields worth knowing:

  • prompt: 20 to 1,600 characters.
  • aspect_ratio: 1:1, 4:5, 9:16, 16:9 or 1.91:1 (default 1.91:1).
  • material_images: up to five photos as {mime_type, data_base64}, each placed untouched (JPEG, PNG or WebP; 2 MiB each, 5 MiB in total).
  • reference_image with reference_mode (mood or style) to borrow a feeling or a palette.
  • The Idempotency-Key header (8 to 96 safe characters): send a retry with the same key and you are never charged twice.

Step 2: Poll the job

const BASE = 'https://picstudio.aismartcontent.co/api/v1';
const auth = { Authorization: `Bearer ${process.env.PRISMA_API_KEY}` };
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function waitForJob(jobId) {
  for (;;) {
    const res = await fetch(`${BASE}/jobs/${jobId}`, { headers: auth });
    if (res.status === 429) {
      await sleep((Number(res.headers.get('Retry-After')) || 15) * 1000);
      continue;
    }
    const { data } = await res.json();
    if (data.status === 'completed') return data;
    if (data.status === 'failed' || data.status === 'cancelled') {
      throw new Error(data.error?.message ?? `Job ${data.status}`);
    }
    await sleep(5000); // the docs ask for one poll every 5 seconds
  }
}

The states are queued, processing, completed, failed and cancelled, and data.progress runs from 0 to 100.

Step 3: Download the editable template

async function getTemplate(jobId) {
  const res = await fetch(`${BASE}/jobs/${jobId}/result`, { headers: auth });
  const body = await res.json();
  const result = body.data ?? body;
  return JSON.parse(result.template_data); // legacy-fabric-v1 canvas JSON
}

Image objects in that JSON point to /api/v1/jobs/{job_id}/assets/.... Every one of those downloads needs the bearer key, so fetch the files on your backend and serve your own copies. Never put the key in a URL.

Step 4: Load it into Fabric.js

const canvas = new fabric.Canvas('editor');
canvas.loadFromJSON(templateJson, () => canvas.renderAll());

Text stays text, so users can retype or translate it. Shapes stay vector, and each photo is its own object. The format is legacy-fabric-v1, so check the docs for the Fabric.js version it targets before you wire it into a newer editor.

Limits and good habits

  • 60 requests and 5 new generations per minute per key, and 2 simultaneous generations per workspace.
  • Honour Retry-After on 429, and don't regenerate automatically.
  • Errors come in an envelope with error.code and error.request_id. Keep the request ID for support.
  • V1.0 has no SDK or webhooks. Review every result, because fonts may be substituted and fine details can need a touch-up.

Wrapping up

That is the whole loop: submit, poll, fetch, load. For pricing and the full feature list, read the Prisma AI design model overview, and find the reference on PicStudio's Prisma page.

πŸ“° Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.