ZukMe
← Pull from MarketplaceAPI Docs

Pull from Marketplace Docs

Full request/response schemas, error codes, and examples for the Pull from Marketplace product — Runway Edit, StyleMe, and marketplace match + render. Looking to match against your own catalog instead? See the Use My Own Inventory Docs.

Base URL

https://zukme.com

Every endpoint below is relative to this base URL. For example, POST /api/v1/marketplace/tryon meansPOST https://zukme.com/api/v1/marketplace/tryon.

Authentication

Every request must include your API key as a bearer token. Create and manage keys in the API Dashboard. The raw key is shown once at creation; only its hash is ever stored, so if it's lost you must revoke it and create a new one.

Authorization: Bearer zk_live_<your key>

A missing, malformed, or revoked key returns 401:

{ "error": "Invalid or missing API key. Pass it as \"Authorization: Bearer zk_live_...\"." }

Rate limits

Each API key is limited to 30 requests per minute (submit and poll requests both count). Exceeding it returns 429:

{ "error": "Rate limit exceeded.", "retryAfterSeconds": 12 }

Credits

API usage draws from the exact same credit balance as the ZukMe app — the same balance the Use My Own Inventory product shares too — with no separate metering system. Each successful Runway Edit, StyleMe, or Marketplace Try-On submission costs 1 credit, deducted when the job is submitted. If generation fails, the credit is refunded automatically. Polling for a job's status never costs a credit. See pricing for subscription tiers, or your account's balance any time via the API Dashboard.

Errors

FieldTypeDescription
400Bad RequestMissing or invalid fields in the request body.
401UnauthorizedMissing, malformed, or revoked API key.
402Payment RequiredCredits exhausted (code CREDITS_EXHAUSTED), with your current looks/bonus/total balance in the body.
404Not FoundjobId does not exist (expired, wrong id, or never submitted).
429Too Many RequestsRate limit exceeded for this key. See retryAfterSeconds.

Example 402 body:

{
  "error": "CREDITS_EXHAUSTED",
  "code": "CREDITS_EXHAUSTED",
  "looks": 0,
  "bonus": 0,
  "total": 0
}

Runway Edit

Generates a photorealistic fashion editorial image: a model wearing an outfit built from your source art/photo, in a scene and style you direct. Runs as an async job: submit, then poll until it's done (generation typically takes 30 to 90 seconds across its internal stages).

POST /api/v1/runway-edit · Submit

FieldTypeDescription
artPhotoBase64requiredstringBase64-encoded source image (art, photo, or design) the outfit is built from.
outfitNamerequiredstringShort name for the outfit, e.g. "Tailored Blazer Set".
outfitDirectionrequiredstringFree-text description of the garment(s): cut, pieces, silhouette. Up to 3000 characters.
sceneNamerequiredstringShort name for the scene/location, e.g. "Golden Hour Rooftop".
styleDirectionrequiredstringFree-text mood/style direction for the scene and shot. Up to 2000 characters.
size"S" | "M" | "L" | "XL" | "XXL" | "XXXL"Model build size. Defaults to "M".
gender"Male" | "Female" | "Neutral"Model gender direction. Defaults to "Neutral".
ageGroup"Adult" | "New Wave""New Wave" generates a teen model profile. Defaults to "Adult".
location{ lat: number, lon: number } | nullOptional, captured on the job for future use. Never alters generation.
callbackUrlstringOptional webhook. See Callbacks below.

Response (submitted):

{ "ok": true, "jobId": "b3f1...", "status": "processing" }

POST /api/v1/runway-edit · Poll

FieldTypeDescription
actionrequired"poll"Selects the poll branch.
jobIdrequiredstringThe jobId returned by the submit call.

Response while processing:

{ "status": "processing", "stage": "t2i" }

Response when done:

{ "ok": true, "status": "done", "imageUrl": "https://..." }

Response on failure (credit already refunded):

{ "status": "error", "error": "The AI model failed on this image. Please try again." }

StyleMe

Generates a personalized style reading from a photo: a stylist-grade read on colouring, proportions, and aesthetic. Feeds directly into Marketplace Try-On below. Also an async job: submit, then poll until done.

POST /api/v1/styleme · Submit

FieldTypeDescription
photoBase64requiredstringBase64-encoded photo of the person to generate a reading for.

Response (submitted):

{ "ok": true, "jobId": "a91c...", "status": "processing" }

POST /api/v1/styleme · Poll

Same poll shape as Runway Edit. Response when done:

{ "ok": true, "status": "done", "reading": { /* StyleMeReading, see below */ } }

The reading object

FieldTypeDescription
validbooleanFalse if the photo could not be read (see rejection_reason).
rejection_reasonstring | nullExplanation when valid is false.
styleTitlestringThe person's style archetype, e.g. "The Modern Minimalist".
styleSubtitlestringOne-line elaboration on the style title.
readingstring[]Paragraphs of the full style reading.
personality{ trait, level, description }[]Personality trait breakdown, level 0–100.
palette{ hex, name }[]Colours that suit this person's colouring.
outfits{ name, occasion, pieces, why }[]Suggested outfit concepts.
tagsstring[]Short style keyword tags.
genderstring | undefinedInferred gender, for downstream use.
bodyTypestring | undefinedInferred body type, e.g. "M", "Petite".

