Node.js · API примерки ювелирных изделий
API примерки ювелирных изделий на Node.js
В двух словах
Задайте PHOTTA_API_KEY в env, напишите небольшую вспомогательную функцию с fetch для https://api.photta.app/api/v1 с ключом Bearer, отправьте POST к /api/v1/tryon/jewelry, затем выполняйте polling /api/v1/tryon/jewelry/{id} каждые 3 секунды, пока статус не станет completed.
- Типичное время: 1.5–4 min
- Кредиты: 5 credits при 2K · 6 credits при 4K
- Обработка: async, polling
- Лимиты: 600 запросов/мин
- Аутентификация: Ключ Bearer
Все показатели на этой странице взяты из документации API Photta · проверено
RESPONSE=$(curl -s -X POST https://api.photta.app/api/v1/tryon/jewelry \
-H "Authorization: Bearer $PHOTTA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}')
ID=$(echo "$RESPONSE" | jq -r '.data.id')
# $ID is data.id from the POST response. Poll every 3 seconds until status is "completed" or "failed".
for i in $(seq 1 120); do
RESULT=$(curl -s "https://api.photta.app/api/v1/tryon/jewelry/$ID" -H "Authorization: Bearer $PHOTTA_API_KEY")
STATUS=$(echo "$RESULT" | jq -r '.data.status')
[ "$STATUS" = "completed" ] && break
[ "$STATUS" = "failed" ] && echo "generation failed" && exit 1
sleep 3
done
echo "$RESULT" | jq -r '.data.output_url'const res = await fetch("https://api.photta.app/api/v1/tryon/jewelry", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}),
});
const { data } = await res.json(); // data.id, data.status
async function waitFor(id) {
for (let attempt = 0; attempt < 120; attempt++) {
const res = await fetch(`https://api.photta.app/api/v1/tryon/jewelry/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } });
const { data } = await res.json();
if (data.status === "completed") return data.output_url;
if (data.status === "failed") throw new Error(data.error_message ?? "generation failed");
await new Promise((r) => setTimeout(r, 3000));
}
throw new Error("timed out after 6 minutes");
}import os, requests
res = requests.post(
"https://api.photta.app/api/v1/tryon/jewelry",
headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"},
json={
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
},
)
data = res.json()["data"] # data["id"], data["status"]
import time
def wait_for(job_id):
for _ in range(120):
res = requests.get(f"https://api.photta.app/api/v1/tryon/jewelry/{job_id}", headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"})
data = res.json()["data"]
if data["status"] == "completed":
return data["output_url"]
if data["status"] == "failed":
raise RuntimeError(data.get("error_message", "generation failed"))
time.sleep(3)
raise TimeoutError("timed out after 6 minutes")Коротко о главном
Коротко о главном
- Эндпоинт
- POST /api/v1/tryon/jewelry
- Аутентификация
- API-ключ Bearer
- Обработка
- Асинхронно — опрашивайте эндпоинт статуса
- Типичное время
- 1.5–4 min
- Кредиты
- 5 credits при 2K · 6 credits при 4K
- Соотношения сторон
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- Ограничения на входные данные
- До 10 МБ на изображение; JPEG, PNG, WebP
- Идемпотентность
- Нет
Как это работает
Пять шагов, около пяти минут от регистрации до первого изображения.
Шаг 1
Зарегистрируйтесь и сгенерируйте ключ
Создайте аккаунт на ai.photta.app. Откройте раздел Developers в дашборде, нажмите Generate API key и скопируйте live-ключ. Он начинается с `photta_live_`, за которым следуют 32 шестнадцатеричных символа.
Шаг 2
Храните ключ в переменных окружения, а не в исходном коде
Добавьте `PHOTTA_API_KEY=...` в `.env` (или в хранилище секретов вашей платформы) и загружайте его через `process.env`. Никогда не коммитьте ключ в репозиторий и не импортируйте его в файлы с директивой `'use client'` — сборщик включит его в бандл для браузера.
node --version # 18 or later ships fetch echo "PHOTTA_API_KEY=photta_live_xxxxx" >> .envШаг 3
Напишите небольшой хелпер для fetch
Одна обертка над `fetch()` на 20 строк берет на себя базовый URL, заголовок Authorization, тело JSON и нормализацию ошибок. Это единственная абстракция, которая вам понадобится до выхода официального SDK.
// photta.js — one helper for every endpoint const BASE = "https://api.photta.app/api/v1"; export async function photta(path, init = {}) { const res = await fetch(BASE + path, { ...init, headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json", ...(init.headers ?? {}) } }); const body = await res.json(); if (!res.ok) throw Object.assign(new Error(body.error?.message ?? res.statusText), { status: res.status, retryAfter: res.headers.get("Retry-After"), body }); return body; }Шаг 4
Запустите try-on и опрашивайте статус
Отправьте POST на `/api/v1/tryon/jewelry` с телом из документации — код ниже содержит каждое поле. API сразу возвращает ID генерации. Опрашивайте `/api/v1/tryon/jewelry/{id}` каждые 3 секунды, пока `status === 'completed'`.
const res = await fetch("https://api.photta.app/api/v1/tryon/jewelry", { method: "POST", headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ "jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg", "jewelry_type": "necklace", "mannequin_id": "mnk_j9k1l2", "background": "soft window light on dark velvet", "resolution": "2K", "aspect_ratio": "3:4", "user_instruction": "Make the pendant 10% smaller." }), }); const { data } = await res.json(); // data.id, data.status async function waitFor(id) { for (let attempt = 0; attempt < 120; attempt++) { const res = await fetch(`https://api.photta.app/api/v1/tryon/jewelry/${id}`, { headers: { Authorization: `Bearer ${process.env.PHOTTA_API_KEY}` } }); const { data } = await res.json(); if (data.status === "completed") return data.output_url; if (data.status === "failed") throw new Error(data.error_message ?? "generation failed"); await new Promise((r) => setTimeout(r, 3000)); } throw new Error("timed out after 6 minutes"); }Шаг 5
Сохраните результат
Готовый payload содержит `output_url` и `thumbnail_url`. Скачайте байты один раз и сохраните их в своем объектном хранилище: URL-адреса стабильны, но ваш продукт не должен зависеть от CDN Photta при отображении.
Ошибки
- 400
invalid_request_error - The request is malformed or contains invalid parameters.
- 401
authentication_error - The API key is missing, invalid, or expired.
- 402
insufficient_credits_error - Your account does not have enough credits.
- 404
not_found_error - The requested resource does not exist.
- 409
conflict_error - The request conflicts with current state — e.g. your concurrent-batch cap is reached.
- 429
rate_limit_error - Too many requests. Slow down and retry.Retry-After: 30
- 500
api_error - An internal server error occurred. Retry later.
try {
await photta("/tryon/jewelry", { method: "POST", body: JSON.stringify({
"jewelry_image": "https://cdn.yourstore.com/products/gold-necklace.jpg",
"jewelry_type": "necklace",
"mannequin_id": "mnk_j9k1l2",
"background": "soft window light on dark velvet",
"resolution": "2K",
"aspect_ratio": "3:4",
"user_instruction": "Make the pendant 10% smaller."
}) });
} catch (err) {
if (err.status === 402) console.error("insufficient_credits_error: top up before retrying");
else if (err.status === 429) await new Promise((r) => setTimeout(r, Number(err.retryAfter ?? 30) * 1000));
else throw err;
}Лимиты
- 600 запросов в минуту на один API-ключ (Фиксированное окно; лимит одинаков для всех планов)
- Ответ 429 содержит заголовок Retry-After: 30 секунд
- До 10 МБ на изображение
- Форматы: JPEG, PNG, WebP
- Параллельных пакетов на план: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- Только polling — API не отправляет вебхуки.
Почему хелпер лучше клиентской библиотеки — на данный момент
- В Node 18+ есть нативный fetch — никаких зависимостей во время выполнения
- Один и тот же хелпер работает в route handlers Next.js, server actions и любых воркерах
- Храните API-ключ в переменных окружения; никогда не импортируйте хелпер из модуля 'use client', иначе бандлер раскроет его
- Работает с любой очередью или cron: BullMQ, Inngest, Trigger.dev, Vercel Cron, Cloudflare Queues
Чего он не делает
- Официального пакета @photta/node пока нет — на сегодня доступен только REST
- Polling — единственный способ узнать о завершении; API не отправляет вебхуки
- Только Bearer-ключ; поток OAuth client-credentials не поддерживается
Частые вопросы разработчиков
Существует ли официальный Node.js SDK для Photta?
Пока нет. Документированный способ — чистый REST через нативный fetch в Node: хелпер на этой странице закрывает всю интеграцию и работает одинаково для каждой capability.
Какие версии Node.js поддерживаются?
Любые с поддержкой нативного `fetch` — то есть Node 18 и выше. В Node 16 нужно либо добавить полифил `node-fetch`, либо обновиться. Остальной код написан на чистом ECMAScript 2020 (async/await, шаблонные строки, динамические импорты), поэтому других системных требований нет.
Как настроить аутентификацию в Node?
Передавайте `Authorization: Bearer photta_live_xxx` в каждом запросе. Поместите ключ в переменную окружения и считывайте его через `process.env`; никогда не импортируйте его из файла, который выполняется в браузере.
Как обрабатывать время генерации?
Эндпоинт генерации полностью асинхронный. POST сразу возвращает ID генерации со значением `status: 'processing'`. Опрашивайте `GET /api/v1/tryon/jewelry/{id}` каждые 3–5 секунд, пока `status` не сменится на `completed` или `failed`, и ограничьте число попыток, чтобы зависшая задача не блокировала запрос.
Можно ли вызывать API внутри Next.js?
Да — из route handler (`app/**/route.ts`), server action (`'use server'`) или middleware. Храните API-ключ на сервере; никогда не импортируйте хелпер из файла с `'use client'`. Для длительных задач, превышающих таймаут функций Vercel, перенесите polling в очередь (Inngest, Trigger.dev, BullMQ) и верните ID генерации браузеру, чтобы он опрашивал ваш собственный эндпоинт статуса.
Как API сообщает об ошибках?
Ответы с кодом, отличным от 2xx, возвращают тело JSON с объектом `error`: `type`, `code`, `message` и ID запроса для поддержки. Типичные случаи: 400 invalid_request_error с полем `param`, указывающим на некорректное поле; 402 insufficient_credits с количеством `required` и `available`; 429 rate_limit_exceeded с `retry_after` в секундах и соответствующим заголовком Retry-After. Запросы с ошибками 5xx можно безопасно повторять с экспоненциальной задержкой.
Связанные страницы
Python
API примерки ювелирных изделий на Python
Вызывайте Photta aPI примерки ювелирных изделий на Python с помощью библиотеки requests. Обертка на тридцать строк, поддержка асинхронности через httpx, работает в Django, FastAPI и Celery.
ЧитатьcURL
API примерки ювелирных изделий с помощью cURL
Вызывайте aPI примерки ювелирных изделий от Photta напрямую из терминала с помощью cURL. Отправка, поллинг, загрузка — каждый фрагмент готов к использованию с jq для построения скриптовых пайплайнов.
ЧитатьВозможности
API примерки ювелирных изделий для колье, колец, браслетов и серег
Примерка ожерелий, колец, браслетов и серёг на AI-моделях через REST. 5 credits в 2K, встроенные манекены крупным планом, рендеринг с учётом отражений из документации Photta.
ЧитатьРазработка
Создайте сервис AI-фотографии товаров
Руководство для основателей по перепродаже API виртуального try-on от Photta как white-label SaaS: ключи для тенантов, пакетный fanout, биллинг за credits, реальность SLA.
ЧитатьБыстрый старт
Первое изображение в Photta менее чем за 5 минут.
Зарегистрируйтесь, сгенерируйте API-ключ, выполните первый вызов cURL, опрашивайте статус до завершения, сохраните результат. 5 шагов с полным описанием.
ЧитатьСправочник
Тарифы Photta API
Сколько стоит каждый endpoint Photta API в credits при 2K и 4K, как устроены списания и возвраты, и какие эндпоинты бесплатны. Никаких цен в деньгах за изображение.
Читать
Все показатели на этой странице взяты из документации API Photta · проверено
Протестируйте API за пять минут
Сгенерируйте API-ключ Photta, вставьте пример cURL выше, и вы получите первое изображение на модели быстрее, чем сварится кофе.
- 1.5–4 min
- 5 credits при 2K · 6 credits при 4K
- async, polling
- 600 запросов/мин
- Ключ Bearer