Produktfotostudiet som API.
Herofabs API modtager et produktfoto og et værktøjsnavn og behandler jobbet i baggrunden; statusforespørgsler eller en signeret webhook melder, når det færdige billede er klar til download.
- Bearer-API-nøgler
- Signerede webhooks
- Op til 100 job pr. batch
- OpenAPI 3.1 og llms.txt
curl https://app.herofab.app/api/v1/jobs -H "Authorization: Bearer $HEROFAB_API_KEY" -H "Idempotency-Key: $(uuidgen)" --json '{"tool": "ghost_mannequin", "inputs": {"garment": "ASSET_ID"}}'
const job = await fetch("https://app.herofab.app/api/v1/jobs", { method: "POST", headers: { Authorization: `Bearer ${process.env.HEROFAB_API_KEY}`, "Idempotency-Key": crypto.randomUUID(), "Content-Type": "application/json" }, body: JSON.stringify({ tool: "ghost_mannequin", inputs: { garment: assetId } }) }).then((r) => r.json());
job = requests.post("https://app.herofab.app/api/v1/jobs", headers={"Authorization": f"Bearer {os.environ['HEROFAB_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())}, json={"tool": "ghost_mannequin", "inputs": {"garment": asset_id}}).json()
Sådan virker det
Fra foto til færdigt billede.
01
Send
Upload produktfotoet, og opret et job med et værktøj og dets indstillinger; jobbet reserverer sine kreditter.
POST /api/v1/assetsPOST /api/v1/jobs
02
Forespørg
Hent jobbet, indtil det er færdigt, eller modtag en signeret webhook, når det er.
GET /api/v1/jobs/{id}
03
Download
Hent det færdige billede med asset-id’et fra jobbets output.
GET /api/v1/assets/{id}/content
Fuldt eksempel: upload fotoet, opret jobbet, vent, download
API=https://app.herofab.app/api/v1
AUTH="Authorization: Bearer $HEROFAB_API_KEY"
# 1 · Upload the product photo
ASSET_ID=$(curl -s "$API/assets" \
-H "$AUTH" \
-F [email protected] | jq -r .id)
# 2 · Create the job
BODY=$(jq -n --arg garment "$ASSET_ID" '{tool: "ghost_mannequin",
inputs: {garment: $garment}, params: {style: "3d", backdrop: "white"}}')
JOB_ID=$(curl -s "$API/jobs" \
-H "$AUTH" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d "$BODY" | jq -r .id)
# 3 · Poll until the job is finished
while :; do
JOB=$(curl -s "$API/jobs/$JOB_ID" -H "$AUTH")
STATE=$(jq -r .state <<<"$JOB")
[ "$STATE" = queued ] || [ "$STATE" = running ] || break
sleep 2
done
[ "$STATE" = succeeded ] || { jq -r .failure.code <<<"$JOB"; exit 1; }
# 4 · Download the image
OUTPUT_ID=$(jq -r '.outputs[0].asset_id' <<<"$JOB")
EXT=$(jq -r '.outputs[0].content_type | ltrimstr("image/")' <<<"$JOB")
curl -sL "$API/assets/$OUTPUT_ID/content" -H "$AUTH" -o "result.$EXT"
import { randomUUID } from "node:crypto";
import { readFile, writeFile } from "node:fs/promises";
const api = "https://app.herofab.app/api/v1";
const auth = { Authorization: `Bearer ${process.env.HEROFAB_API_KEY}` };
// 1 · Upload the product photo
const form = new FormData();
form.append("file", new Blob([await readFile("shirt.jpg")]), "shirt.jpg");
const upload = await fetch(`${api}/assets`, { method: "POST", headers: auth, body: form });
const asset = await upload.json();
// 2 · Create the job
let job = await (await fetch(`${api}/jobs`, {
method: "POST",
headers: { ...auth, "Content-Type": "application/json", "Idempotency-Key": randomUUID() },
body: JSON.stringify({ tool: "ghost_mannequin", inputs: { garment: asset.id },
params: { style: "3d", backdrop: "white" } }),
})).json();
// 3 · Poll until the job is finished
while (job.state === "queued" || job.state === "running") {
await new Promise((resolve) => setTimeout(resolve, 2000));
job = await (await fetch(`${api}/jobs/${job.id}`, { headers: auth })).json();
}
if (job.state !== "succeeded") throw new Error(job.failure.code);
// 4 · Download the image
const [output] = job.outputs;
const image = await fetch(`${api}/assets/${output.asset_id}/content`, { headers: auth });
const ext = output.content_type.split("/")[1];
await writeFile(`result.${ext}`, Buffer.from(await image.arrayBuffer()));
import os, time, uuid
import requests
API = "https://app.herofab.app/api/v1"
AUTH = {"Authorization": f"Bearer {os.environ['HEROFAB_API_KEY']}"}
# 1 · Upload the product photo
with open("shirt.jpg", "rb") as photo:
asset = requests.post(f"{API}/assets", headers=AUTH, files={"file": photo}).json()
# 2 · Create the job
job = requests.post(f"{API}/jobs", json={
"tool": "ghost_mannequin",
"inputs": {"garment": asset["id"]},
"params": {"style": "3d", "backdrop": "white"},
}, headers={**AUTH, "Idempotency-Key": str(uuid.uuid4())}).json()
# 3 · Poll until the job is finished
while job["state"] in ("queued", "running"):
time.sleep(2)
job = requests.get(f"{API}/jobs/{job['id']}", headers=AUTH).json()
if job["state"] != "succeeded":
raise SystemExit(job["failure"]["code"])
# 4 · Download the image
output = job["outputs"][0]
image = requests.get(f"{API}/assets/{output['asset_id']}/content", headers=AUTH)
with open("result." + output["content_type"].split("/")[1], "wb") as file:
file.write(image.content)
Tidlig adgang
Din næste kollektion, fotograferet i denne uge.
20 gratis kreditter, når den tidlige adgang åbner. Intet betalingskort påkrævet.