Marketplace Try-On

Takes a StyleMe reading and a photo, matches the best real product per garment category from ZukMe's marketplace (its own catalog blended with affiliate products), and renders the result onto the photo. Async job: submit, then poll.

POST /api/v1/marketplace/tryon · Submit

FieldTypeDescription
readingrequiredStyleMeReadingThe reading object returned by POST /api/v1/styleme.
photoBase64requiredstringBase64-encoded photo of the person to render the outfit onto.
occasionstringOptional occasion, e.g. "Weekend brunch" — shapes which pieces are shopped for.
bodyTypestringOptional body type override, e.g. "M", "Petite". Defaults to the reading's own inferred bodyType.
location{ lat: number, lon: number } | nullOptional — nudges matching toward nearby shops when relevant.
callbackUrlstringOptional webhook. See Callbacks below.

Response (submitted):

{ "ok": true, "jobId": "c7e2...", "status": "processing" }

POST /api/v1/marketplace/tryon · Poll

Same poll shape as Runway Edit. Response when done:

{
  "ok": true,
  "status": "done",
  "imageUrl": "https://...",
  "outfitBreakdown": [
    {
      "category": "top",
      "productId": "abc123",
      "productName": "Silk Wrap Blouse",
      "shopName": "Studio Nine",
      "imageUrl": "https://...",
      "price": "USD 84",
      "source": "zukme"
    }
  ]
}

source is "zukme" or "cj" depending on which part of the marketplace the piece came from — both are real, purchasable products.

Callbacks (webhooks)

runway-edit and marketplace/tryon both accept an optional callbackUrl in the submit request. When set, wePOST the same payload a completed poll would return to that URL once the job finishes — success or failure — in addition to, never instead of, polling. Delivery is best-effort: we don't retry or track failed deliveries, so keep polling as your source of truth.

// what we POST to callbackUrl on success:
{ "jobId": "...", "status": "done", "imageUrl": "https://...", "outfitBreakdown": [...] }

// on failure:
{ "jobId": "...", "status": "error", "error": "..." }

callbackUrl must be a public http(s) URL — localhost and private network addresses are rejected.

Job polling

Every submit endpoint returns a jobId and runs asynchronously, since generation involves multiple internal AI stages that don't fit in one request/response cycle. Poll the same endpoint every 2 to 3 seconds until you getstatus: "done" orstatus: "error". A job that returns404 either never existed or has expired. Treat it as failed.

Full example: curl

# 1. Get a StyleMe reading first — see the StyleMe section above
# 2. Submit
curl https://zukme.com/api/v1/marketplace/tryon \
  -X POST \
  -H "Authorization: Bearer zk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "reading": { /* from POST /api/v1/styleme */ },
    "photoBase64": "<base64>",
    "occasion": "Weekend brunch"
  }'
# → { "ok": true, "jobId": "c7e2...", "status": "processing" }

# 3. Poll until done
curl https://zukme.com/api/v1/marketplace/tryon \
  -X POST \
  -H "Authorization: Bearer zk_live_..." \
  -H "Content-Type: application/json" \
  -d '{ "action": "poll", "jobId": "c7e2..." }'
# → { "status": "processing", "stage": "edit" }   (repeat)
# → { "ok": true, "status": "done", "imageUrl": "https://...", "outfitBreakdown": [...] }

Full example: Node.js

const KEY = process.env.ZUKME_API_KEY;
const BASE = "https://zukme.com/api/v1/marketplace/tryon";

async function call(body) {
  const res = await fetch(BASE, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(body),
  });
  return res.json();
}

const submitted = await call({
  reading, // from POST /api/v1/styleme
  photoBase64,
  occasion: "Weekend brunch",
});

let result;
while (true) {
  result = await call({ action: "poll", jobId: submitted.jobId });
  if (result.status === "done" || result.status === "error") break;
  await new Promise((r) => setTimeout(r, 2500));
}

console.log(result); // { ok: true, status: "done", imageUrl: "...", outfitBreakdown: [...] }

Full example: Python

import os, time, requests

KEY = os.environ["ZUKME_API_KEY"]
BASE = "https://zukme.com/api/v1/marketplace/tryon"
headers = {"Authorization": f"Bearer {KEY}"}

submitted = requests.post(BASE, headers=headers, json={
    "reading": reading,  # from POST /api/v1/styleme
    "photoBase64": photo_base64,
    "occasion": "Weekend brunch",
}).json()

while True:
    result = requests.post(BASE, headers=headers, json={
        "action": "poll", "jobId": submitted["jobId"],
    }).json()
    if result["status"] in ("done", "error"):
        break
    time.sleep(2.5)

print(result)  # {'ok': True, 'status': 'done', 'imageUrl': '...', 'outfitBreakdown': [...]}

ZukMe Global Network

Africa

Ghana: GS-0168-9885, Attah Mills Street, Opp. Downtown Pub, Old Barrier, Accra, Ga South, Greater Accra

Rwanda: KK 734 St, Kigali, Rwanda

+233(0)505807777

North America

United States 7901 4th St N, Suite 300, St Petersburg, Florida 33702, United States

+1 850 5170 671

Resources

Need help getting started?

Contact Us

© 2026 ZukMe LLC. All rights reserved.