Skip to main content

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 request payload 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:

  • brand
  • number
  • size
  • color
  • logos

Optional top-level fields:

  • tearAwayLabel (defaults to true)
  • useBrandLogos (subject to org-brand approval; falls back to false when approval cannot be verified)
  • profile (decorator profile slug from GET /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:
    • format
    • resolution (x, y, both > 0)
    • view
  • format accepts only:
    • "image/png"
    • "image/jpeg"
    • "image/jpg"
    • "image/webp"
  • view accepts 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 sourceUrl file must be 15MB or smaller
  • Each logo requires:
    • sourceUrl (must be https; source file max 15MB)
  • fill is optional and defaults to false. A non-boolean value is rejected. Replay echoes false when the field was omitted.
    • fill: true scales the graphic to fit inside the region and keeps its aspect ratio. size and placement.at are ignored. placement.align can still shift leftover space.
    • Omit fill, or send false, to place the graphic with size and placement.
  • size.x and size.y are 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. Omit size entirely and the graphic uses its own dimensions, then scales down to stay inside the region.
  • placement.at.x and placement.at.y are offsets in meters from the point of measure. Larger y is toward the top of the piece.
  • placement.at.measure.from is a point-of-measure name from GET /data/v1/points-of-measure. Matching is case-insensitive on name, then id if 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 returns 400 with the style's point-of-measure names.
  • region is required unless placement.at is provided. Send the region name from GET /data/v1/regions. An id is accepted when you already have one.
  • placement.at and placement.align are mutually exclusive
  • placement.align is relative to the region. x is left, center, or right. y is top, center, or bottom.
  • placement.at.measure.to accepts only:
    • "Top Left"
    • "Top Center"
    • "Top Right"
    • "Left"
    • "Center"
    • "Right"
    • "Bottom Left"
    • "Bottom Center"
    • "Bottom Right"
  • layer defaults to 1000 when omitted; higher layers render on top
  • transform.rotation is optional. It is the orientation in the finished scene, in degrees (clockwise). Omit it or send 0 so the logo top points toward the top of the scene; 180 flips it. Placement cancels the host piece's arrangement rotation. Replay echoes that degree value. regionTransform.rotation remains 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.
  • colorMap is optional. It is an array of up to 16 { "from": "#rrggbb", "to": "#rrggbb" } pairs. Each from must be unique. The array length is the palette used to recolor the graphic. Omit colorMap, or send [], to keep the original colors. colorMap does not replace colorPalette swatches when those are sent.
  • Supported source formats:
    • Raster: png, jpg, jpeg, webp, psd, tif, tiff
    • Vector: svg, ai, eps, pdf
  • technique is optional. When provided, technique.name accepts only:
    • "Plastisol"
    • "Waterbased"
    • "Glitter"
    • "HighDensity"
    • "Puff"
    • "HeatTransfer"
    • "DirectToGarment"
    • "Embroidery"
    • "Patch"
    • "Custom"
  • When technique.name is "Custom", technique.value is required and must be a non-empty string
  • When technique is omitted, the default is "Plastisol" (replay reflects "Plastisol")
  • Rubber is accepted as an alias for Plastisol and is replayed as "Plastisol"
  • note is free text rendered in the decoration page "Notes" section
  • underbase accepts 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 from colorMap, 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:

AliasResolves to
FIRSTHighest-priority available decoration region
SECONDSecond-highest-priority available region
THIRDThird-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:

  1. Chest
  2. WL Chest
  3. Chest Pocket
  4. Front
  5. Back
  6. WR Sleeve
  7. WL Sleeve
  8. Nape
  9. WL Hip
  10. WR Hip
  11. WL Hem
  12. WR Hem
  13. 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:

FieldDescription
units"METRIC" or "IMPERIAL". Controls measurements shown in the PDF.
nameBold title in the PDF header. Defaults to ${brand} ${number}.
productProduct description below the title. Defaults to an auto-derived style summary.
logoURL of a header logo image.
disclaimerFooter disclaimer text.
showProductWhen 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:

Field1. Request2. User / org fallback3. Service default
pdf.unitsrequest.pdf.unitsuser preference units"METRIC"
pdf.logorequest.pdf.logoorg settings previewplaceholder header logo
pdf.disclaimerrequest.pdf.disclaimerorg settings disclaimer (best-effort)static disclaimer text
pdf.name, pdf.product, pdf.showProductrequest.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 minutes
  • images is present only when requestedImages was supplied in the request; one entry per requested view
  • logos includes original and processed file references for every submitted logo. Those files live under logos-for-generators/<cacheKey>/
  • request is replayable and normalized: defaults are expanded, 3D placements are canonicalized to placement.at, and pdf reflects the effective values used to render

Behavior notes​

  • Style selection uses the first match by brand + number + color + size
  • tearAwayLabel=false removes 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.logo and pdf.disclaimer are not provided in the request, the service looks them up from your org settings before falling back to the built-in defaults
Generation time

PDF rendering time depends on logo count, vector vs. raster sources, and view rendering. Build asynchronous UX or loading states into your integration.