fix: handle Printful v2 API list response format

v2 returns {data: [...]} (array) not {data: {...}} (object).
Also fixes mockup task polling to use ?id= query param and
extracts mockup_url from nested catalog_variant_mockups structure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-02-24 17:08:53 -08:00
parent be893db11e
commit 9c9c070fbd
2 changed files with 16 additions and 12 deletions

View File

@ -166,16 +166,13 @@ async def _get_printful_mockup(slug: str, product) -> bytes | None:
if not mockups:
return None
# v2 response: catalog_variant_mockups → each has mockup_url or
# placements[].mockup_url. Also check legacy "url" field.
# v2 response: catalog_variant_mockups[] → .mockups[] → .mockup_url
mockup_url = None
for m in mockups:
mockup_url = m.get("mockup_url") or m.get("url")
if not mockup_url and "placements" in m:
for p in m["placements"]:
mockup_url = p.get("mockup_url") or p.get("url")
if mockup_url:
break
for variant_mockup in mockups:
for mockup in variant_mockup.get("mockups", []):
mockup_url = mockup.get("mockup_url") or mockup.get("url")
if mockup_url:
break
if mockup_url:
break

View File

@ -138,7 +138,9 @@ class PrintfulClient:
json=payload,
)
resp.raise_for_status()
data = resp.json().get("data", {})
# v2 returns {"data": [{ ... }]} — data is a list
raw_data = resp.json().get("data", [])
data = raw_data[0] if isinstance(raw_data, list) and raw_data else raw_data
task_id = data.get("id") or data.get("task_key") or data.get("task_id")
logger.info(f"Printful mockup task created: {task_id}")
return str(task_id)
@ -151,11 +153,16 @@ class PrintfulClient:
"""
async with httpx.AsyncClient(timeout=15.0) as client:
resp = await client.get(
f"{BASE_URL}/mockup-tasks/{task_id}",
f"{BASE_URL}/mockup-tasks",
headers=self._headers,
params={"id": task_id},
)
resp.raise_for_status()
return resp.json().get("data", {})
# v2 returns {"data": [{ ... }]} — data is a list
raw_data = resp.json().get("data", [])
if isinstance(raw_data, list) and raw_data:
return raw_data[0]
return raw_data if isinstance(raw_data, dict) else {}
async def generate_mockup_and_wait(
self,