Generating Product Images
The POST /product-image-generator/v1 endpoint generates product imagery for a specific style (brand + number + color + size) and returns signed URLs for rendered files.
It supports:
- Generating one or many views in a single request
- Applying one or many logos with placement, sizing, layering, and technique metadata
- Returning a replayable normalized
requestpayload in the response
Endpoint
POST https://seddi-public-api-gateway-91po835h.uc.gateway.dev/product-image-generator/v1
Content-Type: application/json
Request body
{
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"tearAwayLabel": true,
"logos": [
{
"id": "front-logo",
"name": "Primary Logo",
"sourceUrl": "https://example.com/logo.png?X-Goog-Signature=...",
"region": "Chest",
"fill": true,
"size": { "x": 0.09 },
"layer": 1200,
"placement": {
"align": { "x": "left", "y": "center" }
},
"technique": { "name": "Plastisol" }
}
],
"requestedImages": [
{
"format": "image/png",
"resolution": { "x": 1024, "y": 1024 },
"view": "FRONT"
},
{
"format": "image/webp",
"resolution": { "x": 1024, "y": 1024 },
"view": "BACK"
}
]
}
Required fields
Required top-level fields:
brandnumbersizecolorrequestedImageslogos
Optional top-level fields:
tearAwayLabel(defaults totrue)profile(decorator profile slug fromGET /data/v1/profiles. Omit to use the style's own regions.)
requestedImages rules
requestedImages is required for this endpoint.
- Must contain at least 1 item and at most 4 items
- There are four camera views. You may request the same view more than once (different format or resolution) up to 4 outputs total. The response includes one
images[]entry per requested item. - Each item requires:
formatresolution(x,y, both > 0)view
formataccepts only:"image/png""image/jpeg""image/jpg""image/webp"
viewaccepts only:"FRONT""BACK""LEFT""RIGHT"
logos rules
- Required, minimum 1 graphic and maximum 16 graphics
- Each graphic
sourceUrlfile must be 15MB or smaller - Each logo requires:
sourceUrl(must behttps; source file max 15MB)
fillis optional and defaults tofalse. A non-boolean value is rejected. Replay echoesfalsewhen the field was omitted.fill: truescales the graphic to fit inside the region and keeps its aspect ratio.sizeandplacement.atare ignored.placement.aligncan still shift leftover space.- Omit
fill, or sendfalse, to place the graphic withsizeandplacement.
size.xandsize.yare width and height in meters in the garment piece plane. Provide one or both. When only one axis is set, the other is inferred from the image aspect ratio. The example0.09is about 3.5 inches wide. Omitsizeentirely and the graphic uses its own dimensions, then scales down to stay inside the region.placement.at.xandplacement.at.yare offsets in meters from the point of measure. Largeryis toward the top of the piece.placement.at.measure.fromis a point-of-measure name fromGET /data/v1/points-of-measure. Matching is case-insensitive onname, thenidif you already have one. When several points share a name, the one on the same piece as the logo's region is used. If more than one remains, the closest to that region is used. An unknown name returns400with the style's point-of-measure names.regionis required unlessplacement.atis provided. Send the region name fromGET /data/v1/regions. An id is accepted when you already have one.placement.atandplacement.alignare mutually exclusiveplacement.alignis relative to the region.xisleft,center, orright.yistop,center, orbottom.placement.at.measure.toaccepts only:"Top Left""Top Center""Top Right""Left""Center""Right""Bottom Left""Bottom Center""Bottom Right"
layerdefaults to1000when omitted; higher layers render on toptransform.rotationis optional. It is the orientation in the finished scene, in degrees (clockwise). Omit it or send0so the logo top points toward the top of the scene;180flips it. Placement cancels the host piece's arrangement rotation so that scene angle is what you see. The same value is stored on Customizer recipes.colorMapis optional. It is an array of up to 16{ "from": "#rrggbb", "to": "#rrggbb" }pairs. Eachfrommust be unique. The array length is the palette used to recolor the graphic. OmitcolorMap, or send[], to keep the original colors.- Supported source formats:
- Raster:
png,jpg,jpeg,webp,psd,tif,tiff - Vector:
svg,ai,eps,pdf
- Raster:
techniqueis optional. When provided,technique.nameaccepts only:"Plastisol""Waterbased""Glitter""HighDensity""Puff""HeatTransfer""DirectToGarment""Embroidery""Patch""Custom"
- When
technique.nameis"Custom",technique.valueis required and must be a non-empty string - When
techniqueis omitted, the default is"Plastisol"(replay reflects"Plastisol") Rubberis accepted as an alias forPlastisoland is replayed as"Plastisol"
Region aliases
region may be a style region name from GET /data/v1/regions, an id you already have, or one of the ordinal aliases:
| Alias | Resolves to |
|---|---|
FIRST | Highest-priority available decoration region |
SECOND | Second-highest-priority available region |
THIRD | Third-highest-priority available region |
Aliases are case-insensitive. Exact name/id matches always win over aliases.
Regions are ordered with this Decorator priority (highest first). Only regions that exist on the style are used:
- Chest
- WL Chest
- Chest Pocket
- Front
- Back
- WR Sleeve
- WL Sleeve
- Nape
- WL Hip
- WR Hip
- WL Hem
- WR Hem
- Back Neck Label
Any other region names on the style sort after this list, alphabetically by name.
If the ordinal slot is already used by another logo in the same request, the next unused region is chosen. If the style has fewer regions than the ordinal, the last region is used. Unknown names return 400 with the list of available regions.
{
"sourceUrl": "https://example.com/logo.png",
"region": "FIRST",
"fill": true
}
Use an exact name from Style Data when you need a specific placement (for example "Chest" or "Back").
Place from a point of measure by sending placement.at and omitting fill (or sending false). x and y are meters from that point:
{
"sourceUrl": "https://example.com/logo.png",
"fill": false,
"size": { "x": 0.09 },
"placement": {
"at": {
"x": 0,
"y": -0.05,
"measure": { "from": "Center Front Neck", "to": "Top Center" }
}
}
}
cURL example
curl -X POST "https://seddi-public-api-gateway-91po835h.uc.gateway.dev/product-image-generator/v1" \
-H "x-api-key: $SEDDI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"logos": [
{
"sourceUrl": "https://example.com/logo.png",
"region": "FIRST",
"fill": true
}
],
"requestedImages": [
{
"format": "image/png",
"resolution": { "x": 1024, "y": 1024 },
"view": "FRONT"
}
]
}'
Python example
import os
import requests
payload = {
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"logos": [
{
"sourceUrl": "https://example.com/logo.png",
"region": "Chest",
"fill": True,
}
],
"requestedImages": [
{"format": "image/png", "resolution": {"x": 1024, "y": 1024}, "view": "FRONT"},
{"format": "image/webp", "resolution": {"x": 1024, "y": 1024}, "view": "BACK"},
],
}
response = requests.post(
"https://seddi-public-api-gateway-91po835h.uc.gateway.dev/product-image-generator/v1",
json=payload,
headers={"x-api-key": os.environ["SEDDI_API_KEY"]},
)
response.raise_for_status()
print(response.json())
Response shape
{
"styleId": "uuid",
"logos": [
{
"id": "front-logo",
"sourceUrl": "https://example.com/logo.png?X-Goog-Signature=...",
"originalFilePath": "logos-for-generators/<cacheKey>/original.png",
"processedFilePath": "logos-for-generators/<cacheKey>/processed.png",
"originalSignedUrl": "https://...",
"processedSignedUrl": "https://..."
}
],
"images": [
{
"view": "FRONT",
"format": "image/png",
"resolution": { "x": 1024, "y": 1024 },
"filePath": "product-image-generator/<styleId>/<file>.png",
"signedUrl": "https://..."
}
],
"request": {
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"tearAwayLabel": true,
"requestedImages": [
{
"format": "image/png",
"resolution": { "x": 1024, "y": 1024 },
"view": "FRONT"
}
]
}
}
Key response notes:
images[].signedUrland the logo signed URLs last 30 minuteslogosincludes original and processed file references for every submitted logo. Those files live underlogos-for-generators/<cacheKey>/requestis replayable and normalized (defaults and resolved values are expanded)
Behavior notes
- Style selection uses first match by
brand + number + color + size tearAwayLabel=falseremoves scene logos marked as tear-away labels- Brand logos are removed if org-brand approval cannot be verified (fail closed)
- Higher
layervalues render on top of lower values - For vector uploads, conversion to PNG is handled automatically before render
Rendering time depends on image count, resolution, and logo processing complexity. Build asynchronous UX or loading states into your integration.