Render Photo Mockup
Render your artwork onto a photo mockup. You set the mockup up once in the dashboard (photo, printable surface, print area), then call this endpoint with the mockup UUID in the path and the print area UUIDs in the body to render any design programmatically.
/api/v1/sudoai/2d-mockups/{mockup_uuid}/renderSet up the mockup once, then render any design
mockup_uuid and a returned target ID.How It Works
mockup_uuidplus a surface_uuid for each printable product, and auuid for each print area you draw on one.mockup_uuid and target uuid or surface_uuid already filled in. Pick your language and copy it.POST /api/v1/sudoai/2d-mockups/{mockup_uuid}/render with yourartwork_url (and optional placement / adjustments) to render. Swap the artwork on every call to render a new design onto the same saved mockup.Why is there a setup step?
Prefer no backend? Embed Studio
Security
Request
Headers
X-API-KeystringRequiredYour SudoMock API key starting with sm_
Content-TypestringRequiredMust be application/json
Idempotency-KeystringOptional. Use a stable value to retry an asynchronous render without creating and charging for a duplicate job. Max 255 characters.
Request Body
mockup_uuidstringRequiredPath parameter in the URL, not the body: UUID of the photo mockup you set up in the dashboard. Find it in the editor's Code tab, or in the URL of the mockup in Dashboard > Photo to Mockup.
print_areasarrayRequiredOne entry per render target. Each entry supplies exactly one identifier, a print-area uuid or a surface_uuid, plus its artwork or color and options.
export_optionsobjectOutput format, size, and quality settings for the rendered file.
is_asyncbooleanOptional, default false. When false, returns the rendered file in the same response. When true, returns a 202 2d_render job.
Render Target Object
Each item in print_areas targets either one print area or one product surface. Send exactly one identifier per item. A product that has print areas drawn on it can still be addressed as a surface, so an all-over print and a chest logo are two entries on the same product.
uuidstringUUID of a print area from data.quads. Required when surface_uuid is omitted.
surface_uuidstringUUID of a printable product from data.surfaces. Required when uuid is omitted.
artwork_urlstringPublicly reachable URL of the artwork/design to place in this print area. Required unless color is provided.
colorstringColor fill in hex format (e.g., '#FF0000'). Use alone for a solid color fill, or together with artwork_url to apply a color overlay.
remove_backgroundboolean= falseRemove the artwork background before placement. Pricing starts at about $0.06 per unique artwork source.
adjustmentsobjectArtwork appearance controls: brightness, contrast, opacity, saturation, vibrance, blur, and blend mode.
placementobjectHow the artwork is positioned and sized on this target. position, offset_x, offset_y and rotation apply to both kinds. A surface target also takes coverage; a print-area target also takes fit, or an explicit width and height.
Artwork or Color Required
artwork_url orcolor. You can provide both to apply a color overlay on top of your artwork.Print areas and surfaces use different IDs
uuid for an entry returned in data.quads. Use surface_uuid for an entry returned in data.surfaces. Never send both on one target, and never send the mockup's own UUID as a target: it names the mockup in the URL path, not a render target.Adjustments
brightnessinteger= 0Brightness adjustment (-150 to 150)
contrastinteger= 0Contrast adjustment (-100 to 100)
opacityinteger= 100Artwork opacity (0=fully transparent, 100=fully opaque)
saturationinteger= 0Saturation adjustment (-100 to 100)
vibranceinteger= 0Vibrance adjustment (-100 to 100)
blurinteger= 0Gaussian blur amount (0 to 100)
blend_modeenum= multiplyHow the artwork sits on the product surface. One of 'multiply', 'normal', 'screen', 'lighten', 'soft_light', 'overlay', or 'darken'. Send 'normal' when a brand color has to match the supplied file. See Blend Modes below.
Placement
Controls how the artwork is positioned and sized on the target. position, offset_x, offset_y and rotation apply to both kinds of target. The sizing option depends on what you addressed: a surface takes coverage, a print area takes fit or an explicit width and height.
positionenum= centerPredefined position within the target
coverageinteger= 100Surface targets only. Percentage of the product surface the artwork covers (10 to 100). Sending it with a print-area target returns 422.
fitenum= fitPrint-area targets only, and always measured against the full print area: 'fill' (stretch to the bounds, proportions not kept), 'fit' (fit inside, proportions kept), 'crop' (cover the area and crop the overflow, proportions kept). Sending it with a surface target, or alongside width and height, returns 422.
widthintegerAn explicit box, accepted by either kind of target. Artwork width in print-area pixels (1 to 30000). Send it together with height, and without fit or coverage. The two axes are independent, so you can stretch artwork on one axis alone, and an explicit box is also how you leave padding inside the area.
heightintegerAn explicit box, accepted by either kind of target. Artwork height in print-area pixels (1 to 30000). Send it together with width. Sending only one of the two is rejected rather than guessed.
rotationnumber= 0Rotation in degrees. Applied to the artwork before placement.
offset_xinteger= 0Horizontal offset in print-area pixels, measured from the anchor that position picks. Positive moves right, negative moves left. With the default position of center, that anchor is the middle of the print area.
offset_yinteger= 0Vertical offset in print-area pixels, measured from the anchor that position picks. Positive moves down, negative moves up. With the default position of center, that anchor is the middle of the print area.
Available Position Values
The position parameter accepts a 3x3 grid of predefined positions within the target:
Export Options
image_formatenum= webpOutput format: png, jpg, or webp
image_sizeinteger= 2048Output width in pixels (100-10000). Height scales proportionally. This sets the actual pixel dimensions of the file.
qualityinteger= 90Compression quality for JPG/WebP (1-100). Ignored for PNG.
dpiinteger= nullPrint resolution tag written into the output file metadata (72-2400). Metadata only; it does not change the pixels. image_size controls the actual pixels. For a print file, size your pixels: image_size = print_inches x dpi (e.g. 12 in x 300 = 3600 px). All formats (JPG, PNG, WebP) carry the tag; JPG and PNG are recommended for the widest print-tool compatibility. Opt-in: when omitted, files carry a default 25.4 DPI tag.
1{2 "print_areas": [3 {4 "uuid": "128394ee-6758-4f2f-aa36-e2b19b152bd9",5 "artwork_url": "https://your-domain.com/design.png",6 "adjustments": {7 "brightness": 0,8 "contrast": 0,9 "opacity": 100,10 "saturation": 0,11 "vibrance": 0,12 "blur": 0,13 "blend_mode": "multiply"14 },15 "placement": {16 "position": "center",17 "fit": "fit"18 }19 }20 ],21 "export_options": {22 "image_format": "webp",23 "image_size": 1920,24 "quality": 9525 }26}
1{2 "print_areas": [3 {4 "surface_uuid": "323e4567-e89b-12d3-a456-426614174002",5 "artwork_url": "https://your-domain.com/design.png",6 "placement": {7 "position": "center",8 "coverage": 709 }10 }11 ],12 "export_options": {13 "image_format": "webp",14 "image_size": 1920,15 "quality": 9516 }17}
Code Examples
The Code tab in the editor generates these snippets for your own mockup, with the real mockup_uuid and render target ID already filled in. The examples below use a print-area uuid; a product surface uses surface_uuid instead.
1curl -X POST "https://api.sudomock.com/api/v1/sudoai/2d-mockups/c315f78f-d2c7-4541-b240-a9372842de94/render" \2 -H "Content-Type: application/json" \3 -H "X-API-Key: sm_your_api_key" \4 -d '{5 "print_areas": [6 {7 "uuid": "128394ee-6758-4f2f-aa36-e2b19b152bd9",8 "artwork_url": "https://your-domain.com/design.png",9 "placement": {10 "position": "center",11 "fit": "fit"12 }13 }14 ],15 "export_options": {16 "image_format": "webp",17 "image_size": 1920,18 "quality": 9519 }20 }'
Response
Success Response
1{2 "success": true,3 "data": {4 "print_files": [5 {6 "export_path": "https://cdn.sudomock.com/renders/sudoai/abc123.webp",7 "duration_ms": 1840,8 "export_format": "webp"9 }10 ]11 }12}
Response Fields
successbooleanRequiredAlways true for successful responses
dataobjectRequiredResponse data wrapper
data.print_filesarrayRequiredArray of rendered output files, one per rendered print area
data.print_files[].export_pathstringRequiredCDN URL to the rendered mockup image
data.print_files[].duration_msintegerTime in milliseconds the render took to produce this file
data.print_files[].export_formatstringOutput format that was used (png, jpg, or webp)
Asynchronous Response
Set is_async: true for batch or long-running workflows. The API returns a job immediately instead of holding the request open.
1{2 "job_id": "9d4e2b51-2ef0-49ca-92bc-9a4c157a2fe8",3 "kind": "2d_render",4 "status": "queued",5 "status_url": "/api/v1/jobs/9d4e2b51-2ef0-49ca-92bc-9a4c157a2fe8"6}
Poll status_url or subscribe to 2d_render.succeeded and 2d_render.failed. A succeeded job exposes the rendered image in result_url. See Jobs & Polling and the Webhooks reference.
Error Responses
1{2 "detail": "Mockup not found",3 "success": false4}
Returned when mockup_uuid does not match a mockup on your account. Copy the exact value from the editor's Code tab, or from the mockup's URL in Dashboard → Photo to Mockup.
1{2 "detail": "Validation error",3 "errors": [4 {"field": "print_areas", "message": "Field required"}5 ],6 "success": false7}
Returned when required fields are missing or invalid. The most common cause is sending the body without print_areas, or a render target without exactly one valid uuid or surface_uuid. Each target also needs at least one of artwork_url or color. A placement option sent to the wrong kind of target is rejected the same way: coverage belongs to a surface, fit and an explicit width plus height belong to a print area, and fit and that pair cannot travel together. The Code tab produces a body that already satisfies these requirements.
1{2 "detail": "Invalid or missing API key",3 "success": false4}
1{2 "error": "credits_exhausted",3 "message": "You have used all 500 trial credits. Add a payment method to keep rendering, or start a plan.",4 "actions": [5 { "label": "Add a payment method", "url": "https://sudomock.com/dashboard/billing?action=topup#payg-section" },6 { "label": "Start a plan", "url": "https://sudomock.com/pricing" }7 ]8}
1{2 "detail": "Rate limit exceeded. Try again in 30 seconds.",3 "error": {4 "type": "rate_limit_exceeded",5 "code": "RATE_LIMIT_EXCEEDED",6 "limit": 1000,7 "remaining": 0,8 "reset_seconds": 30,9 "retry_after": 30,10 "resource": "api"11 }12}
1{2 "detail": "Something went wrong while processing your image. Please try again.",3 "success": false4}
Retired Paths
Earlier 2D render paths were retired
/api/v1/sudoai/2d-mockup/render and its older alias/api/v1/sudoai/render. The mockup UUID moved from the request body into the URL path. Use the canonical endpoint POST /api/v1/sudoai/2d-mockups/{mockup_uuid}/render and send only print_areas and export_options in the body.Try It Live
Replace the placeholder UUIDs below with values from your own mockup. The fastest way to get a working request is the Code tab in the editor. It fills in the correct mockup_uuid and render target uuid or surface_uuid for you.
Photo to Mockup vs Standard Render API
Photo to Mockup and the standard Render API serve different use cases. Here is when to use each:
| Photo to Mockup | Standard Render | |
|---|---|---|
| Template | A product photo prepared as a reusable mockup | A PSD with smart object layers |
| Setup | Automatic preparation, with optional review in the dashboard | Upload a prepared PSD (once) |
| Render input | mockup_uuid + target uuid or surface_uuid | mockup_uuid + smart_objects[].uuid |
| Credits | 5 per render | 1 per render |
| Best for | Quick mockups from a single product photo | Professional templates, high-volume automation |
| Perspective | Automatic surface warp from the product photo | Baked into PSD smart objects |
A single product photo becomes a reusable mockup, then any artwork warps onto the printable surface with realistic perspective. No PSD template required.
Image Fit Modes
The placement.fit parameter controls how your artwork meets the print area. The editor prints these same three words on its buttons, so the value you send and the button a seller clicks are the same word.
contain and cover are the older names forfit and crop. They are still accepted and will stay accepted, so nothing you have already shipped needs to change.
| Mode | Editor label | Behavior | Use Case |
|---|---|---|---|
fill | Fill | Stretched to the area; proportions are not kept, so the design can distort | When the design already has the print area's proportions |
fit | Fit | Scaled until it fits inside; proportions kept, so space can be left over | When the whole design has to stay visible (default) |
crop | Crop | Covers the area and cuts the overflow; proportions kept | All-over prints and whole-product designs |
Blend Modes
The adjustments.blend_mode parameter controls how artwork blends with the product surface:
Pick the mode from the garment, not the artwork
multiply for garments and textured surfaces: it lets the material texture show through, so the design looks printed rather than pasted on. On a dark garment a light artwork gets swallowed by multiply, so reach for screen there. Use normal for hard surfaces like mugs or phone cases, where you want the artwork exactly as supplied. The remaining four are for a specific look: overlay for stronger contrast, soft_light for a gentle finish, darken and lighten to keep only the darker or lighter parts of the artwork.When a brand color must not shift
multiply behaves like real ink: on a black tee a white logo comes out grey. That is what makes it look printed, and it is not what you want when a brand color has to match. Send "blend_mode": "normal" and the artwork keeps its exact colors on any product color: white stays white, and a brand blue stays that blue. Blend mode is set per print area, so one area can hold an exact logo while another stays on multiply.Tips for Best Results
mockup_uuid and target uuid work for every print-area render. Surface targets reuse their surface_uuid. Swap only artwork_url to render a new design onto the same product.coverage sets how much of the product the artwork takes: leave it out for the whole surface, or drop it to 30-40 for a small centered design. On a print area, fit sizes the artwork against the full area, and an explicit width and height place it exactly.Batch Rendering
Parallel Renders
mockup_uuid and target uuid or surface_uuid, and vary only the artwork_url.1// JavaScript: Render multiple designs on the same mockup2const mockupUuid = "c315f78f-d2c7-4541-b240-a9372842de94";3const printAreaUuid = "128394ee-6758-4f2f-aa36-e2b19b152bd9";4const designs = [5 "https://cdn.example.com/design-1.png",6 "https://cdn.example.com/design-2.png",7 "https://cdn.example.com/design-3.png",8];910const renders = designs.map(url =>11 fetch(`https://api.sudomock.com/api/v1/sudoai/2d-mockups/${mockupUuid}/render`, {12 method: "POST",13 headers: {14 "Content-Type": "application/json",15 "X-API-Key": "sm_your_api_key"16 },17 body: JSON.stringify({18 print_areas: [19 { uuid: printAreaUuid, artwork_url: url }20 ]21 })22 }).then(r => r.json())23);2425const results = await Promise.all(renders);
Need a feature that's not here? Request it or see what's planned.