Skip to content
Docs Introduction
Docs REST API v1

KaroStudio API

Create and edit images in your project's style from your own code: your shop, your CMS, a nightly script or automations like Zapier and Make.

Quickstart

The API is a classic REST interface with JSON. It does everything the app does: read the style, create images and series, match photos, upscale, vectorize, convert and search the Collection. Every result follows your project's rules and lands in the Collection.

Getting started

API or MCP?#

Both use the same tokens and the same scopes. The difference is who makes the calls.

  • Who calls it
    An AI assistant like Claude or ChatGPT
    Your code, a shop, a CMS, Zapier
  • Typical use
    In conversation, e.g. "Make me 4 posts for the summer party"
    Automated and recurring, e.g. matching all new product photos every night
  • Results arrive
    Right in the chat
    As JSON with image URLs, by polling or webhook
  • Docs
    This page

Quickstart#

From token to first image in three steps.

  1. 1

    Create a token

    In KaroStudio, open Account settings, then AI connection and API. Choose Create token, then pick the scopes and the project.

  2. 2

    Start a job

    Terminal
    curl -X POST "https://api.karostudio.example/v1/projects/hafenkueche/images" \
      -H "Authorization: Bearer <YOUR_TOKEN>" \
      -H "Content-Type: application/json" \
      -d '{"template":"social-media","subjects":["Summer at the harbor"]}'

    The response comes back right away and includes the job ID.

  3. 3

    Fetch the result

    Terminal
    curl "https://api.karostudio.example/v1/jobs/job_7f3c2a" \
      -H "Authorization: Bearer <YOUR_TOKEN>"

    Once it says "status": "succeeded", you'll find the image URLs under images. Instead of polling, you can also pass a webhook.

Basics

Authentication#

Every request sends the token in a header. Requests without HTTPS are rejected.

HTTP header
Authorization: Bearer <YOUR_TOKEN>
  • projects:read
    See projects and templates
  • style:read
    Read the style and rules. Changes are only possible in the app.
  • images:write
    Create, match, upscale, vectorize, convert, upload
  • collection:read
    Find results
  • collection:write
    Rename, mark and delete results

Jobs#

Creating images takes a few seconds. That's why creating calls respond right away with 202 and a job ID. Get the status via GET /jobs/{job} or have a webhook notify you.

  • queued
    Accepted, waiting to start.
  • running
    In progress. progress shows the share done in percent.
  • succeeded
    All images are ready.
  • partial
    Some subjects are done, others failed. Each image lists its reason.
  • failed
    Nothing could be created. error gives the reason.
  • canceled
    Canceled by you.

Webhooks#

Pass a URL in webhook when you start a job. When the job is done, we send a POST there. If your URL doesn't answer with a 2xx, we retry up to [Number] times.

POST to your URL
{
  "event": "job.succeeded",
  "created_at": "2026-10-12T08:14:03Z",
  "data": {
    "job": "job_7f3c2a",
    "project": "hafenkueche",
    "images": [{ "id": "img_01", "url": "https://…/img_01.png" }]
  }
}

Every message is signed with your webhook secret. Check the signature in the KaroStudio-Signature header before you trust the message:

Node.js
import crypto from "node:crypto";

// header: value of KaroStudio-Signature, e.g. "t=1791800043,v1=5f2b…"
function isValid(rawBody, header, secret) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${parts.t}.${rawBody}`)
    .digest("hex");
  const stale = Math.abs(Date.now() / 1000 - Number(parts.t)) > 300; // older than 5 minutes
  return !stale && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}
  • job.succeeded
    All images of a job are ready
  • job.partial
    Done, but not every subject worked
  • job.failed
    The job failed

Pagination#

Lists come in pages. limit sets the page size, and next in the response is the cursor for the next page. When it's null, you've reached the end.

Next page
curl "https://api.karostudio.example/v1/projects/hafenkueche/collection?limit=50&after=c_b01" \
  -H "Authorization: Bearer <YOUR_TOKEN>"

Versioning#

The version is part of the path: /v1. Within a version we only add things, like new fields. Ignore unknown fields and your code will never break. Breaking changes only come with a new version and [Notice period] of notice.

Reference

Projects#

Style#

Create images#

Jobs#

Edit images#

Uploads#

Collection#

Errors#

Errors come with a matching HTTP status and always have the same shape. Include the request_id when you contact support.

Example
{
  "error": {
    "code": "forbidden",
    "message": "This token can't use the project nordgarten.",
    "request_id": "req_7d2e"
  }
}
  • 400
    A field is missing or has the wrong type. The message names the field.
    invalid_request
  • 401
    The token is missing, mistyped or revoked.
    unauthenticated
  • 402
    Your quota for this period is used up.
    quota_exceeded
  • 403
    The token lacks the scope, or the project isn't shared with it.
    forbidden
  • 404
    The project, job or image doesn't exist.
    not_found
  • 409
    The job conflicts with a locked rule.
    rule_locked
  • 422
    The file is damaged or in an unsupported format.
    invalid_file
  • 429
    Too many requests. The Retry-After header gives the seconds to wait.
    rate_limited
  • 500
    Something went wrong on our side. Share the request_id and support can help quickly.
    server_error

Limits#

  • Requests per minute
    [Number] per token
  • Subjects per job
    [Number]
  • Upload file size
    [Size] MB
  • Quota
    Per your plan: [Plan]

Every response includes the RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers, so you can see ahead of time when to slow down.

Tools

OpenAPI file#

The whole API as OpenAPI 3.1. Use it to generate clients for almost any language, import every endpoint into Postman or Insomnia, or open it in the Swagger Editor.

karostudio-openapi.json

13 endpoints, version 1.0.0

Example: generate a client
npx @openapitools/openapi-generator-cli generate \
  -i karostudio-openapi.json -g typescript-fetch -o ./karostudio

Still have questions? Write to us. We'll help with your integration.

Contact us