Python · 首饰试穿 API

首饰试穿 API 在 Python 中

一句话总结

安装 requests,从环境变量读取 PHOTTA_API_KEY,编写一个发送 Bearer Key 并在非 2xx 响应时抛出类型化 PhottaError 的 photta() 包装函数,随后 POST 请求至 /api/v1/tryon/jewelry,并每隔 3 秒轮询一次 /api/v1/tryon/jewelry/{id} 直至 status 为 completed。

  • 常规耗时: 1.5–4 min
  • Credits: 2K 分辨率 5 credits · 4K 分辨率 6 credits
  • 处理方式: 异步,轮询
  • 限制: 600 次请求/分钟
  • 身份验证: Bearer key

本页所有数据均来自 Photta API 文档 · 已验证

POST/api/v1/tryon/jewelry
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
输入限制
单张图片最大 10 MB;支持 JPEG, PNG, WebP
幂等性
否

工作原理

仅需五步,零 Photta 专属依赖——requests 即可搞定一切。

  1. 步骤 1

    注册并生成密钥

    与其他语言路径一致:ai.photta.app → Developers → Generate API key。密钥以 `photta_live_` 开头,通用于 Photta 的所有功能特性。

  2. 步骤 2

    从环境变量加载密钥

    在环境中设置 `PHOTTA_API_KEY` 并通过 `os.environ` 读取。在 FastAPI 或 Django 中,系统启动时将其加载到 settings 模块中即可。切勿将密钥硬编码在源码中或提交至公开的 Git 历史。

    python3 -m pip install requests
    export PHOTTA_API_KEY="photta_live_xxxxx"
  3. 步骤 3

    编写 requests 包装函数

    一个三十行的 `photta_request()` 函数即可搞定 base 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. 步骤 4

    提交并轮询

    向 `/api/v1/tryon/jewelry` 发起 POST 请求获取生成任务 ID,随后按 3 秒间隔轮询 `/api/v1/tryon/jewelry/{id}`。在 Celery 或 RQ 中,请将轮询循环拆分到多个任务中,避免耗时数分钟的任务长时间占用 worker。

    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. 步骤 5

    持久化存储结果

    任务完成的 payload 包含 `output_url` 和 `thumbnail_url`。将二进制数据下载并存入你自己的对象存储(S3、GCS、Cloudflare R2)中,避免长期展示依赖 Photta 的 CDN。

错误

400invalid_request_error
The request is malformed or contains invalid parameters.
401authentication_error
The API key is missing, invalid, or expired.
402insufficient_credits_error
Your account does not have enough credits.
404not_found_error
The requested resource does not exist.
409conflict_error
The request conflicts with current state — e.g. your concurrent-batch cap is reached.
429rate_limit_error
Too many requests. Slow down and retry.Retry-After: 30
500api_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 秒
  • 单张图片最大 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 worker、Lambda、脚本
  • 客户端封装仅约三十行代码——直接粘贴至 photta.py 即可使用
  • 需要并行提交时,可通过 httpx 与 asyncio 无缝搭配

不支持的特性

  • 暂无官方 Photta Python 包——目前文档规范的集成模式是基于 requests 的 REST 调用
  • 轮询是获取完成状态的唯一方式;API 不发送 webhook
  • 仅支持 Bearer key;不支持 OAuth 客户端凭证(client-credentials)流程

开发者常见问题

Photta 是否提供官方 Python SDK?

暂未提供。官方推荐的集成路径是 requests 库(同步)或 httpx(异步)——两者只需一层极简封装即可使用,本页提供的封装代码适用于所有 capability。

支持哪些 Python 版本?

Python 3.9 及更高版本。封装代码使用了类型注解、f-strings 以及 `str | None` 语法,这些在 3.10+ 环境下原生支持。在 3.9 环境下请将 `str | None` 替换为 `Optional[str]`。requests 本身官方支持 3.8+,但 3.9+ 是现代 Photta 项目切合实际的最低版本要求。

我应该选择 requests 还是 httpx?

如果是少数顺序调用,选 requests——更简单且几乎存在于所有代码库中。如果需要异步并发(并行提交、批量回填)或 HTTP/2 支持,选 httpx。无论选哪个,封装都非常轻量;将 `requests.request` 替换为 `httpx.Client().request`,其余代码完全通用。

可以在 Django 中调用吗?

可以。将封装代码放在 `services/photta.py` 中,在 view 或 Celery 任务中导入即可。对于耗时较长的任务,切勿在同步请求处理函数中调用 API——应在 view 中提交任务、返回生成任务 ID,然后在后台任务或 Channels consumer 中进行轮询。

如何在 Celery worker 中进行轮询?

在一个任务中提交作业,然后调度后续任务(通过 `apply_async(countdown=3)`)单次轮询;若未完成则重新调度自身,直到作业完成或达到最大重试次数上限。这样可以保持 worker 处于空闲状态,避免因长时运行任务干扰弹性伸缩(autoscaler)。

API 如何返回错误?

非 2xx 响应会返回一个包含 `error` 对象的 JSON body:包括 `type`、`code`、`message`,以及 400 状态码下的 `param` 和 429 状态码下的 `retry_after`。本页的封装代码会抛出一个携带上述全部字段的 `PhottaError`,方便调用方根据状态码直接处理逻辑,无需自行解析 body。

五分钟内上手试用 API

生成 Photta API key,粘贴上方的 cURL 代码片段,咖啡还没煮好,你的第一张模特实穿图就已经生成完毕。

  • 1.5–4 min
  • 2K 分辨率 5 credits · 4K 分辨率 6 credits
  • 异步,轮询
  • 600 次请求/分钟
  • Bearer key