Python · ジュエリー try-on API
ジュエリー try-on API Pythonでの実装
要約
requests をインストールし、環境変数から PHOTTA_API_KEY をロードし、Bearer キーを送信して 2xx 以外のレスポンスで型付きの PhottaError を発生させる photta() ラッパーを作成します。その後 /api/v1/tryon/jewelry に POST し、status が completed になるまで 3秒ごとに /api/v1/tryon/jewelry/{id} をポーリングします。
- 所要時間の目安: 1.5–4 min
- Credits: 2Kで5 credits · 4Kで6 credits
- 処理方式: 非同期、ポーリング
- 制限: 600 リクエスト/分
- 認証: Bearerキー
このページに記載されている数値はすべて以下に基づきます: Photta APIドキュメント · 確認済み
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
- 認証
- Bearer APIキー
- 処理方式
- 非同期 — ステータスエンドポイントをポーリング
- 所要時間の目安
- 1.5–4 min
- Credits
- 2Kで5 credits · 4Kで6 credits
- アスペクト比
- 3:4 · 1:1 · 4:3 · 9:16 · 16:9
- 入力制限
- 1画像あたり最大10 MB、JPEG, PNG, WebP
- 冪等性
- なし
仕組み
5つのステップ、Photta 固有の依存関係はゼロ — requests ですべてカバーできます。
ステップ 1
サインアップしてキーを生成する
他のすべての言語と同じ手順です: ai.photta.app → Developers → Generate API key。キーは `photta_live_` で始まり、すべての Photta 機能で使用できます。
ステップ 2
環境変数からキーをロードする
環境変数に `PHOTTA_API_KEY` を設定し、`os.environ` 経由で読み込みます。FastAPI や Django では、起動時に設定モジュールへ1度だけロードしてください。ソースコードや公開 Git 履歴にキーを埋め込まないでください。
python3 -m pip install requests export PHOTTA_API_KEY="photta_live_xxxxx"ステップ 3
requests ラッパーを作成する
30行の `photta_request()` 関数が、ベースURL、Authorizationヘッダー、JSONシリアライズ、エラー変換を処理します。Python SDKが登場するまでは、この抽象化だけで十分です。
# photta.py — one helper for every endpoint import os, requests BASE = "https://api.photta.app/api/v1" class PhottaError(Exception): def __init__(self, status, error, retry_after=None): super().__init__(error.get("message", "request failed")) self.status, self.type, self.retry_after = status, error.get("type"), retry_after def photta(method, path, **kwargs): res = requests.request(method, BASE + path, headers={"Authorization": f"Bearer {os.environ['PHOTTA_API_KEY']}"}, timeout=30, **kwargs) body = res.json() if not res.ok: raise PhottaError(res.status_code, body.get("error", {}), res.headers.get("Retry-After")) return bodyステップ 4
送信とポーリング
`/api/v1/tryon/jewelry` にPOSTして生成IDを取得し、3秒間隔で `/api/v1/tryon/jewelry/{id}` をポーリングします。CeleryやRQでは、数分かかるジョブでワーカーを占有しないよう、ポーリングループをタスクに分割してください。
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")ステップ 5
結果の永続化
完了時のペイロードには `output_url` と `thumbnail_url` が含まれます。長期的なレンダリングでプロダクトがPhottaのCDNに依存しないよう、バイトデータを自身のオブジェクトストレージ(S3、GCS、Cloudflare R2など)にダウンロードしてください。
エラー
- 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:
photta("POST", "/tryon/jewelry", 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."
})
except PhottaError as e:
if e.status == 402:
print("insufficient_credits_error: top up before retrying")
elif e.status == 429:
time.sleep(int(e.retry_after or 30))
else:
raise制限
- APIキーごとに毎分600リクエスト (固定ウィンドウ方式。制限値はすべてのプランで共通です)
- 429にはRetry-After: 30 secondsが含まれます
- 1画像あたり最大10 MB
- フォーマット: JPEG, PNG, WebP
- プランごとの同時実行バッチ数: Free 1 · Hobby 2 · Seller 3 · Brand 4 · Studio 6
- ポーリングのみ — APIはWebhookを送信しません。
現時点でrequestsが最適な選択肢である理由
- Photta固有の依存関係は不要 — ほとんどのPythonプロジェクトにrequestsはすでに導入されています
- Pythonが動作する環境ならどこでも機能: Django、FastAPI、Flask、Celeryワーカー、Lambda、スクリプト
- クライアントラッパーは約30行 — photta.py に貼り付けるだけですぐに使えます
- 並行送信が必要な場合はhttpx経由でasyncioと連携可能
対応していない機能
- 公式のPhotta Pythonパッケージは未提供 — requestsを使用したRESTがドキュメント記載のパターンです
- 完了シグナルはポーリングのみで、APIからWebhookは送信されません
- Bearerキーのみ対応。OAuthのクライアント認証情報フローはありません
開発者からのよくある質問
公式のPhotta Python SDKはありますか?
現時点ではありません。サポートされている連携方法はrequestsライブラリ(同期)またはhttpx(非同期)です。どちらも薄いラッパーを介して利用でき、本ページのラッパーはすべての機能に対応しています。
サポートされているPythonのバージョンは?
Python 3.9以降です。このラッパーは型ヒント、f-string、`str | None` 構文を使用しており、3.10以降で問題なく動作します。3.9の場合は `str | None` を `Optional[str]` に置き換えてください。requests自体は公式に3.8以降をサポートしていますが、近年のPhottaプロジェクトでは3.9以降が実質的な最小要件です。
requestsとhttpxのどちらを使うべきですか?
少数の呼び出しを順次実行する場合はrequestsが適しています。シンプルであり、ほとんどのコードベースにすでに含まれています。非同期の並行処理(並列送信、一括バックフィルなど)やHTTP/2が必要な場合はhttpxを使用してください。どちらの場合もラッパーは軽量で、`requests.request` を `httpx.Client().request` に置き換えるだけで、残りのコードは同一のまま動作します。
Djangoから呼び出せますか?
はい。ラッパーを `services/photta.py` に配置し、ビューまたはCeleryタスクからインポートしてください。ジョブに時間がかかる場合、同期リクエストハンドラー内でAPIを呼び出すのは避けてください。ビューから送信して生成IDを返し、バックグラウンドタスクまたはChannelsのコンシューマーからポーリングします。
Celeryワーカーからポーリングするにはどうすればよいですか?
1つのタスクからジョブを送信し、`apply_async(countdown=3)` を使用して1回ポーリングする後続タスクをスケジュールします。ジョブが完了するか最大再試行回数に達するまで自身を再スケジュールします。これによりワーカーが解放され、オートスケーラーに悪影響を与える長時間タスクを回避できます。
APIはどのようにエラーを通知しますか?
2xx以外のレスポンスには、`error` オブジェクト(`type`、`code`、`message`、さらに400番台では `param`、429番台では `retry_after`)を含むJSONボディが返されます。本ページのラッパーはこれらすべてを保持する `PhottaError` を送出するため、呼び出し元はボディ自体をパースすることなくステータスコードで分岐できます。
関連ページ
Node.js
Node.jsでのジュエリー try-on API
ネイティブのfetchを使用してNode.jsバックエンドからPhottaのジュエリー try-on APIを呼び出します。SDKは不要です。キーを保存し、ジョブを送信して、結果をポーリングするだけです。
読むcURL
cURLによるジュエリー try-on API
cURLを使用してシェルから直接Phottaのジュエリー try-on APIを呼び出します。送信、ポーリング、ダウンロード — すべてのスニペットはスクリプトパイプライン向けにjqと連携可能です。
読む機能一覧
ジュエリー try-on API ネックレス、リング、ブレスレット、イヤリングに対応
REST 経由でネックレス、指輪、ブレスレット、イヤリングを AI モデルに配置。2K で 5 credits、クローズアップマネキンを内蔵、Photta のドキュメントに基づく反射を考慮したレンダリング。
読む実装
AI商品撮影サービスを構築する
Phottaのバーチャルtry-on APIをホワイトラベルSaaSとしてリセールするためのファウンダー向けプレイブック:テナントキー、バッチファンアウト、credit単位の請求、SLAの現実。
読むクイックスタート
5 分以内に最初の Photta 画像を生成。
サインアップ、API キーの生成、最初の cURL 呼び出しの実行、完了までのポーリング、結果の保存。エンドツーエンドで文書化された 5 つのステップ。
読むリファレンス
Photta API の料金体系
Photta APIの各endpointにおける2Kおよび4Kでのcredits消費量、請求と返金の仕組み、無料のendpoint一覧。画像単位の金銭的価格設定はありません。
読む
このページに記載されている数値はすべて以下に基づきます: Photta APIドキュメント · 確認済み
5分でAPIを試す
Photta APIキーを生成し、上記のcURLスニペットを貼り付ければ、コーヒーが淹れ終わる前に最初のモデル着用画像が手に入ります。
- 1.5–4 min
- 2Kで5 credits · 4Kで6 credits
- 非同期、ポーリング
- 600 リクエスト/分
- Bearerキー