Skip to content
Gauge

ax-check.com

The New Black AI

thenewblack.ai

ax-check.com

Checked 30 October 2026

B

84/100

Agents need your login

Agents can install, authenticate, and price this product fast.

21 of 23 checks passed: CLI, API, MCP server and skills are all documented with working install paths, and pricing is stated openly with no login wall.

2 fixes to start with

Concrete changes, backed by what we found.

Onboarding

Give agents a clear login handoff and a way to resume setup.

Agents cannot progress through onboarding without human help. Provide an agent-accessible path through authentication and setup.

Docs

Return Markdown when clients request text/markdown.

Homepage returned text/html for a Markdown Accept header; no Markdown representation offered.

Recorded coding sessions

Same task, 3 models, no thenewblack.ai account. Recorded 30 October 2026 on Pi.

3 recorded · 2m 28s

2m 28s · recorded

Session findings

Select a finding to see it in context.

piv0.84.2
modelQwen 3.8 Maxcwd/sandbox/repo
Help me build a simple example using The New Black AI. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage. Let me know if you get blocked. If this product has no developer workflow you can act on, say so plainly and stop. Stay light: use the hosted product through its SDK or API. Do not start local service stacks or wait for long-running commands; if the quickstart requires either, say so plainly and stop.
Thinking…

Let me look at the repo to see what's there.

"The New Black" is an AI fashion design platform (thenewblack.ai). Let me check the environment/repo first, and whether there's any info available.

Let me investigate.

pwd; ls -la; cat README* 2>/dev/null | head -50; env | grep -i -E "black|tnb|api_key" | sed 's/=.*/=<set>/'
/sandbox/repo
/sandbox/repo
total 16
drwxr-xr-x 3 root root 4096 Sep 18 08:00 .
drwxr-xr-x 7 root root 4096 Oct 30 20:22 ..
drwxr-xr-x 8 root root 4096 Sep 24 20:05 .git
-rw-r--r-- 1 root root  408 Sep 18 08:00 .gitignore
PI_GATEWAY_API_KEY=<set>
ls /usr/local/lib/node_modules/@earendil-works/pi-coding-agent/docs 2>/dev/null
compaction.md
compaction.md
containerization.md
custom-provider.md
development.md
docs.json
environment-variables.md
extensions.md
images
index.md
json.md
keybindings.md
llama-cpp.md
models.md
packages.md
prompt-templates.md
providers.md
quickstart.md
rpc.md
sdk.md
security.md
session-format.md
sessions.md
settings.md
shell-aliases.md
skills.md
terminal-setup.md
termux.md
themes.md
tmux.md
tui.md
usage.md
windows.md
Thinking…

The repo is empty (just .gitignore). The task: build a simple example using "The New Black AI". This is thenewblack.ai — an AI fashion design generation platform. Does it have a public developer API/SDK? I don't believe The New Black offers a public API or SDK. Let me check network access and try to find docs.

Let me test network connectivity.

cd /sandbox/repo && cat .gitignore; git log --oneline | head; timeout 15 curl -sSI https://thenewblack.ai 2>&1 | head -5; echo "---"; timeout 15 curl -sS https://pypi.org/simple/ 2>&1 | head -3
# Keep generated and vendored files out of source diffs.
# Keep generated and vendored files out of source diffs.

# Logs / OS cruft
*.log
.DS_Store

# JavaScript / TypeScript
node_modules/
.next/
dist/
build/
coverage/

# Python
.venv/
venv/
__pycache__/
*.py[cod]
.pytest_cache/
*.egg-info/

# Rust
target/

# Go / PHP / Ruby vendored deps
vendor/
.bundle/

# Java / Kotlin / Scala
.gradle/

# .NET
bin/
obj/

# Elixir
_build/
deps/

# Dart / Flutter
.dart_tool/
9ebf5fb Initial workspace
HTTP/2 200 
age: 0
cache-control: private, no-cache, no-store, max-age=0, must-revalidate
content-type: text/html; charset=utf-8
date: Fri, 30 Oct 2026 20:22:50 GMT
---
<!DOCTYPE html>
<html lang="en">
  <head>
Thinking…

Network works. Let's check whether The New Black has a developer API/SDK. Search for docs: thenewblack.ai/api, developers, docs. Also check npm and PyPI for packages.

cd /tmp && for p in api docs developers developer api-docs pricing; do echo "== /$p"; timeout 12 curl -s -o /dev/null -w "%{http_code}\n" "https://thenewblack.ai/$p"; done
== /api
== /api
404
== /docs
404
== /developers
404
== /developer
404
== /api-docs
404
== /pricing
200
echo "== npm"; timeout 20 curl -s "https://registry.npmjs.org/-/v1/search?text=the-new-black&size=10" | python3 -c "import json,sys; d=json.load(sys.stdin); [print(o['package']['name'],'|',o['package'].get('description','')[:80]) for o in d.get('objects',[])]"; echo "== pypi"; for n in thenewblack the-new-black tnb-sdk newblack; do timeout 12 curl -s -o /dev/null -w "$n %{http_code}\n" https://pypi.org/pypi/$n/json; done
== npm
== npm
@thenewblack/cli | The New Black AI from the command line: every fashion workflow of the studio, yo
functional-red-black-tree | A fully persistent balanced binary search tree
wouter | Minimalist-friendly ~1.5KB router for React
@fontsource/archivo-black | Self-host the Archivo Black font in a neatly bundled NPM package.
cssom | CSS Object Model implementation and CSS parser
input-otp | One-time password input component for React.
rrweb-cssom | CSS Object Model implementation and CSS parser
playwright-msw | A Mock Service Worker API for Playwright.
hasura-cli | A package that automatically installs and wraps Hasura CLI binary in isolated ma
wxt | ⚡ Next-gen Web Extension Framework
== pypi
thenewblack 404
the-new-black 404
tnb-sdk 404
newblack 404
Thinking…

There's an npm package @thenewblack/cli — "The New Black AI from the command line: every fashion workflow of the studio, yo..." Let's inspect it. Also check if there's an SDK package. Let's fetch package metadata.

timeout 20 curl -s https://registry.npmjs.org/@thenewblack%2Fcli | python3 -c "
import json,sys
d=json.load(sys.stdin)
print('name',d['name']); print('desc',d.get('description'))
print('latest',d['dist-tags'])
v=d['versions'][d['dist-tags']['latest']]
print('bin',v.get('bin')); print('deps',v.get('dependencies')); print('engines',v.get('engines'))
print('homepage',v.get('homepage')); print('repo',v.get('repository'))
print('keywords',v.get('keywords'))
print('readme len',len(d.get('readme','')))
open('/tmp/tnb_readme.md','w').write(d.get('readme',''))
"
name @thenewblack/cli
name @thenewblack/cli
desc The New Black AI from the command line: every fashion workflow of the studio, your creations, tech packs, publishing and Mila, your AI agent — one command each, JSON out. Made for AI coding agents and scripts.
latest {'latest': '0.3.3'}
bin {'tnb': 'bin/tnb.js'}
deps None
engines {'node': '>=18.17'}
homepage https://thenewblack.ai/clothing_fashion_api_integrations
repo {'url': 'git+https://github.com/newblackai/tnb-site.git', 'type': 'git', 'directory': 'cli'}
keywords ['fashion', 'ai', 'cli', 'thenewblack', 'virtual-try-on', 'fashion-design', 'agent']
readme len 4468
timeout 20 curl -s "https://registry.npmjs.org/-/v1/search?text=thenewblack&size=20" | python3 -c "import json,sys; d=json.load(sys.stdin); [print(o['package']['name'],'|',o['package'].get('description','')[:100]) for o in d.get('objects',[])]"
@thenewblack/cli | The New Black AI from the command line: every fashion workflow of the studio, your creations, tech p
@thenewblack/cli | The New Black AI from the command line: every fashion workflow of the studio, your creations, tech p
Thinking…

There is a CLI package. Let's read the readme. Also the homepage: thenewblack.ai/clothing_fashion_api_integrations — that's their API integration page. Let's read both.

