Generating Techpacks
The POST /techpack-generator/v1 endpoint generates a multi-page techpack PDF for a specific style (brand + number + color + size) and returns a signed URL to the rendered file.
It supports:
- 3D catalog styles, with automatic placement canonicalization for logos
- One or many logos with placement, sizing, layering, technique, notes, underbase, and color-palette metadata
- Optional org-/user-driven branding for the PDF (header logo, footer disclaimer, units)
- Optional extra product view images (
requestedImages) returned alongside the PDF, using the same contract as product-image-generator - A replayable normalized
requestpayload in the response
Endpoint
POST https://seddi-public-api-gateway-91po835h.uc.gateway.dev/techpack-generator/v1
Content-Type: application/json
Request body
{
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"tearAwayLabel": true,
"useBrandLogos": true,
"logos": [
{
"id": "front-logo",
"name": "Primary Logo",
"sourceUrl": "https://example.com/logo.png?X-Goog-Signature=...",
"region": "Chest",
"fill": false,
"size": { "x": 0.25, "y": 0.12 },
"layer": 1200,
"placement": {
"align": { "x": "center", "y": "top" }
},
"technique": { "name": "Plastisol" },
"note": "Use approved colorway",
"underbase": "white",
"colorPalette": [
{ "color": "#000000", "name": "Black" }
]
}
],
"pdf": {
"units": "METRIC",
"name": "Gildan 64000",
"showProduct": true
}
}
Required fields
Required top-level fields:
brandnumbersizecolorlogos
Optional top-level fields:
tearAwayLabel(defaults totrue)useBrandLogos(subject to org-brand approval; falls back tofalsewhen approval cannot be verified)profile(decorator profile slug fromGET /data/v1/profiles. Omit to use the style's own regions.)requestedImages(optional extra product views to return with the PDF; omit for PDF-only)pdf(see below)
requestedImages rules
requestedImages is optional for this endpoint. It uses the same shape as product-image-generator. Omit the field entirely for PDF-only generation (the default). When provided, the response includes an images[] array in addition to the techpack PDF.
- 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"
Example — techpack plus a front PNG and back WebP:
{
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"logos": [ "...same as above..." ],
"requestedImages": [
{ "format": "image/png", "resolution": { "x": 1024, "y": 1024 }, "view": "FRONT" },
{ "format": "image/webp", "resolution": { "x": 1024, "y": 1024 }, "view": "BACK" }
]
}
Extra view rendering is blocking: if requestedImages is supplied and rendering fails, the whole request fails. Overview and extra views share one viewport-images batch for the same garment, so the scene is loaded once per request. When an extra view matches an overview slot exactly (same angle, format, and resolution), it is not rendered twice — the service reuses the overview file and copies it to the extra output path.
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. 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. Replay echoes that degree value.regionTransform.rotationremains the style-frame angle in radians. Previously this rotation field was accepted and not applied to placement; clients that stored a radian number should convert it to degrees.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.colorMapdoes not replacecolorPaletteswatches when those are sent.- 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"noteis free text rendered in the decoration page "Notes" sectionunderbaseaccepts only"none"(default),"white", or"grey"colorPalette[]is optional. Each entry is{ "color": "#RRGGBB", "name"?: string }. If omitted, a palette is auto-extracted from the uploaded logo asset (vector files are parsed structurally, raster files are quantized). These are the swatches printed in the PDF. They are separate fromcolorMap, which recolors the graphic.
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,
"technique": { "name": "Plastisol" }
}
Use an exact name from Style Data when you need a specific placement (for example "Chest" or "Back").
pdf options
All inputs that only affect the PDF render live under a single optional pdf object:
| Field | Description |
|---|---|
units | "METRIC" or "IMPERIAL". Controls measurements shown in the PDF. |
name | Bold title in the PDF header. Defaults to ${brand} ${number}. |
product | Product description below the title. Defaults to an auto-derived style summary. |
logo | URL of a header logo image. |
disclaimer | Footer disclaimer text. |
showProduct | When false, the product description line is omitted. Defaults to true. |
pdf fallback order
When fields are omitted, the service falls back through user/org settings before the static defaults. The first non-empty source wins:
| Field | 1. Request | 2. User / org fallback | 3. Service default |
|---|---|---|---|
pdf.units | request.pdf.units | user preference units | "METRIC" |
pdf.logo | request.pdf.logo | org settings preview | placeholder header logo |
pdf.disclaimer | request.pdf.disclaimer | org settings disclaimer (best-effort) | static disclaimer text |
pdf.name, pdf.product, pdf.showProduct | request.pdf.* | (no fallback) | ${brand} ${number} / auto-derived summary / true |
The org/user fetches are non-blocking: any failure logs a warning and the service falls through to the next layer. The request block in the response always echoes the effective pdf so a response can be replayed verbatim.
Placement canonicalization
Every logo is resolved to a canonical placement.at representation regardless of how the request expressed placement (fill, align, at, or omitted). The response's replayable request always echoes this canonical form ({ x, y, measure: { from: <POM name>, to: <graphic anchor> } }), so the exact same PDF can be reproduced without depending on auto-resolution rules later.
cURL example
curl -X POST "https://seddi-public-api-gateway-91po835h.uc.gateway.dev/techpack-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": "Chest",
"fill": true,
"technique": { "name": "Plastisol" }
}
]
}'
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,
"technique": {"name": "Plastisol"},
"note": "Use approved colorway",
"underbase": "white",
}
],
"pdf": {
"units": "METRIC",
"showProduct": True,
},
}
response = requests.post(
"https://seddi-public-api-gateway-91po835h.uc.gateway.dev/techpack-generator/v1",
json=payload,
headers={"x-api-key": os.environ["SEDDI_API_KEY"]},
)
response.raise_for_status()
print(response.json())
Response shape
{
"styleId": "uuid",
"pdf": {
"filePath": "techpack-generator/<requestId>/techpack.pdf",
"signedUrl": "https://..."
},
"images": [
{
"view": "FRONT",
"format": "image/png",
"resolution": { "x": 1024, "y": 1024 },
"filePath": "techpack-generator/<requestId>/images/0-front.png",
"signedUrl": "https://..."
}
],
"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://..."
}
],
"request": {
"brand": "Gildan",
"number": "64000",
"size": "M",
"color": "Black",
"tearAwayLabel": true,
"useBrandLogos": true,
"logos": [
{
"id": "front-logo",
"sourceUrl": "https://example.com/logo.png",
"region": "Chest",
"fill": true,
"layer": 1200,
"placement": {
"at": {
"x": 0.0,
"y": 0.05,
"measure": { "from": "Center Front Neck", "to": "Top Center" }
}
},
"technique": { "name": "Plastisol" },
"note": "Use approved colorway",
"underbase": "white",
"colorPalette": [{ "color": "#000000", "name": "Black" }]
}
],
"pdf": {
"units": "METRIC",
"showProduct": true,
"logo": "https://org-settings.example.com/preview.png"
}
}
}
Key response notes:
pdf.signedUrl,images[].signedUrl, and the logo signed URLs last 30 minutesimagesis present only whenrequestedImageswas supplied in the request; one entry per requested viewlogosincludes original and processed file references for every submitted logo. Those files live underlogos-for-generators/<cacheKey>/requestis replayable and normalized: defaults are expanded, 3D placements are canonicalized toplacement.at, andpdfreflects the effective values used to render
Behavior notes
- Style selection uses the 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)
- For vector uploads, conversion to PNG is handled automatically before render
- When
pdf.logoandpdf.disclaimerare not provided in the request, the service looks them up from your org settings before falling back to the built-in defaults
PDF rendering time depends on logo count, vector vs. raster sources, and view rendering. Build asynchronous UX or loading states into your integration.