read /tmp/tnb_readme.md{"content":[{"text":"# @thenewblack/cli — `tnb`\n\n[The New Black AI](https://thenewblack.ai) from the command line: every fashion workflow of the studio (desig…ctrl+o
{"content":[{"text":"# @thenewblack/cli — `tnb`\n\n[The New Black AI](https://thenewblack.ai) from the command line: every fashion workflow of the studio (design, product-to-model, virtual try-on, fabric, sketch, video, HD), your creations, tech packs, publishing to Shopify and social accounts, and Mila, the account's AI agent. One command each, JSON out. Made for AI coding agents (Claude Code, Codex, Cursor…), scripts, crons and CI.\n\n```sh\nnpx @thenewblack/cli --help          # nothing to install\nnpm install -g @thenewblack/cli      # or keep it: `tnb`\n```\n\nNode 18.17 or newer. No dependencies.\n\n## The key\n\n```sh\ntnb login                     # opens your profile's API tab, asks for the key, keeps it (config dir, mode 600)\nexport TNB_API_KEY=tnb_live_… # or: the environment wins — for a cron, a CI job, a container\ntnb whoami\n```\n\nKeys are created in your profile, API tab (up to three, each with scopes: `read`, `generate`, `publish`, `agents` — the last one to talk to Mila). Without a key, `tnb workflows` and every `--help` still work.\n\n## Generate\n\n```sh\ntnb workflows                                  # every workflow, with prices — read live from the catalogue\ntnb generate virtual_try_on --help             # the flags of one workflow, read live\ntnb generate virtual_try_on \\\n  --product_images dress.jpg belt.jpg --model_image model.jpg \\\n  --seg_camera slightly_above --ratio 4:5 --tier pro \\\n  --wait --out ./renders/\n# → {\"generation_id\":\"…\",\"status\":\"succeeded\",\"workflow\":\"virtual_try_on\",\"url\":\"https://…\",\"type\":\"image\",\"file\":\"renders/dress-virtual_try_on.webp\"}\n```\n\n- Pictures are **local files or https urls**. A local file is uploaded once and remembered (path, size, date), so tomorrow's run re-uploads nothing.\n- `--wait` polls until the generation settles; `--out dir/` saves the result with a readable name (`<first input>-<workflow>.<ext>`), `--out file.webp` saves it there. Without `--wait`, the answer is the id and `tnb status <id> --wait` picks it up later.\n- Results live 48 hours on our url. Save them.\n- Credits are debited at submission and refunded on failure; `402 insufficient_credits` means the account needs topping up.\n- Text-only workflows take `--prompt`; guided ones take the catalogue's `--<field>` flags; video ones take `--duration` and, for some, `--end-image`.\n\nA folder, one line each:\n\n```sh\nfor f in ./products/*.jpg; do tnb generate product_to_model --product_images \"$f\" --prompt \"studio light, neutral background\" --wait --out ./renders/; done\n```\n\n## Everything else\n\n```\ntnb credits · account · ledger · invoices · brand-dna [read <id>]\ntnb media [--project id] · elements · projects · upload <files…>\ntnb techpacks · techpack <id> · techpack pdf <id> · techpack rename <id> --name …\ntnb techpack add-section <id> --page <page_id> --kind bom [--at 0]\ntnb techpack write-section <id> <section_id> --data '<json>' | --data @file.json\ntnb techpack from-photos front.jpg [--back back.jpg] [--sketch front] [--size-range XS-XL] [--unit cm]\ntnb moodboards · moodboard pdf <id>\ntnb shopify products · shopify publish --product <id> --media <media_id>\ntnb publish accounts · publish --account <connection_id> --placement <placement> --media <media_id> [--caption …] · post <id>\ntnb mila · mila send \"message\" [--media …] · mila thread [--since …] · mila stop\ntnb mila schedules · mila schedule \"request\" --kind single --date 2026-10-01 --time 09:30 · mila unschedule <schedule_id>\ntnb files [--query …] · file <id|path> [--page 2] · file describe <id> --description \"…\"\n```\n\n`tnb <command> --help` prints the flags; `--pretty` indents the JSON. Exit codes: `0` done, `1` the platform or the network refused (the JSON error is on stderr, with the platform's own `code`), `2` the command line was wrong.\n\n## For an AI agent\n\nInstall it, run `tnb --help`, then `tnb generate <key> --help` for the workflow you need — the help is the live contract. Read the JSON, keep the ids, save the files. The full API reference is at https://thenewblack.ai/clothing_fashion_api_integrations and the Claude skill at https://github.com/newblackai/claude-skill.\n\n## Configuration\n\n| Variable | Meaning |\n|---|---|\n| `TNB_API_KEY` | The key; wins over the one kept by `tnb login`. |\n| `TNB_API_URL` | The API base (default `https://thenewblack.ai/api/v1`). |\n| `TNB_CONFIG_DIR` | Where the key is kept (default `~/.config/tnb`, `%APPDATA%\\tnb` on Windows). |\n| `TNB_CACHE_DIR` | Where uploaded files are remembered (default `~/.cache/tnb`). |\n\nMIT.\n","type":"text"}]}
timeout 20 curl -s https://thenewblack.ai/clothing_fashion_api_integrations | python3 -c "
import sys,re,html
t=sys.stdin.read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S)
t=re.sub(r'<style.*?</style>','',t,flags=re.S)
t=re.sub(r'<[^>]+>',' ',t)
t=html.unescape(t)
t=re.sub(r'[ \t]+',' ',t)
t=re.sub(r'\n\s*\n+','\n',t)
print(t[:6000])"
AI Fashion Clothing API | The New Black AI The New Black AI T he N ew B lack AI he ew lack API / MCP / CLI Pricing Tutorials Log in Start free The New Black AI
 AI Fashion Clothing API | The New Black AI The New Black AI T he N ew B lack AI he ew lack API / MCP / CLI Pricing Tutorials Log in Start free The New Black AI Start AI Fashion Clothing API Generate AI fashion visuals from your own product with a REST API, or straight from Claude or ChatGPT with our MCP. Every workflow of the studio, one endpoint. Get an API key MCP Claude skill API REST, for your code MCP for a conversation with Claude or ChatGPT CLI for a project of code, a script, an agent Endpoints Workflows catalogue (77) Publishing catalogue (5) Creations catalogue (4) Account (6) Tech packs (9) Mila - AI Agent (10) Fixed routes (39) Guide Introduction Authentication Errors Rate limits Create a generation Retrieve a generation Webhooks Credits MCP Command line Migrating from the legacy API Status GET /v1/workflows Workflows catalogue ( 77 ) Every studio workflow is callable by its versioned endpoint name. The route returns the live catalogue — named image parameters, fields, variants, formats and prices; the table below is rendered from the same data. Method Workflow key Title Mode Standard Pro Ultra Max refs POST freeform_image-v1 Free Prompt Image image 1 cr 3 cr 7 cr 3 POST freeform_video-v1 Free Prompt Video video 2.2 cr/s 4.4 cr/s 23 cr/s 1 POST virtual_try_on-v1 Virtual Try-On image 1 cr 3 cr 7 cr 5 POST product_to_model-v1 Product to Model image 1 cr 3 cr 7 cr 5 POST image_to_ghost_mannequin-v1 Image to Ghost Mannequin image 1 cr 3 cr 7 cr 1 POST change_color-v1 Change a Color image 1 cr 3 cr 7 cr 1 POST create_design-v1 Create a Product image 1 cr 3 cr 7 cr 3 POST enhance_photo_to_hd-v1 Enhance Photo to HD (2K/4K) image 1 cr 3 cr — 3 POST retouch-v1 Edit an Area image 1 cr 3 cr — 16 POST reimagine_scene-v1 Reimagine your Model image 1 cr 3 cr 7 cr 1 POST edit_video-v1 Edit video video 3.3 cr/s 4.3 cr/s — 1 POST motion_design-v1 Motion Design video 4 cr 4 cr — 4 POST model_walk-v1 Model Walk video 2.2 cr/s 4.4 cr/s 23 cr/s 1 POST product_360-v1 Product 360 video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST model_360-v1 Model 360 video 2.2 cr/s 4.4 cr/s 23 cr/s 2 POST swap_models-v1 Swap Model image 1 cr 3 cr 7 cr 1 POST face_swap-v1 Face Swap image 1 cr 1 cr — 2 POST fabric_to_design-v1 Fabric to Image image 1 cr 3 cr 7 cr 1 POST image_to_fabric-v1 Image to Fabric image 1 cr 3 cr 7 cr 1 POST text_to_textile-v1 Text to Textile image 1 cr 3 cr 7 cr 3 POST snap_freeze-v1 Snap Freeze video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST ugc_video-v1 UGC Video video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST image_to_flat_lay-v1 Image to Flat Lay image 1 cr 3 cr 7 cr 1 POST swap_fabrics-v1 Swap Fabrics image 1 cr 3 cr 7 cr 2 POST logo_placement-v1 Add a Logo image 1 cr 3 cr — 3 POST text_to_sketch-v1 Text to Sketch image 1 cr 3 cr 7 cr 3 POST sketch_to_image-v1 Sketch to Image image 1 cr 3 cr — 1 POST image_to_sketch-v1 Image to Sketch image 1 cr 3 cr 7 cr 2 POST sketch_to_svg-v1 Sketch to SVG image 1 cr 1 cr — 1 POST vectorize_image-v1 Vectorize Prints & Logos image 1 cr 1 cr — 1 POST insert_fabric_on_sketch-v1 Insert Fabric on Sketch image 1 cr 3 cr 7 cr 2 POST create_similar_outfits-v1 Create Similar Outfits image 1 cr 3 cr 7 cr 1 POST create_design_variations-v1 Create Design Variations image 1 cr 3 cr 7 cr 1 POST change_background-v1 Change Background image 1 cr 3 cr — 2 POST remove_background-v1 Remove Background image 0.5 cr 0.5 cr — 1 POST ad_creative-v1 Ad Creative image 1 cr 3 cr 7 cr 2 POST enhance_video_to_hd-v1 Enhance Video to HD video 4.4 cr/s 4.4 cr/s — 3 POST ai_stylist-v1 AI Stylist image 1 cr 3 cr 7 cr 1 POST outpaint_new_ratio-v1 Expand Image image 1 cr 1 cr — 1 POST create_3d_models-v1 Image to 3D 3d 10 cr 10 cr — 1 POST tryon_video-v1 Virtual Try-On Video video 2.2 cr/s 4.4 cr/s 23 cr/s 2 POST outfit_transition-v1 Outfit Transition video 2.2 cr/s 4.4 cr/s 23 cr/s 2 POST fashion_ad-v1 Fashion Ad video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST detail_closeup-v1 Detail Close-up video 2.2 cr/s 4.4 cr/s 23 cr/s 1 POST editorial_video-v1 Editorial Lookbook video 2.2 cr/s 4.4 cr/s 23 cr/s 1 POST outfit_drop-v1 Outfit Drop video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST remove_video_background-v1 Remove Video Background video 1.4 cr/s 1.4 cr/s — 1 POST reframe_video-v1 Reframe Video video 4.4 cr/s 4.4 cr/s — 1 POST passerby_transition-v1 Passer-By Transition video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST crosswalk_look_switch-v1 Look Switch Walk video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST change_video_background-v1 Change Video Background video 4.4 cr/s 8.8 cr/s — 1 POST change_video_outfit-v1 Edit Outfit in Video video 3.3 cr/s 4.3 cr/s — 1 POST swap_video_model-v1 Swap Model in Video video 3.3 cr/s 4.3 cr/s — 2 POST hanger_layering-v1 Hanger Switch video 2.2 cr/s 4.4 cr/s 23 cr/s 5 POST window_walkby-v1 Window Walk-By video 2.2 cr/s 4.4 cr/s 23 cr/s 3 POST detail_zoom_rush-v1 Detail Zoom Rush video 2.2 cr/s 4.4 cr/s 23 cr/s 1 POST outfit_morph-v1 Outfit Morph video 2.2 cr/s 4.4 cr/s 23 cr/s 4 POST freeform_audio-v1 Create a Soundtrack audio 2 cr 2 cr — 1 POST voice_over-v1 Create a Voice-over audio 1.06 cr/1k chars 2.12 cr/1k chars 2.12 cr/1k chars 3 POST motion_collection_panorama-v1 Collection Panorama video 1 cr 1 cr — 6 POST motion_split_reel-v1 Split Reel video 1 cr 1 cr — 4 POST motion_style_post-v1 Style Post video 1 cr 1 cr — 1 POST motion_look_film-v1 Look Film video 1 cr 1 cr — 4 POST motion_colour_drop-v1 Colour Drop video 1 cr 1 cr — 4 POST motion_phone_promo-v1 Phone Promo video 1 cr 1 cr — 4 POST motion_cut_montage-v1 Cut Montage video 1 cr 1 cr — 6 POST motion_paper_collage-v1 Paper Collage video 1 cr 1 cr — 8 POST motion_lineup-v1 Lineup video 1 cr 1 cr — 6 POST motion_character_select-v1 Character Select video 1 cr 1 cr — 6 POST motion_grid_mosaic-v1 Grid Mosaic video 1 cr 1 cr — 2 POST motion_ways_to_wear-v1 Ways to Wear video 1 cr 1 cr — 6 POST motion_detail_study-v1 Detail Study video 1 cr 1 cr — 3 POST motion_signature_film-v1 Signature Film video 1 cr 1 cr — 4 POST motion_outfit_picker-v1 Outfit Picker video
Thinking…

Good — there IS a real developer workflow: REST API at https://thenewblack.ai/api/v1, a CLI (npx @thenewblack/cli), MCP, and a Claude skill.

The task: "build a simple example using The New Black AI. Tell me how pricing works, and briefly tell me whether this product will be easy for you to manage." Stay light: use the hosted product through SDK or API. No local stacks, no long-running commands.

We need an API key (TNB_API_KEY) which we don't have. Let's check what works without a key: tnb workflows and --help. Also the API guide pages for pricing (credits), rate limits, etc.

Plan:

  1. Read the API guide pages (introduction, authentication, errors, rate limits, create a generation, retrieve a generation, webhooks, credits, command line) to learn the contract.
  2. Install/run the CLI via npx (quick, no long-running).
  3. Build a simple example in the repo: a small script (bash or Node) that uses the API/CLI. Since no API key exists, the example should work against the live catalogue unauthenticated where possible (tnb workflows works without key), and be ready for a key.
  4. Report pricing (credits, tiers) and manageability assessment.

Let's fetch the guide pages. URLs likely https://thenewblack.ai/clothing_fashion_api_integrations#... or separate routes. Let me check the nav links in HTML.

timeout 20 curl -s https://thenewblack.ai/clothing_fashion_api_integrations | grep -oE 'href="[^"]+"' | sort -u | head -60
href="#account"
href="#account"
href="#agents"
href="#authentication"
href="#cli"
href="#creations"
href="#credits"
href="#endpoints"
href="#errors"
href="#generate"
href="#introduction"
href="#legacy"
href="#limits"
href="#mcp"
href="#publishing"
href="#retrieve"
href="#techpacks"
href="#webhooks"
href="#workflows"
href="/"
href="/_next/static/chunks/1kw7gp-u2o2z8.js?dpl=dpl_7K6dkycLhdzDQNfCmcpgTpG3UJ3j"
href="/_next/static/chunks/2t-vx1m9ct447.css?dpl=dpl_7K6dkycLhdzDQNfCmcpgTpG3UJ3j"
href="/_next/static/chunks/3g-5cr3co5boh.css?dpl=dpl_7K6dkycLhdzDQNfCmcpgTpG3UJ3j"
href="/about_us"
href="/affiliate_program"
href="/ai-agent-for-fashion-brands"
href="/ai-clothing-fashion-design-generator"
href="/ai-design-features"
href="/ai-design-features/ai-fashion-video-generator"
href="/ai-design-features/create-ai-clothing-designs"
href="/ai-design-features/generate-ai-fashion-in-bulk"
href="/ai-generated-models"
href="/ai-logo-ai-moodboard-generator-for-brands"
href="/ai-lookbook"
href="/ai-outfit-generator-coach-assistant-stylist"
href="/ai-virtual-try-on-clothes"
href="/api/v1/openapi.json"
href="/app_privacy_policy"
href="/blog"
href="/blog/ai-agents-for-fashion-brands-guide"
href="/clothing-fashion-techpack"
href="/clothing_fashion_api_integrations"
href="/clothing_fashion_api_integrations/ad-creative-api"
href="/clothing_fashion_api_integrations/ai-generated-models-api"
href="/clothing_fashion_api_integrations/ai-stylist-api"
href="/clothing_fashion_api_integrations/ai-video"
href="/clothing_fashion_api_integrations/change-background-api"
href="/clothing_fashion_api_integrations/change-fabric-on-clothes-api"
href="/clothing_fashion_api_integrations/change-video-background-api"
href="/clothing_fashion_api_integrations/cli"
href="/clothing_fashion_api_integrations/clothing-image-to-flat-sketch"
href="/clothing_fashion_api_integrations/color-change-api"
href="/clothing_fashion_api_integrations/create-edit-image-api"
href="/clothing_fashion_api_integrations/crosswalk-look-switch-api"
href="/clothing_fashion_api_integrations/detail-closeup-video-api"
href="/clothing_fashion_api_integrations/detail-zoom-rush-api"
href="/clothing_fashion_api_integrations/edit-photo-api"
href="/clothing_fashion_api_integrations/edit-video-api"
href="/clothing_fashion_api_integrations/edit-video-outfit-api"
href="/clothing_fashion_api_integrations/editorial-lookbook-video-api"
href="/clothing_fashion_api_integrations/enhance-photo-hd-api"
cd /tmp && timeout 25 curl -s https://thenewblack.ai/api/v1/workflows -o w.json -w "%{http_code}\n"; head -c 600 w.json; echo
401
401
{"error":{"code":"missing_key","message":"Send your API key as: Authorization: Bearer tnb_live_..."}}
Thinking…

There's an OpenAPI spec: /api/v1/openapi.json — but it 401'd? No, that was /api/v1/workflows. Let's try openapi.json.

Also extract the guide sections text (credits, authentication, errors, limits, generate, retrieve, webhooks) from the page HTML.

cd /tmp && timeout 25 curl -s -o openapi.json -w "%{http_code}\n" https://thenewblack.ai/api/v1/openapi.json; python3 -c "
import json;d=json.load(open('openapi.json'));print(d['info']);print(len(d['paths']));print(list(d['paths'])[:40])" 2>&1|head -20
200
200
{'title': 'The New Black AI — API', 'version': '1', 'description': "Generate AI fashion visuals from your own products, read and write the account's creations and tech packs, publish to Shopify and social accounts, and make Mila, the account's AI agent, work for you.\n\nThis document is assembled at the instant of the call: the fixed routes from their descriptions in the code, the workflows from the live catalogue. It is the source the docs page, the `tnb` CLI, the MCP connector and any agent read.\n\nHuman documentation: https://thenewblack.ai/clothing_fashion_api_integrations", 'contact': {'name': 'The New Black AI', 'url': 'https://thenewblack.ai/clothing_fashion_api_integrations', 'email': 'team@thenewblack.ai'}, 'license': {'name': 'Terms of service', 'url': 'https://thenewblack.ai/terms_of_service'}, 'termsOfService': 'https://thenewblack.ai/terms_of_service', 'x-generated-at': '2026-10-30T20:22:33.114Z', 'x-workflows-revision': '870852d33bdc5fb6', 'x-openapi-revision': '80cf958128362350'}
36
['/openapi.json', '/catalog', '/catalog/presets', '/workflows', '/generate', '/generations/{id}', '/credits', '/account', '/account/invoices', '/ledger', '/brand-dna', '/brand-dna/{id}', '/media', '/media/upload', '/elements', '/projects', '/techpacks', '/techpacks/{id}', '/techpacks/{id}/pdf', '/techpacks/{id}/sections', '/techpacks/{id}/sections/{sectionId}', '/techpacks/from-photos', '/moodboards', '/moodboards/{id}/pdf', '/shopify/products', '/shopify/publish', '/publish/accounts', '/publish', '/publish/{id}', '/mila', '/mila/messages', '/mila/stop', '/mila/schedules', '/mila/schedules/{scheduleId}', '/files', '/files/{id}']
cd /tmp && timeout 25 curl -s https://thenewblack.ai/clothing_fashion_api_integrations > page.html && python3 - <<'EOF'
import re,html
t=open('page.html').read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S); t=re.sub(r'<style.*?</style>','',t,flags=re.S)
t=re.sub(r'<[^>]+>','\n',t); t=html.unescape(t)
t=re.sub(r'[ \t]+',' ',t); t=re.sub(r'\n\s*\n+','\n',t)
open('page.txt','w').write(t)
i=t.find('Guide')
print(t[i:i+9000])
EOF
Guide
Guide
Introduction
Authentication
Errors
Rate limits
Create a generation
Retrieve a generation
Webhooks
Credits
MCP
Command line
Migrating from the legacy API
Status
GET
/v1/workflows
Workflows catalogue 
(
77
)
Every studio workflow is callable by its versioned endpoint name. The route returns the live catalogue — named image parameters, fields, variants, formats and prices; the table below is rendered from the same data.
Method
Workflow key
Title
Mode
Standard
Pro
Ultra
Max refs
POST
freeform_image-v1
Free Prompt Image
image
1 cr
3 cr
7 cr
3
POST
freeform_video-v1
Free Prompt Video
video
2.2 cr/s
4.4 cr/s
23 cr/s
1
POST
virtual_try_on-v1
Virtual Try-On
image
1 cr
3 cr
7 cr
5
POST
product_to_model-v1
Product to Model
image
1 cr
3 cr
7 cr
5
POST
image_to_ghost_mannequin-v1
Image to Ghost Mannequin
image
1 cr
3 cr
7 cr
1
POST
change_color-v1
Change a Color
image
1 cr
3 cr
7 cr
1
POST
create_design-v1
Create a Product
image
1 cr
3 cr
7 cr
3
POST
enhance_photo_to_hd-v1
Enhance Photo to HD (2K/4K)
image
1 cr
3 cr
—
3
POST
retouch-v1
Edit an Area
image
1 cr
3 cr
—
16
POST
reimagine_scene-v1
Reimagine your Model
image
1 cr
3 cr
7 cr
1
POST
edit_video-v1
Edit video
video
3.3 cr/s
4.3 cr/s
—
1
POST
motion_design-v1
Motion Design
video
4 cr
4 cr
—
4
POST
model_walk-v1
Model Walk
video
2.2 cr/s
4.4 cr/s
23 cr/s
1
POST
product_360-v1
Product 360
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
model_360-v1
Model 360
video
2.2 cr/s
4.4 cr/s
23 cr/s
2
POST
swap_models-v1
Swap Model
image
1 cr
3 cr
7 cr
1
POST
face_swap-v1
Face Swap
image
1 cr
1 cr
—
2
POST
fabric_to_design-v1
Fabric to Image
image
1 cr
3 cr
7 cr
1
POST
image_to_fabric-v1
Image to Fabric
image
1 cr
3 cr
7 cr
1
POST
text_to_textile-v1
Text to Textile
image
1 cr
3 cr
7 cr
3
POST
snap_freeze-v1
Snap Freeze
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
ugc_video-v1
UGC Video
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
image_to_flat_lay-v1
Image to Flat Lay
image
1 cr
3 cr
7 cr
1
POST
swap_fabrics-v1
Swap Fabrics
image
1 cr
3 cr
7 cr
2
POST
logo_placement-v1
Add a Logo
image
1 cr
3 cr
—
3
POST
text_to_sketch-v1
Text to Sketch
image
1 cr
3 cr
7 cr
3
POST
sketch_to_image-v1
Sketch to Image
image
1 cr
3 cr
—
1
POST
image_to_sketch-v1
Image to Sketch
image
1 cr
3 cr
7 cr
2
POST
sketch_to_svg-v1
Sketch to SVG
image
1 cr
1 cr
—
1
POST
vectorize_image-v1
Vectorize Prints & Logos
image
1 cr
1 cr
—
1
POST
insert_fabric_on_sketch-v1
Insert Fabric on Sketch
image
1 cr
3 cr
7 cr
2
POST
create_similar_outfits-v1
Create Similar Outfits
image
1 cr
3 cr
7 cr
1
POST
create_design_variations-v1
Create Design Variations
image
1 cr
3 cr
7 cr
1
POST
change_background-v1
Change Background
image
1 cr
3 cr
—
2
POST
remove_background-v1
Remove Background
image
0.5 cr
0.5 cr
—
1
POST
ad_creative-v1
Ad Creative
image
1 cr
3 cr
7 cr
2
POST
enhance_video_to_hd-v1
Enhance Video to HD
video
4.4 cr/s
4.4 cr/s
—
3
POST
ai_stylist-v1
AI Stylist
image
1 cr
3 cr
7 cr
1
POST
outpaint_new_ratio-v1
Expand Image
image
1 cr
1 cr
—
1
POST
create_3d_models-v1
Image to 3D
3d
10 cr
10 cr
—
1
POST
tryon_video-v1
Virtual Try-On Video
video
2.2 cr/s
4.4 cr/s
23 cr/s
2
POST
outfit_transition-v1
Outfit Transition
video
2.2 cr/s
4.4 cr/s
23 cr/s
2
POST
fashion_ad-v1
Fashion Ad
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
detail_closeup-v1
Detail Close-up
video
2.2 cr/s
4.4 cr/s
23 cr/s
1
POST
editorial_video-v1
Editorial Lookbook
video
2.2 cr/s
4.4 cr/s
23 cr/s
1
POST
outfit_drop-v1
Outfit Drop
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
remove_video_background-v1
Remove Video Background
video
1.4 cr/s
1.4 cr/s
—
1
POST
reframe_video-v1
Reframe Video
video
4.4 cr/s
4.4 cr/s
—
1
POST
passerby_transition-v1
Passer-By Transition
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
crosswalk_look_switch-v1
Look Switch Walk
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
change_video_background-v1
Change Video Background
video
4.4 cr/s
8.8 cr/s
—
1
POST
change_video_outfit-v1
Edit Outfit in Video
video
3.3 cr/s
4.3 cr/s
—
1
POST
swap_video_model-v1
Swap Model in Video
video
3.3 cr/s
4.3 cr/s
—
2
POST
hanger_layering-v1
Hanger Switch
video
2.2 cr/s
4.4 cr/s
23 cr/s
5
POST
window_walkby-v1
Window Walk-By
video
2.2 cr/s
4.4 cr/s
23 cr/s
3
POST
detail_zoom_rush-v1
Detail Zoom Rush
video
2.2 cr/s
4.4 cr/s
23 cr/s
1
POST
outfit_morph-v1
Outfit Morph
video
2.2 cr/s
4.4 cr/s
23 cr/s
4
POST
freeform_audio-v1
Create a Soundtrack
audio
2 cr
2 cr
—
1
POST
voice_over-v1
Create a Voice-over
audio
1.06 cr/1k chars
2.12 cr/1k chars
2.12 cr/1k chars
3
POST
motion_collection_panorama-v1
Collection Panorama
video
1 cr
1 cr
—
6
POST
motion_split_reel-v1
Split Reel
video
1 cr
1 cr
—
4
POST
motion_style_post-v1
Style Post
video
1 cr
1 cr
—
1
POST
motion_look_film-v1
Look Film
video
1 cr
1 cr
—
4
POST
motion_colour_drop-v1
Colour Drop
video
1 cr
1 cr
—
4
POST
motion_phone_promo-v1
Phone Promo
video
1 cr
1 cr
—
4
POST
motion_cut_montage-v1
Cut Montage
video
1 cr
1 cr
—
6
POST
motion_paper_collage-v1
Paper Collage
video
1 cr
1 cr
—
8
POST
motion_lineup-v1
Lineup
video
1 cr
1 cr
—
6
POST
motion_character_select-v1
Character Select
video
1 cr
1 cr
—
6
POST
motion_grid_mosaic-v1
Grid Mosaic
video
1 cr
1 cr
—
2
POST
motion_ways_to_wear-v1
Ways to Wear
video
1 cr
1 cr
—
6
POST
motion_detail_study-v1
Detail Study
video
1 cr
1 cr
—
3
POST
motion_signature_film-v1
Signature Film
video
1 cr
1 cr
—
4
POST
motion_outfit_picker-v1
Outfit Picker
video
1 cr
1 cr
—
4
POST
motion_beat_cut-v1
Beat Cut
video
1 cr
1 cr
—
4
POST
motion_bold_word-v1
Bold Word
video
1 cr
1 cr
—
4
POST
motion_mix_match-v1
Mix & Match
video
1 cr
1 cr
—
6
Publishing catalogue 
(
5
)
Send what you create where it sells, by API — keys with the
publish
 scope. One documentation page per platform.
Platform
Endpoints
Publishes
Status
 Shopify
/v1/shopify/products · /v1/shopify/publish
Images & videos onto product pages
live
Instagram
/v1/publish/accounts · /v1/publish · /v1/publish/
{id}
Images & videos as feed posts, stories, carousels, reels
live
TikTok
/v1/publish/accounts · /v1/publish · /v1/publish/
{id}
Videos & photo posts
live
X
/v1/publish/accounts · /v1/publish · /v1/publish/
{id}
Images & videos as posts
live
Pinterest
/v1/publish/accounts · /v1/publish · /v1/publish/
{id}
Images & videos as pins, onto a board
live
YouTube
/v1/publish/accounts · /v1/publish · /v1/publish/
{id}
Videos as Shorts
live
GET
/v1/media · /v1/projects · /v1/elements · /v1/media/upload
Creations catalogue 
(
4
)
Read back what the account has created — keys with the
read
 scope. Every listing accepts
?project=<id>
 to filter by project. PDF exports return a JSON 
{ url }
 — public but unguessable, the same regime as every creation URL.
Resource
Endpoints
Returns
Status
Media
GET
/v1/media
Your images, videos, 3D models and soundtracks — URLs, thumbnails, project; filters by project, type, favourites, prompt words, workflow, date; next_before and next_before_id page back
live
Projects
GET
/v1/projects
Your projects — the filter of every listing
live
Elements
GET
/v1/elements
Your starred pot — creations, presets, uploads
live
Upload
POST
/v1/media/upload
multipart `file` (JPG, PNG, WebP, 15 MB) + optional `project` → { media_id, url } — a picture of yours, hosted by us, for any image parameter
live
GET
/v1/account · /v1/credits · /v1/ledger · /v1/account/invoices · /v1/brand-dna
Account 
(
6
)
The account as its AI agent reads it, for your own program: everything in one reading, the credit balance, what it spent and received, its invoices, and its Visual styles with the analysis the vision model wrote.
read
 scope; nothing is debited.
Action
Endpoints
Returns
Status
Read the account
GET
/v1/account
Username, credits, plan, team, brand, Shopify store, Visual styles, projects with their counts, exact library counts, tech packs
live
Credit balance
GET
/v1/credits
The balance, one decimal
live
Read the ledger
GET
/v1/ledger?days=30&lines=60
The credit lines of the period, signed, and the usage by team member
live
Invoices
GET
/v1/account/invoices?limit=12
Every invoice, plans and credit packs, newest first, with its page and its PDF; next_starting_after pages back
live
Visual style
GET
/v1/brand-dna · /v1/brand-dna/{id}
The profiles; one in full with its references and its analysis text
live
curl "https://thenewblack.ai/api/v1/account" \
 -H "Authorization: Bearer tnb_live_XXXXXXXXXXXX"
{
 "id": "a1e259ae-...", "username": "maison-k", "credits": 206.5,
 "team": { "role": "leader", "members": [{ "id": "3edf...", "username": "lea" }] },
 "brand_dna": [{ "id": "7c1a...", "name": "SS27", "focus": "womenswear", "analysed": true, "references": 12 }],
 "library": { "creations": 1000, "favourites": 3, "archived": 3 },
 "projects": [{ "id": "7763...", "name": "Linen capsule", "creations": 41, "archived": 0, "last_creation": "2026-09-11T16:02:00Z" }],
 "counts": { "shopify_products": 18, "techpacks": 4 },
 "techpacks": [{ "id": "8363...", "name": "Custom Print Crew Neck T-Shirt", "pages": 2, "project": null, "template": false, "origin": "ai", "updated_at": "2026-09-10T09:14:00Z" }]
}
GET
/v
Thinking…

Now let me read the guide sections: authentication, errors, rate limits, create a generation, retrieve, webhooks, credits. Find in page.txt after the catalogues. Let me grep for "Credits" section and "Rate limits".

cd /tmp && python3 - <<'EOF'
t=open('page.txt').read()
i=t.find('Rate limits', t.find('Guide')+200)
print(t[i:i+7000])
EOF
Rate limits
Rate limits
An account starts a set number of generations a minute, through the API, the CLI and the MCP connector together: 30 without a plan or on Starter, 60 on Pro, 120 on Business, 300 on Enterprise. Reading — polling a generation, listing, checking credits — is not counted. Past the limit,
POST /v1/generate
 answers
429 rate_limited
 with a
Retry-After
 header (seconds to wait), and nothing is charged. Need more for a launch or a store network? 
Write to us
 — the limit can be raised for your account.
// 429 Too Many Requests · Retry-After: 12
{ "error": { "code": "rate_limited", "message": "This account starts at most 60 generations a minute on its plan. Try again in 12 s.",
 "retry_after": 12, "limit_per_minute": 60 } }
POST
/v1/generate
Create a generation
Requires the 
generate
 scope. Credits are debited when the request is accepted; if the balance is short nothing starts and nothing is charged. Returns
202
 with the generation id.
Parameter
Type
workflow
string
required
A versioned endpoint from the catalogue, e.g. 
create_design-v1
. The version is part of the name — earlier versions keep being served under theirs.
prompt
string
optional
What to create — in English for best results (workflows that take one). Required where the catalogue says 
prompt_required
: a picture made from words alone, and the text Voice reads.
<named images>
string
optional
Each workflow declares its image parameters by name, exactly like its panel — 
sketch_image
, 
fabric_image
, 
model_image
… — listed on its endpoint page and in the catalogue. Positional arrays are not accepted. A place the panel may hide (
conditional
 in the catalogue) is required only while the fields' choice shows it.
fields
object
optional
The workflow's panel fields by name, options validated — see its endpoint page.
variant
string
optional
Workflows with tabs: the variant by its visible title.
tier
string
optional
"standard" (default), "pro", or "ultra" where the catalogue lists it in 
tiers
: our best model at its largest output — a picture in 4K (from the Pro plan), a video in 1080p on our top video model. For a picture: 
standard
 — 
1K resolution image + fast generation
; 
pro
 — 
2K resolution image + thinking process before generating
; 
ultra
 — 
4K resolution image + deep thinking process before generating
. For a video: 
standard
 — 
720p resolution video + fast generation
; 
pro
 — 
1080p resolution video + thinking process before generating
; 
ultra
 — 
1080p resolution video + deep thinking process before generating
.
ratio
string
optional
From the workflow's offered ratios.
duration
string
optional
Video and soundtrack workflows: seconds of output, from the allowed durations.
visual_dna
string
optional
Optional — the id of one of your Visual styles (
GET /v1/brand-dna
) or a house style; its paragraph closes the prompt. Only on the workflows where the studio shows a Visual style (
visual_dna: true
 in the catalogue); refused elsewhere. How far it reaches is in 
effects.reach
.
sound
string
optional
Video workflows: "on" (default) keeps the clip's own sound, "off" makes it silent; how far it reaches is in 
effects.reach
.
end_image
string
optional
Video workflows that take one (
end_image: true
): an optional closing frame, one public HTTPS URL.
references
string[]
optional
Workflows that take them (
references: true
): one to three public HTTPS URLs put into the clip — a person, a garment, a place — instead of a start or end frame.
webhook_url
string
optional
Optional — we POST the outcome here when the generation settles. Without it, poll the URL returned in the response until the status settles.
curl -X POST https://thenewblack.ai/api/v1/generate \
 -H "Authorization: Bearer tnb_live_XXXXXXXXXXXX" \
 -H "Content-Type: application/json" \
 --data-binary @- <<'JSON'
{
 "workflow": "product_to_model-v1",
 "product_images": [
 "https://example.com/handbag.jpg"
 ],
 "fields": {
 "gender": "Woman",
 "seg_framing": "full body",
 "seg_scene": "a rooftop terrace at dusk"
 },
 "tier": "standard",
 "ratio": "4:5",
 "webhook_url": "https://example.com/hooks/tnb"
}
JSON
// 202 Accepted
{
 "generation_id": "3f1c9a6e-...",
 "status": "running",
 "poll": "/api/v1/generations/3f1c9a6e-..."
}
GET
/v1/generations/
{id}
Retrieve a generation
Requires the 
read
 scope. Poll every few seconds until
status
 is 
succeeded
 or
failed
. A failed generation is refunded automatically.
Most images are ready in under a minute — a background removal in seconds, a virtual try-on or a product on a model in about half a minute; videos take longer. The result's URL lives 
48 hours
: copy the file to your own storage. After that the result is deleted and the call answers 
expired
 — unless the creation was opened in the app, which keeps it like any other.
// 200 OK
{
 "generation_id": "3f1c9a6e-...",
 "workflow": "product_to_model",
 "status": "succeeded",
 "result": {
 "type": "image",
 "url": "https://.../result.webp",
 "thumbnail": "https://.../thumb.webp"
 }
}
Webhooks
Pass 
webhook_url
 when creating a generation and we POST the outcome — success or failure — to your endpoint the moment it settles, instead of being polled. Answer with any 2xx; we try once, with a 5-second timeout, and your poll endpoint always remains the source of truth.
// POST to your webhook_url
{
 "generation_id": "3f1c9a6e-...",
 "status": "succeeded",
 "result": { "type": "image", "url": "https://...", "thumbnail": "https://..." }
}
GET
/v1/credits
Credits
The account's live balance. Generation costs are per workflow and tier — see the catalogue; video is billed per second of output. Top up or subscribe on the
pricing page
.
// 200 OK
{ "credits": 142 }
MCP
The same capabilities inside a conversation: connect The New Black AI to Claude or ChatGPT as a Model Context Protocol server and generate from your chat — no code, same keys, same credits. The connector builds its tools from the live catalogue. Setup and details on the
MCP page
.
Building your integration 
with Claude Code
? Install our skill and Claude knows the whole contract — auth, the async loop, every workflow read live from the catalogue, the CLI — before it writes a line:
npx skills add newblackai/claude-skill --skill thenewblack
Command line
The same API as a program — for an AI coding agent (Claude Code, Codex, Cursor), a script, a cron or a CI job. One command per workflow, generated from the live catalogue, and one per route of this page; local pictures uploaded once, 
--wait
 and
--out
 do the plumbing. In a conversation, add the connector; in a project of code, install the CLI. Everything on the
CLI page
.
npx @thenewblack/cli --help
tnb generate virtual_try_on --product_images dress.jpg --model_image model.jpg --ratio 4:5 --wait --out ./renders/
Migrating from the legacy API
When the platform migration completes, the legacy endpoints are retired and answer with a notice pointing here. Keys are 
not
 carried over: create a new key from your
API / MCP tab
, point your integratio
Thinking…

Now pricing: the pricing page. Let me fetch it for credit pack prices and plans. Also check errors section and authentication section text.

Let me get the pricing page.

cd /tmp && timeout 25 curl -s https://thenewblack.ai/pricing > pricing.html && python3 - <<'EOF'
import re,html
t=open('pricing.html').read()
t=re.sub(r'<script.*?</script>','',t,flags=re.S); t=re.sub(r'<style.*?</style>','',t,flags=re.S)
t=re.sub(r'<[^>]+>','\n',t); t=html.unescape(t)
t=re.sub(r'[ \t]+',' ',t); t=re.sub(r'\n\s*\n+','\n',t)
open('pricing.txt','w').write(t)
print(len(t)); print(t[:6000])
EOF
10089
10089

Pricing | The New Black AI
The New Black AI
T
he 
N
ew 
B
lack 
AI
he 
ew 
lack 
Pricing
Pricing
Tutorials
Log in
Start free
The New Black 
AI
Start
Subscribe to a plan
A one-off top-up, on any account.
Packs are limited to 
basic features
 when no plan is active.
Compare the plans and what each one unlocks.
Need more? 
Add multiple plans.
Monthly
Yearly
2 months free
Packs
Starter
Create your first visuals with AI
$15
/month
Billed monthly, cancel anytime
Start for $15/month
200 credits / month
Every workflow
3 Visual styles
See everything included
Credits
200 / month · hold up to 700
Studio
Every workflow
HD 4K, bulk generation, video montage
3 Visual styles
Brand Manager
Your store's full history
Act from the Store, profit & loss
Publish to Instagram, TikTok, YouTube…
Launch ad campaigns
Tools
Unlimited lookbooks
Unlimited tech packs
Unlimited canvases
Connect your custom domain
Team & agents
Several brands from one account
3 seats
AI agent · spends up to 200 cr / month
API · 30 generations / minute
See what every plan unlocks
Pro
For a brand selling every season
$35
/month
Billed monthly, cancel anytime
Start for $35/month
500 credits / month
HD 4K, bulk generation, video montage
10 Visual styles
See everything included
Credits
500 / month · hold up to 2,000
Studio
Every workflow
HD 4K, bulk generation, video montage
10 Visual styles
Brand Manager
Your store's full history
Act from the Store, profit & loss
Publish to Instagram, TikTok, YouTube…
Launch ad campaigns
Tools
Unlimited lookbooks
Unlimited tech packs
Unlimited canvases
Connect your custom domain
Team & agents
Several brands from one account
5 seats
AI agent · spends up to 500 cr / month
API · 60 generations / minute
See what every plan unlocks
Most popular
Business
Grow your sales with full access
$65
/month
Billed monthly, cancel anytime
Start for $65/month
1,000 credits / month
Unlimited Visual styles
Launch ad campaigns
See everything included
Credits
1,000 / month · hold up to 4,000
Studio
Every workflow
HD 4K, bulk generation, video montage
Unlimited Visual styles
Brand Manager
Your store's full history
Act from the Store, profit & loss
Publish to Instagram, TikTok, YouTube…
Launch ad campaigns
Tools
Unlimited lookbooks
Unlimited tech packs
Unlimited canvases
Connect your custom domain
Team & agents
Several brands from one account
Unlimited seats
AI agent · spends up to 1,000 cr / month
API · 120 generations / minute
See what every plan unlocks
Enterprise
Multi-brands
For a brand at scale, a group or an agency
$195
/month
Billed monthly, cancel anytime
Start for $195/month
3,000 credits / month
Several brands from one account
AI agent · spends up to 3,000 cr / month
See everything included
Credits
3,000 / month · hold up to 12,000
Studio
Every workflow
HD 4K, bulk generation, video montage
Unlimited Visual styles
Brand Manager
Your store's full history
Act from the Store, profit & loss
Publish to Instagram, TikTok, YouTube…
Launch ad campaigns
Tools
Unlimited lookbooks
Unlimited tech packs
Unlimited canvases
Connect your custom domain
Team & agents
Several brands from one account
Unlimited seats
AI agent · spends up to 3,000 cr / month
API · 300 generations / minute
See what every plan unlocks
What every plan unlocks
What you can do
Packs only
See packs
Starter
$15/mo
Pro
$35/mo
Business
$65/mo
Enterprise
$195/mo
Credits
Credits every month
—
200
500
1,000
3,000
Credits you can hold
pack size
700
2,000
4,000
12,000
Studio
Every workflow, photo and video — Standard AI
PRO AI — a stronger model, video in 1080p
Ultra AI video — our best video model, up to 30 seconds
Ultra AI photos — our best image model, in 4K
Enhance to HD 2K
Enhance to HD 4K
Bulk generation — a whole catalog at once
Visual styles
3
10
Unlimited
Unlimited
Model, product and fabric presets
Photo montage — type, layers, compose by hand
Video montage — cut clips, titles, music
Brand Manager
Connect your store — sales, traffic, SEO and ads on one dashboard
Import your Shopify catalog
Publish your creations to Shopify
Write articles, pages, newsletters and theme texts with AI
Email campaigns with Klaviyo
Authority & backlinks of your store
Publish to Instagram, Facebook, Pinterest, TikTok, YouTube, X
Act from the Store — campaigns, budgets, stock, costs, theme, articles
Add your visuals to running ad campaigns
Profit & loss
Launch Meta, Google, Pinterest and X campaigns from your creations
Lookbook
Lookbooks, online at their own address
2
Unlimited
Unlimited
Unlimited
Unlimited
Links to your products and any page
Your own domain — lookbook.yourbrand.com
Without our mark on the last page
Tech pack
Tech packs, built by hand
2
Unlimited
Unlimited
Unlimited
Unlimited
Tech packs drafted by the AI, AI review
credits
credits
credits
credits
credits
Canvas
Canvases
Team & projects
Projects, shared with your team
Team seats
1
3
5
Unlimited
Unlimited
Multi-brands — a workspace per brand, same plan and credits
AI agents
AI agent — chat, tasks, scheduled jobs, connectors
Credits your agent can spend a month
50 / 30 days
200
500
1,000
3,000
API
API access and keys
API rate, generations per minute
30
30
60
120
300
Create from Claude and ChatGPT via MCP
Packs
Starter
Pro
Business
Enterprise
$35/mo
Credits
Credits every month
500
Credits you can hold
2,000
Studio
Every workflow, photo and video — Standard AI
PRO AI — a stronger model, video in 1080p
Ultra AI video — our best video model, up to 30 seconds
Ultra AI photos — our best image model, in 4K
Enhance to HD 2K
Enhance to HD 4K
Bulk generation — a whole catalog at once
Visual styles
10
Model, product and fabric presets
Photo montage — type, layers, compose by hand
Video montage — cut clips, titles, music
Brand Manager
Connect your store — sales, traffic, SEO and ads on one dashboard
Import your Shopify catalog
Publish your creations to Shopify
Write articles, pages, newsletters and theme texts with AI
Email campaigns with Klaviyo
Authority & backlinks of your store
Publish to Instagram, Facebook, Pinterest, TikTok, Yo
cd /tmp && python3 - <<'EOF'
t=open('page.txt').read()
i=t.find('Introduction', t.find('Guide')+200)
print(t[i:i+4200])
EOF
Introduction
Introduction
The API is asynchronous, like the studio it drives: you submit a generation, credits are debited atomically at submission, and you collect the result by polling — or let us call your webhook when it settles. A generation that fails is refunded automatically.
Serving several stores or clients? On the
Enterprise plan
, each one can be a workspace of its own — its own API keys, its own creations — on one plan and one balance, with the usage of each workspace in Team › Usage.
Base URL https://thenewblack.ai/api/v1
Format JSON in, JSON out
Auth Authorization: Bearer tnb_live_...
The whole API is described in OpenAPI 3.1, publicly and without a key, generated at the instant of the call:
GET /api/v1/openapi.json
— every route, every workflow as a body schema of 
/generate
, every error code. Point a code generator, an agent or an SDK builder at it. The catalogue alone is at
GET /api/v1/catalog
 (every workflow's contract and prices) and
GET /api/v1/catalog/presets
 (the stock preset shelves). The Claude connector and the CLI build themselves from these.
Authentication
Create up to three keys from your account's
API / MCP tab
. A key is shown once at creation and stored only as a hash — keep it server-side, never in a browser. Keys belong to the paying account: on a team, they spend the leader's credits.
Each key carries 
scopes
 chosen at creation:
generate
 (create with the workflows and edit tech packs — spends credits),
read
 (poll generations, list workflows, check credits, read the account, the ledger, the Visual style and everything in the Creations catalogue),
agents
 (talk to Mila, her calendar and the Files — spends credits like the chat),
publish
 (post to connected platforms —
Shopify
 and
the social platforms
).
curl https://thenewblack.ai/api/v1/credits \
 -H "Authorization: Bearer tnb_live_XXXXXXXXXXXX"
Errors
Errors are JSON with a stable 
code
 and a human
message
:
{ "error": { "code": "insufficient_credits", "message": "Not enough credits — this needs 3." } }
Parameter
Type
401
status
required
missing_key · invalid_key — no key, or an unknown/revoked one.
402
status
required
insufficient_credits — the account balance cannot cover the generation.
403
status
required
missing_scope — the key exists but lacks the scope for this action.
404
status
required
unknown_workflow · not_found — no such workflow, or no such generation on this account.
429
status
required
rate_limited — the account started its plan's generations for this minute; wait the 
Retry-After
 seconds. Nothing was charged.
502
status
required
generation_refused — the job was refused; any debited credit is refunded.
Rate limits
An account starts a set number of generations a minute, through the API, the CLI and the MCP connector together: 30 without a plan or on Starter, 60 on Pro, 120 on Business, 300 on Enterprise. Reading — polling a generation, listing, checking credits — is not counted. Past the limit,
POST /v1/generate
 answers
429 rate_limited
 with a
Retry-After
 header (seconds to wait), and nothing is charged. Need more for a launch or a store network? 
Write to us
 — the limit can be raised for your account.
// 429 Too Many Requests · Retry-After: 12
{ "error": { "code": "rate_limited", "message": "This account starts at most 60 generations a minute on its plan. Try again in 12 s.",
 "retry_after": 12, "limit_per_minute": 60 } }
POST
/v1/generate
Create a generation
Requires the 
generate
 scope. Credits are debited when the request is accepted; if the balance is short nothing starts and nothing is charged. Returns
202
 with the generation id.
Parameter
Type
workflow
string
required
A versioned endpoint from the catalogue, e.g. 
create_design-v1
. The version is part of the name — earlier versions keep being served under theirs.
prompt
string
optional
What to create — in English for best results (workflows that take one). Required where the catalogue says 
prompt_required
: a picture made from words alone, and the text Voice reads.
<named images>
string
optional
Each workflow declares its image parameters by name, exactly like its panel — 
sketch_image
, 
fabric_image
, 
model_image
… — listed on its endpoint page and in the cata
Thinking…

Also grab credit pack prices (one-off top-ups). The pricing text mentioned "Packs ... A one-off top-up" but the pack prices may be rendered client-side. Let me search pricing.txt for "$" values and "credits" pack amounts.

Also check /api/v1/catalog (public, no key). Let's verify.

Then build the example. Since we don't have an API key, the example must be runnable without one for the read-only parts, and dry-run for generation. I'll build:

  • A tiny Node script examples/tnb-demo.mjs? Or a bash + Node? Keep it simple: a single Node script using fetch (Node 18+) that:
    1. Reads the live catalogue (public, no key) → prints prices for a chosen workflow.
    2. If TNB_API_KEY set: check credits, submit a generation (e.g. remove_background-v1 or create_design-v1 with prompt), poll until settled, download the result to ./renders/.
    3. Dry-run mode by default if no key: prints the exact request it would send.

Plus a README with pricing notes.

Let's check the catalog endpoint is public and the pack prices.

cd /tmp && timeout 25 curl -s -o catalog.json -w "catalog %{http_code}\n" https://thenewblack.ai/api/v1/catalog && python3 -c "
import json;d=json.load(open('catalog.json'))
print(type(d), list(d)[:10] if isinstance(d,dict) else len(d))
w=d['workflows'] if isinstance(d,dict) and 'workflows' in d else d
print(len(w))
import json as j
print(j.dumps(w[0] if isinstance(w,list) else list(w.items())[0], indent=1)[:2500])
"
catalog 200
catalog 200
<class 'dict'> ['catalog_version', 'workflows_revision', 'base_url', 'services', 'workflows']
77
{
 "endpoint": "freeform_image-v1",
 "key": "freeform_image",
 "version": 1,
 "title": "Free Prompt Image",
 "description": "Create or edit an image",
 "mode": "image",
 "thumbnail": "https://cloud.thenewblack.ai/storage/v1/object/public/workflow-thumbnails/b8216b8b-7b89-4f39-8195-367aec1cf781.jpg",
 "takes_prompt": true,
 "images": [
  {
   "param": "reference_images",
   "label": "Reference images",
   "required": false,
   "multiple": true,
   "max": 3,
   "media": "image"
  }
 ],
 "fields": [],
 "variants": [],
 "ratios": [
  "auto",
  "9:16",
  "1:1",
  "4:5",
  "3:4",
  "2:3",
  "16:9",
  "4:3",
  "3:2",
  "5:4",
  "21:9"
 ],
 "durations": [],
 "end_image": false,
 "references": false,
 "requires_plan": false,
 "visual_dna": true,
 "credits": {
  "standard": 1,
  "pro": 3,
  "ultra": 7,
  "unit": "per generation",
  "rounding": "a fixed price per generation"
 },
 "tiers": [
  "standard",
  "pro",
  "ultra"
 ],
 "effects": {
  "visual_dna": true,
  "reach": {
   "visual_dna": "all"
  }
 },
 "prompt_required": true
}
cd /tmp && grep -nE '\$[0-9]+|[0-9,]+ credits' pricing.txt | head -40
36:$15
36:$15
39:Start for $15/month
40:200 credits / month
68:$35
71:Start for $35/month
72:500 credits / month
101:$65
104:Start for $65/month
105:1,000 credits / month
134:$195
137:Start for $195/month
138:3,000 credits / month
169:$15/mo
171:$35/mo
173:$65/mo
175:$195/mo
273:$35/mo
333:1 credit ≈ 1 image, 10 credits ≈ 1 video. The price is always shown before you generate.
Thinking…

Pack prices are client-rendered; only "1 credit ≈ 1 image, 10 credits ≈ 1 video". Good enough for pricing explanation. Let me check line ~320-360 of pricing.txt for pack section details.

Now build the example. Keep it light: one script + README. No API key available → verify the script runs in "dry-run/no-key" mode against the live public catalogue, and confirm auth-gated paths produce the documented error (already saw 401 missing_key).

Let's write:

  • /sandbox/repo/examples/thenewblack/demo.mjs — Node 18+, zero deps: reads /api/v1/catalog, picks a workflow, prints price; if TNB_API_KEY present: GET /credits, POST /generate, poll, download to renders/. Default: dry-run when no key.
  • /sandbox/repo/examples/thenewblack/README.md

Run it to verify.

Check node version.

cd /tmp && sed -n '320,345p' pricing.txt; node --version
5
5
Multi-brands — a workspace per brand, same plan and credits
AI agents
AI agent — chat, tasks, scheduled jobs, connectors
Credits your agent can spend a month
500
API
API access and keys
API rate, generations per minute
60
Create from Claude and ChatGPT via MCP
How it works
Credits pay for generations
1 credit ≈ 1 image, 10 credits ≈ 1 video. The price is always shown before you generate.
The plan is the licence
What each plan unlocks is in the table above; credits are the fuel.
Credit packs
Packs alone open the Standard studio; plan features need an active plan.
Your credit bank
The most you can hold at once. Plans and packs stack to raise it.
Roll over, pause, cancel
Credits roll over while a plan is active. Pause or cancel whenever you like.
Security
Encrypted in transit
TLS 1.2 and 1.3. HTTPS enforced.
Encrypted at rest
v22.23.4
Thinking…

Pack dollar prices aren't in the static HTML (client-rendered). I'll note that. Maybe check an API for packs? Not necessary.

Now write the example.

File edits

1 file

Completed
Writtenexamples/thenewblack/demo.mjsView changes

/sandbox/repo/examples/thenewblack/demo.mjs

Written content · previous contents were not recorded

#!/usr/bin/env node
/**
* The New Black AI — minimal hosted-API example (zero dependencies, Node >= 18).
*
* The whole product is hosted: https://thenewblack.ai/api/v1 — nothing to run locally.
* The public, key-free endpoints (openapi.json, /catalog) let you read the live
* contract and prices before you spend a credit.
*
* Usage:
* node demo.mjs # dry run: live catalogue + price, no key needed
* node demo.mjs --list # every workflow with its prices
* node demo.mjs --workflow create_design-v1 --prompt "..." --tier standard
* TNB_API_KEY=tnb_live_... node demo.mjs --workflow create_design-v1 --prompt "..." --run
*
* --run submits for real (credits are debited at submission, refunded on failure).
* Without --run or without TNB_API_KEY the script only prints what it would send.
*/
const BASE = process.env.TNB_API_URL || "https://thenewblack.ai/api/v1";
const KEY = process.env.TNB_API_KEY || "";
const argv = process.argv.slice(2);
const flag = (name, dflt = undefined) => {
const i = argv.indexOf(`--${name}`);
return i === -1 ? dflt : argv[i + 1];
};
const has = (name) => argv.includes(`--${name}`);
async function json(path, init) {
const res = await fetch(BASE + path, {
...init,
headers: {
"Content-Type": "application/json",
...(KEY ? { Authorization: `Bearer ${KEY}` } : {}),
...(init?.headers || {}),
},
});
const body = await res.json().catch(() => ({}));
if (!res.ok) {
const e = body.error || {};
throw new Error(`${res.status} ${e.code || res.statusText}: ${e.message || ""}`.trim());
}
return body;
}
const priceOf = (w, tier) => {
const c = w.credits?.[tier] ?? w.credits?.standard;
if (c == null) return "—";
return w.mode === "video" ? `${c} cr/s` : `${c} cr`;
};
async function listCatalog() {
const { workflows } = await json("/catalog"); // public, no key
for (const w of workflows) {
console.log(
[w.endpoint.padEnd(34), w.mode.padEnd(6),
`std ${priceOf(w, "standard")}`.padEnd(14),
`pro ${priceOf(w, "pro")}`.padEnd(14),
`ultra ${priceOf(w, "ultra")}`].join(" ")
);
}
console.log(`\n${workflows.length} workflows. Prices read live from the catalogue.`);
}
async function main() {
if (has("list")) return listCatalog();
const workflow = flag("workflow", "create_design-v1");
const prompt = flag("prompt", "a minimal linen overshirt, sand colour, studio light");
const tier = flag("tier", "standard");
const ratio = flag("ratio", "4:5");
// 1. Read the live contract for this workflow (public, costs nothing).
const { workflows } = await json("/catalog");
const w = workflows.find((x) => x.endpoint === workflow);
if (!w) throw new Error(`unknown workflow ${workflow} — run with --list`);
console.log(`${w.endpoint} · ${w.title} (${w.mode})`);
console.log(` price : ${priceOf(w, tier)} (${w.credits?.unit || "per generation"})`);
console.log(` images : ${w.images.map((i) => i.param).join(", ") || "none"}`);
console.log(` fields : ${w.fields.map((f) => f.param || f.name).join(", ") || "none"}`);
console.log(` ratios : ${w.ratios.join(" ") || "none"}`);
console.log(` prompt : ${w.prompt_required ? "required" : "optional"}`);
const payload = { workflow, tier, ...(w.takes_prompt ? { prompt } : {}), ...(w.ratios.length ? { ratio } : {}) };
// 2. Without a key (or without --run) stop here: show the exact request.
if (!KEY || !has("run")) {
console.log(`\nDRY RUN${KEY ? "" : " (no TNB_API_KEY)"} — would POST ${BASE}/generate:`);
console.log(JSON.stringify(payload, null, 2));
console.log("\nSet TNB_API_KEY=tnb_live_… and add --run to spend credits for real.");
return;
}
// 3. Balance, submit, poll, save. Reads are free and not rate limited.
console.log(`\ncredits before: ${(await json("/credits")).credits}`);
const submitted = await json("/generate", { method: "POST", body: JSON.stringify(payload) });
console.log(`submitted: ${submitted.generation_id} (${submitted.status})`);
const poll = submitted.poll.replace(/^\/api\/v1/, "") || `/generations/${submitted.generation_id}`;
const started = Date.now();
for (;;) {
await new Promise((r) => setTimeout(r, 5000));
const g = await json(poll);
process.stdout.write(` ${((Date.now() - started) / 1000).toFixed(0)}s ${g.status}\n`);
if (g.status === "succeeded") {
console.log(`result (${g.result.type}): ${g.result.url}`);
console.log("URL lives 48 h — copy it to your own storage.");
return;
}
if (g.status === "failed") {
console.log("failed — credits refunded automatically.");
return;
}
if (Date.now() - started > 10 * 60 * 1000) return console.log("gave up after 10 min; poll the id later.");
}
}
main().catch((e) => {
console.error(e.message);
process.exit(1);
});

File edits

1 file

Completed
Writtenexamples/thenewblack/README.mdView changes

/sandbox/repo/examples/thenewblack/README.md

Written content · previous contents were not recorded

# The New Black AI — minimal example
Hosted AI fashion-image/video generation. Everything runs on their servers; there is
nothing to install or run locally beyond this script.
- API base: `https://thenewblack.ai/api/v1` (JSON in / JSON out, `Authorization: Bearer tnb_live_…`)
- Live contract, public and key-free: `GET /api/v1/openapi.json`, `GET /api/v1/catalog`
- Docs: https://thenewblack.ai/clothing_fashion_api_integrations
- Official CLI (same API, JSON out): `npx @thenewblack/cli --help`
## Run
```sh
node demo.mjs --list # every workflow + live prices (no key)
node demo.mjs # dry run of one generation (no key)
TNB_API_KEY=tnb_live_… node demo.mjs --run \
--workflow create_design-v1 --prompt "a minimal linen overshirt, sand colour" --tier standard
```
Keys are created in the account's **API / MCP tab** (up to 3, with scopes `read`,
`generate`, `publish`, `agents`). `TNB_API_KEY` in the environment wins over `tnb login`.
## Flow
1. `GET /catalog` — the workflow's image params, fields, ratios, tiers and **price** (free).
2. `GET /credits` — balance (free, not rate limited).
3. `POST /generate` → `202` + `generation_id` + `poll` URL. Credits debited at submission.
4. `GET /generations/{id}` every few seconds until `succeeded` / `failed` (failures refund),
or pass `webhook_url` and let them POST the outcome once.
5. Download `result.url` — it expires after **48 hours**.
Errors carry a stable `code`: `missing_key`/`invalid_key` (401), `insufficient_credits` (402),
`missing_scope` (403), `unknown_workflow`/`not_found` (404), `rate_limited` (429 + `Retry-After`,
nothing charged), `generation_refused` (502, refunded).
## Pricing (as of 2026-10-30)
Credits are the fuel, the plan is the licence.
| Plan | $/mo | Credits/mo | Hold up to | API rate (generations/min) |
|---|---|---|---|---|
| Packs only | top-up | — | pack size | 30 |
| Starter | 15 | 200 | 700 | 30 |
| Pro | 35 | 500 | 2,000 | 60 |
| Business | 65 | 1,000 | 4,000 | 120 |
| Enterprise | 195 | 3,000 | 12,000 | 300 |
Per-generation cost is per workflow **and tier** — `standard` / `pro` / `ultra`
(1K→2K→4K images; 720p→1080p video). Typical image: 1 / 3 / 7 credits; video is billed
**per second of output** (e.g. 2.2 / 4.4 / 23 cr/s); `remove_background` 0.5 cr;
`create_3d_models` 10 cr. Their rule of thumb: 1 credit ≈ 1 image, 10 credits ≈ 1 video.
Ultra photos need the Pro plan or above. Credits roll over while a plan is active; packs
alone unlock only the Standard studio. Yearly billing = 2 months free.
Thinking…

Now run it to verify (quick, no long-running). Test --list (truncate), dry run, and a bogus key path to show error handling.

cd /sandbox/repo/examples/thenewblack && timeout 60 node demo.mjs --list 2>&1 | head -12; echo "=== dry run ==="; timeout 60 node demo.mjs 2>&1; echo "=== bad key ==="; TNB_API_KEY=tnb_live_nope timeout 60 node demo.mjs --run 2>&1 | tail -3
freeform_image-v1 image std 1 cr pro 3 cr ultra 7 cr
freeform_image-v1                  image  std 1 cr       pro 3 cr       ultra 7 cr
freeform_video-v1                  video  std 2.2 cr/s   pro 4.4 cr/s   ultra 23 cr/s
virtual_try_on-v1                  image  std 1 cr       pro 3 cr       ultra 7 cr
product_to_model-v1                image  std 1 cr       pro 3 cr       ultra 7 cr
image_to_ghost_mannequin-v1        image  std 1 cr       pro 3 cr       ultra 7 cr
change_color-v1                    image  std 1 cr       pro 3 cr       ultra 7 cr
create_design-v1                   image  std 1 cr       pro 3 cr       ultra 7 cr
enhance_photo_to_hd-v1             image  std 1 cr       pro 3 cr       ultra 1 cr
retouch-v1                         image  std 1 cr       pro 3 cr       ultra 1 cr
reimagine_scene-v1                 image  std 1 cr       pro 3 cr       ultra 7 cr
edit_video-v1                      video  std 3.3 cr/s   pro 4.3 cr/s   ultra 3.3 cr/s
motion_design-v1                   video  std 4 cr/s     pro 4 cr/s     ultra 4 cr/s
=== dry run ===
create_design-v1 · Create a Product (image)
  price   : 1 cr (per generation)
  images  : none
  fields  : product_type, age, bodyform, gender, country, craziness, outfit, seg_look, seg_view
  ratios  : 21:9 16:9 3:2 4:3 5:4 1:1 4:5 3:4 2:3 9:16
  prompt  : optional

DRY RUN (no TNB_API_KEY) — would POST https://thenewblack.ai/api/v1/generate:
{
  "workflow": "create_design-v1",
  "tier": "standard",
  "ratio": "4:5"
}

Set TNB_API_KEY=tnb_live_… and add --run to spend credits for real.
=== bad key ===
  ratios  : 21:9 16:9 3:2 4:3 5:4 1:1 4:5 3:4 2:3 9:16
  prompt  : optional
401 invalid_key: This API key is unknown or revoked.
Thinking…

Works. Small fix: in dry-run with prompt for create_design, prompt optional so omitted — fine, but the payload omits prompt when takes_prompt false; create_design takes_prompt? It printed prompt: optional, and payload lacks prompt — meaning w.takes_prompt is false for create_design? Payload didn't include prompt. Let me check: takes_prompt for create_design-v1. If takes_prompt is false but prompt is accepted... Let's check catalog entry.

Also "ultra 1 cr" for workflows without ultra — priceOf falls back to standard when ultra missing. Better to print "—" when the tier isn't in w.tiers. Fix that.

Also for the dry-run payload, include prompt when provided regardless (docs say workflows that take one). Let's inspect create_design entry.

cd /tmp && python3 -c "
import json;d=json.load(open('catalog.json'))
w=[x for x in d['workflows'] if x['endpoint']=='create_design-v1'][0]
print({k:w[k] for k in ('takes_prompt','prompt_required','tiers','credits','mode')})
print(json.dumps(w['fields'][0])[:300])
"
{'takes_prompt': False, 'prompt_required': False, 'tiers': ['standard', 'pro', 'ultra'], 'credits': {'standard': 1, 'pro': 3, 'ultra': 7, 'unit': 'per generatio
{'takes_prompt': False, 'prompt_required': False, 'tiers': ['standard', 'pro', 'ultra'], 'credits': {'standard': 1, 'pro': 3, 'ultra': 7, 'unit': 'per generation', 'rounding': 'a fixed price per generation'}, 'mode': 'image'}
{"name": "product_type", "label": "Product", "options": ["garment", "shoes", "bag", "jewelry", "eyewear", "headwear", "other"], "required": false, "hint": "What the product is \u2014 the studio's Product row.", "default": "garment"}
Thinking…

So create_design-v1 doesn't take a prompt at all — guided by fields. My default workflow choice with a prompt is misleading. Better default: freeform_image-v1 (prompt_required, no images needed) — a perfect "hello world". Update demo: default workflow freeform_image-v1, and include fields support maybe minimal. Also fix priceOf to show "—" for tiers not offered.

Also default example should include an optional --field key=value support? Keep light: add --field k=v repeatable, small.

Update README accordingly.

File edits

1 file

Completed
Modifiedexamples/thenewblack/demo.mjs+33−6View changes

/sandbox/repo/examples/thenewblack/demo.mjs

Replacement excerpt

- * node demo.mjs --workflow create_design-v1 --prompt "..." --tier standard
- * TNB_API_KEY=tnb_live_... node demo.mjs --workflow create_design-v1 --prompt "..." --run
+ * node demo.mjs --workflow virtual_try_on-v1 --product_images https://x/dress.jpg
+ * TNB_API_KEY=tnb_live_... node demo.mjs --run --prompt "..." --tier standard --field gender=Woman
+ *
+ * Repeatable: --field k=v (panel fields), --<param> url|file for named image params.

Replacement excerpt

const priceOf = (w, tier) => {
- const c = w.credits?.[tier] ?? w.credits?.standard;
+ const c = (w.tiers || []).includes(tier) ? w.credits?.[tier] : null;
if (c == null) return "—";

Replacement excerpt

- const workflow = flag("workflow", "create_design-v1");
+ const workflow = flag("workflow", "freeform_image-v1");
const prompt = flag("prompt", "a minimal linen overshirt, sand colour, studio light");

Replacement excerpt

- const payload = { workflow, tier, ...(w.takes_prompt ? { prompt } : {}), ...(w.ratios.length ? { ratio } : {}) };
+ // Named image params (--product_images https://… ) and panel fields (--field gender=Woman).
+ for (const img of w.images) {
+ const v = flag(img.param);
+ if (v) payloadImages[img.param] = img.multiple ? argv.slice(argv.indexOf(`--${img.param}`) + 1).filter((x) => !x.startsWith("--") && x !== v).concat(v) : v;
+ }
+ const fields = {};
+ for (const a of argv) {
+ const m = /^--field$/.exec(a);
+ if (m) continue;
+ }
+ argv.forEach((a, i) => {
+ if (a === "--field" && argv[i + 1]) {
+ const [k, ...rest] = argv[i + 1].split("=");
+ fields[k] = rest.join("=");
+ }
+ });
+
+ const payload = {
+ workflow,
+ tier,
+ ...(w.takes_prompt ? { prompt } : {}),
+ ...(w.ratios.includes(ratio) ? { ratio } : {}),
+ ...payloadImages,
+ ...(Object.keys(fields).length ? { fields } : {}),
+ };

Replacement excerpt

- console.log(` fields : ${w.fields.map((f) => f.param || f.name).join(", ") || "none"}`);
+ console.log(` fields : ${w.fields.map((f) => `${f.name}${f.required ? "*" : ""}`).join(", ") || "none"}`);

Replacement excerpt

const ratio = flag("ratio", "4:5");
+ const payloadImages = {};
Thinking…

The image-param parsing I wrote is convoluted and buggy. Let me rewrite that block cleanly: a helper to collect values after a flag until next --.

Simplify:

const valuesOf = (name) => {
  const out = [];
  const i = argv.indexOf(`--${name}`);
  if (i === -1) return out;
  for (let j = i + 1; j < argv.length && !argv[j].startsWith("--"); j++) out.push(argv[j]);
  return out;
};

Then flag(name) = valuesOf(name)[0].

Let me rewrite the file portions cleanly — easier to just rewrite whole file.

File edits

1 file

Completed
Writtenexamples/thenewblack/demo.mjsView changes

/sandbox/repo/examples/thenewblack/demo.mjs

Written content · previous contents were not recorded

#!/usr/bin/env node
/**
* The New Black AI — minimal hosted-API example (zero dependencies, Node >= 18).
*
* Everything is hosted at https://thenewblack.ai/api/v1 — nothing to install or run locally.
* The public, key-free endpoints (/catalog, /openapi.json) let you read the live contract
* and the prices before you spend a credit.
*
* Usage:
* node demo.mjs --list # every workflow with live prices (no key)
* node demo.mjs # dry run: contract + price + request body
* node demo.mjs --workflow virtual_try_on-v1 --product_images https://x/dress.jpg \
* --model_image https://x/model.jpg --field seg_camera=slightly_above
* TNB_API_KEY=tnb_live_... node demo.mjs --run --prompt "a linen overshirt, sand colour"
*
* --run submits for real: credits are debited at submission, refunded on failure.
* Without --run, or without TNB_API_KEY, nothing is submitted — it only prints the request.
*/
const BASE = process.env.TNB_API_URL || "https://thenewblack.ai/api/v1";
const KEY = process.env.TNB_API_KEY || "";
const argv = process.argv.slice(2);
const valuesOf = (name) => {
const i = argv.indexOf(`--${name}`);
if (i === -1) return [];
const out = [];
for (let j = i + 1; j < argv.length && !argv[j].startsWith("--"); j++) out.push(argv[j]);
return out;
};
const flag = (name, dflt) => valuesOf(name)[0] ?? dflt;
const has = (name) => argv.includes(`--${name}`);
async function json(path, init) {
const res = await fetch(BASE + path, {
...init,
headers: {
"Content-Type": "application/json",
...(KEY ? { Authorization: `Bearer ${KEY}` } : {}),
...(init?.headers || {}),
},
});
const body = await res.json().catch(() => ({}));
if (!res.ok) {
const e = body.error || {};
throw new Error(`${res.status} ${e.code || res.statusText}: ${e.message || ""}`.trim());
}
return body;
}
const priceOf = (w, tier) => {
const c = (w.tiers || []).includes(tier) ? w.credits?.[tier] : null;
if (c == null) return "—";
return w.mode === "video" ? `${c} cr/s` : `${c} cr`;
};
async function listCatalog() {
const { workflows } = await json("/catalog"); // public, no key, free
for (const w of workflows) {
console.log(
[w.endpoint.padEnd(34), w.mode.padEnd(6),
`std ${priceOf(w, "standard")}`.padEnd(15),
`pro ${priceOf(w, "pro")}`.padEnd(15),
`ultra ${priceOf(w, "ultra")}`].join(" ")
);
}
console.log(`\n${workflows.length} workflows — prices read live from the catalogue.`);
}
async function main() {
if (has("list")) return listCatalog();
const workflow = flag("workflow", "freeform_image-v1");
const prompt = flag("prompt", "a minimal linen overshirt, sand colour, studio light");
const tier = flag("tier", "standard");
const ratio = flag("ratio", "4:5");
// 1. Read this workflow's live contract (public, costs nothing).
const { workflows } = await json("/catalog");
const w = workflows.find((x) => x.endpoint === workflow);
if (!w) throw new Error(`unknown workflow ${workflow} — run with --list`);
console.log(`${w.endpoint} · ${w.title} (${w.mode})`);
console.log(` price : ${priceOf(w, tier)} (${w.credits?.unit || "per generation"})`);
console.log(` images : ${w.images.map((i) => `${i.param}${i.required ? "*" : ""}`).join(", ") || "none"}`);
console.log(` fields : ${w.fields.map((f) => `${f.name}${f.required ? "*" : ""}`).join(", ") || "none"}`);
console.log(` ratios : ${w.ratios.join(" ") || "none"}`);
console.log(` prompt : ${w.prompt_required ? "required" : w.takes_prompt ? "optional" : "not accepted"}`);
// 2. Build the body: named image params and panel fields, exactly as the catalogue names them.
const payload = { workflow, tier };
if (w.takes_prompt) payload.prompt = prompt;
if (w.ratios.includes(ratio)) payload.ratio = ratio;
if (w.mode === "video" && flag("duration")) payload.duration = flag("duration");
for (const img of w.images) {
const v = valuesOf(img.param);
if (v.length) payload[img.param] = img.multiple ? v : v[0]; // https URLs (or upload via /media/upload)
}
const fields = {};
argv.forEach((a, i) => {
if (a === "--field" && argv[i + 1]) {
const [k, ...rest] = argv[i + 1].split("=");
fields[k] = rest.join("=");
}
});
if (Object.keys(fields).length) payload.fields = fields;
const missing = w.images.filter((i) => i.required && !payload[i.param]).map((i) => i.param)
.concat(w.fields.filter((f) => f.required && !(f.name in fields)).map((f) => f.name));
if (missing.length) console.log(` MISSING : ${missing.join(", ")}`);
// 3. No key, or no --run: stop here and show the exact request.
if (!KEY || !has("run")) {
console.log(`\nDRY RUN${KEY ? "" : " (no TNB_API_KEY)"} — would POST ${BASE}/generate:`);
console.log(JSON.stringify(payload, null, 2));
console.log("\nSet TNB_API_KEY=tnb_live_… and add --run to spend credits for real.");
return;
}
// 4. Balance → submit → poll. Reads are free and not rate limited.
console.log(`\ncredits before: ${(await json("/credits")).credits}`);
const submitted = await json("/generate", { method: "POST", body: JSON.stringify(payload) });
console.log(`submitted: ${submitted.generation_id} (${submitted.status})`);
const poll = (submitted.poll || `/api/v1/generations/${submitted.generation_id}`).replace(/^\/api\/v1/, "");
const started = Date.now();
for (;;) {
await new Promise((r) => setTimeout(r, 5000));
const g = await json(poll);
console.log(` ${((Date.now() - started) / 1000).toFixed(0)}s ${g.status}`);
if (g.status === "succeeded") {
console.log(`result (${g.result.type}): ${g.result.url}`);
console.log("That URL lives 48 h — copy the file to your own storage.");
return;
}
if (g.status === "failed") return console.log("failed — credits refunded automatically.");
if (Date.now() - started > 10 * 60 * 1000) {
return console.log(`still running after 10 min — poll later: GET ${poll}`);
}
}
}
main().catch((e) => {
console.error(e.message);
process.exit(1);
});
Thinking…

Wait — poll uses KEY auth; the poll request needs read scope. Fine.

One bug: poll path replace — json(poll) prepends BASE. OK.

Test again: --list tail, dry run default, dry run virtual_try_on with missing required images.

cd /sandbox/repo/examples/thenewblack && timeout 60 node demo.mjs 2>&1; echo "=== try-on ==="; timeout 60 node demo.mjs --workflow virtual_try_on-v1 --product_images https://x/dress.jpg --field seg_camera=slightly_above 2>&1 | tail -20; echo "=== list tail ==="; timeout 60 node demo.mjs --list 2>&1 | tail -3
freeform_image-v1 · Free Prompt Image (image)
freeform_image-v1 · Free Prompt Image (image)
  price   : 1 cr (per generation)
  images  : reference_images
  fields  : none
  ratios  : auto 9:16 1:1 4:5 3:4 2:3 16:9 4:3 3:2 5:4 21:9
  prompt  : required

DRY RUN (no TNB_API_KEY) — would POST https://thenewblack.ai/api/v1/generate:
{
  "workflow": "freeform_image-v1",
  "tier": "standard",
  "prompt": "a minimal linen overshirt, sand colour, studio light",
  "ratio": "4:5"
}

Set TNB_API_KEY=tnb_live_… and add --run to spend credits for real.
=== try-on ===
  images  : product_images*, model_image*, scene_image
  fields  : seg_framing, seg_camera, seg_look, seg_scene, seg_features
  ratios  : auto 21:9 16:9 3:2 4:3 5:4 1:1 4:5 3:4 2:3 9:16
  prompt  : not accepted
  MISSING : model_image

DRY RUN (no TNB_API_KEY) — would POST https://thenewblack.ai/api/v1/generate:
{
  "workflow": "virtual_try_on-v1",
  "tier": "standard",
  "ratio": "4:5",
  "product_images": [
    "https://x/dress.jpg"
  ],
  "fields": {
    "seg_camera": "slightly_above"
  }
}

Set TNB_API_KEY=tnb_live_… and add --run to spend credits for real.
=== list tail ===
motion_mix_match-v1                video  std 1 cr/s      pro 1 cr/s      ultra —

77 workflows — prices read live from the catalogue.
Thinking…

Works. Update README to match new flags (default workflow freeform_image-v1, --field, --duration). Also add a commit? Repo is a git repo; I'll leave committing optional — maybe commit is nice. I'll just leave files; not asked. Actually keeping it clean: no commit unless asked.

Update README run section.

File edits

1 file

Completed
Modifiedexamples/thenewblack/README.md+11−2View changes

/sandbox/repo/examples/thenewblack/README.md

Replacement excerpt

node demo.mjs --list # every workflow + live prices (no key)
node demo.mjs # dry run of one generation (no key)
-TNB_API_KEY=tnb_live_… node demo.mjs --run \
- --workflow create_design-v1 --prompt "a minimal linen overshirt, sand colour" --tier standard
+node demo.mjs --workflow virtual_try_on-v1 \
+ --product_images https://x/dress.jpg --model_image https://x/model.jpg \
+ --field seg_camera=slightly_above --ratio 4:5 # flags are validated against the catalogue
+
+TNB_API_KEY=tnb_live_… node demo.mjs --run --tier standard \
+ --prompt "a minimal linen overshirt, sand colour, studio light" # spends 1 credit
```
+
+Image parameters take public `https` URLs (or upload a local file first:
+`POST /v1/media/upload`, multipart `file`, → `{ media_id, url }`). Panel fields go in
+`fields` by name — `--field k=v` here. `MISSING:` in the output lists what the workflow
+still needs before it would be accepted.
Thinking…

I need to wrap up by summarizing the pricing structure, how manageable this is to implement, any blockers we're facing—mainly the missing API key that would prevent running an actual generation—and what files need to be created. I should also verify that the quickstart doesn't require any local infrastructure, which it doesn't, so that's clear.

Yes, there's a real developer workflow — a hosted REST API (no local stack, no long-running services), plus an official CLI, MCP connector, and a public OpenAPI spec.

What I built

examples/thenewblack/demo.mjs — zero-dependency Node ≥18 script, plus examples/thenewblack/README.md.

It: reads the live catalogue (GET /api/v1/catalog, public and free) → prints the workflow's contract and price before spending → builds the request body from the catalogue's own param/field names (and flags MISSING: inputs) → with a key and --run, checks credits, submits, polls to succeeded/failed, and prints the result URL.

Verified against the live API just now:

  • node demo.mjs --list → 77 workflows with live std/pro/ultra prices
  • node demo.mjs → dry run for freeform_image-v1 (1 cr), request body printed
  • node demo.mjs --workflow virtual_try_on-v1 … → correctly reports MISSING: model_image
  • bad key → clean 401 invalid_key handling

Blocked on one thing only: no TNB_API_KEY in this environment, so I could not execute a paid generation end-to-end. Keys come from the account's API/MCP tab (up to 3, scopes read/generate/publish/agents). Set it and add --run.

How pricing works

Two layers: credits are the fuel, the plan is the licence.

  • Per generation, per workflow and tier: standard / pro / ultra (1K→2K→4K images, 720p→1080p video). Typical image = 1 / 3 / 7 credits; remove_background 0.5 cr; create_3d_models 10 cr. Video is billed per second of output (e.g. 2.2 / 4.4 / 23 cr/s). Their rule of thumb: 1 credit ≈ 1 image, 10 credits ≈ 1 video.
  • Plans (monthly, yearly = 2 months free): Starter $15 → 200 cr; Pro $35 → 500 cr; Business $65 → 1,000 cr; Enterprise $195 → 3,000 cr. One-off credit packs work on any account but only unlock the Standard studio; Ultra photos need Pro+. Credits roll over while a plan is active, with a hold cap per plan (700 / 2,000 / 4,000 / 12,000).
  • Billing mechanics that matter for code: debited at submission, auto-refunded on failure or 502 generation_refused; 402 insufficient_credits if short; 429 rate_limited + Retry-After charges nothing. Rate = generations/min per plan (30 / 30 / 60 / 120 / 300) shared across API+CLI+MCP; reads are free and uncounted.

Will it be easy for me to manage?

Yes — unusually so. Machine-readable contract published key-free (/api/v1/openapi.json, /api/v1/catalog) and generated at call time, so flags/schemas/prices are read live instead of hardcoded; versioned workflow endpoints (create_design-v1) mean old integrations keep working; stable error codes; async submit + poll or single-shot webhook; official no-dependency CLI with JSON output built for agents.

Two things I'd watch: result URLs expire after 48 hours (must copy to your own storage), and webhooks are fire-once with a 5 s timeout, so the poll endpoint stays the source of truth.

AX Fundamentals

23 checks. Open an area for details.

This check is a quick preview. Test more tasks and models with Gauge Agents.

Test your product with Gauge Agents

AX Check by Gauge