SudoMock
POST

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.

POST/api/v1/sudoai/2d-mockups/{mockup_uuid}/render
5 credits per render

Set up the mockup once, then render any design

Upload a product photo once and SudoMock prepares a reusable mockup automatically. You can review and adjust the result in the dashboard. This endpoint then renders new artwork onto the saved mockup using its mockup_uuid and a returned target ID.

How It Works

1
Set up your mockup in the dashboard (once)
Open Dashboard → Photo to Mockup and upload the product photo. SudoMock prepares its supported product surfaces and opens the result for review. The saved mockup receives a mockup_uuidplus a surface_uuid for each printable product, and auuid for each print area you draw on one.
2
Copy the working request from the Code tab
The editor has a Code tab that generates a ready-to-run request for your mockup, with the correct mockup_uuid and target uuid or surface_uuid already filled in. Pick your language and copy it.
3
Render any artwork programmatically
Send 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?

Confirming the printable surface and print area once, up front, makes every render land correctly. It is a one-time step per mockup, not per render.

Prefer no backend? Embed Studio

Rendering from your server is one path. If you would rather let your customers place their own artwork on the storefront, embed the Studio editor with one iframe. Studio handles upload, placement, live preview, and add to cart for you.

Security

Studio uses an opaque, origin-bound session token, and config writes are gated to your API key. Studio requests and responses expose no pipeline internals, only the mockup contract. See the Studio security model.

Request

Headers

X-API-KeystringRequired

Your SudoMock API key starting with sm_

Content-TypestringRequired

Must be application/json

Idempotency-Keystring

Optional. Use a stable value to retry an asynchronous render without creating and charging for a duplicate job. Max 255 characters.

Request Body

mockup_uuidstringRequired

Path 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_areasarrayRequired

One 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_optionsobject

Output format, size, and quality settings for the rendered file.

is_asyncboolean

Optional, default false. When false, returns the rendered file in the same response. When true, returns a 202 2d_render job.

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.

uuidstring

UUID of a print area from data.quads. Required when surface_uuid is omitted.

surface_uuidstring

UUID of a printable product from data.surfaces. Required when uuid is omitted.

artwork_urlstring

Publicly reachable URL of the artwork/design to place in this print area. Required unless color is provided.

colorstring

Color 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= false

Remove the artwork background before placement. Pricing starts at about $0.06 per unique artwork source.

adjustmentsobject

Artwork appearance controls: brightness, contrast, opacity, saturation, vibrance, blur, and blend mode.

placementobject

How 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

Each render target must include at least one of artwork_url orcolor. You can provide both to apply a color overlay on top of your artwork.

Print areas and surfaces use different IDs

Use 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= 0

Brightness adjustment (-150 to 150)

contrastinteger= 0

Contrast adjustment (-100 to 100)

opacityinteger= 100

Artwork opacity (0=fully transparent, 100=fully opaque)

saturationinteger= 0

Saturation adjustment (-100 to 100)

vibranceinteger= 0

Vibrance adjustment (-100 to 100)

blurinteger= 0

Gaussian blur amount (0 to 100)

blend_modeenum= multiply

How 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= center

Predefined position within the target

coverageinteger= 100

Surface targets only. Percentage of the product surface the artwork covers (10 to 100). Sending it with a print-area target returns 422.

fitenum= fit

Print-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.

widthinteger

An 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.

heightinteger

An 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= 0

Rotation in degrees. Applied to the artwork before placement.

offset_xinteger= 0

Horizontal 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= 0

Vertical 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:

top_left
top_center
top_right
center_left
center
center_right
bottom_left
bottom_center
bottom_right

Export Options

image_formatenum= webp

Output format: png, jpg, or webp

image_sizeinteger= 2048

Output width in pixels (100-10000). Height scales proportionally. This sets the actual pixel dimensions of the file.

qualityinteger= 90

Compression quality for JPG/WebP (1-100). Ignored for PNG.

dpiinteger= null

Print 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.

Print-Area Request
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": 95
25 }
26}
Surface Request
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": 70
9 }
10 }
11 ],
12 "export_options": {
13 "image_format": "webp",
14 "image_size": 1920,
15 "quality": 95
16 }
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.

Render Photo Mockup
bash
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": 95
19 }
20 }'

Response

Success Response

200OK
Response 200 OK
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

successbooleanRequired

Always true for successful responses

dataobjectRequired

Response data wrapper

data.print_filesarrayRequired

Array of rendered output files, one per rendered print area

data.print_files[].export_pathstringRequired

CDN URL to the rendered mockup image

data.print_files[].duration_msinteger

Time in milliseconds the render took to produce this file

data.print_files[].export_formatstring

Output 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.

202Accepted
Response 202 Accepted
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

404Not Found
json
1{
2 "detail": "Mockup not found",
3 "success": false
4}

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.

422Validation Error
json
1{
2 "detail": "Validation error",
3 "errors": [
4 {"field": "print_areas", "message": "Field required"}
5 ],
6 "success": false
7}

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.

401Unauthorized
json
1{
2 "detail": "Invalid or missing API key",
3 "success": false
4}
402Payment Required
json
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}
429Too Many Requests
json
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}
500Internal Server Error
json
1{
2 "detail": "Something went wrong while processing your image. Please try again.",
3 "success": false
4}

Retired Paths

Earlier 2D render paths were retired

Two earlier paths are no longer available and now return 404: the singular/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.

POST/api/v1/sudoai/2d-mockups/c315f78f-d2c7-4541-b240-a9372842de94/render

Render artwork onto a prepared photo mockup. Use your own mockup_uuid in the path and exactly one uuid or surface_uuid per render target.

Get your API key from the Dashboard

Path Parameters

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 MockupStandard Render
TemplateA product photo prepared as a reusable mockupA PSD with smart object layers
SetupAutomatic preparation, with optional review in the dashboardUpload a prepared PSD (once)
Render inputmockup_uuid + target uuid or surface_uuidmockup_uuid + smart_objects[].uuid
Credits5 per render1 per render
Best forQuick mockups from a single product photoProfessional templates, high-volume automation
PerspectiveAutomatic surface warp from the product photoBaked 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.

ModeEditor labelBehaviorUse Case
fillFillStretched to the area; proportions are not kept, so the design can distortWhen the design already has the print area's proportions
fitFitScaled until it fits inside; proportions kept, so space can be left overWhen the whole design has to stay visible (default)
cropCropCovers the area and cuts the overflow; proportions keptAll-over prints and whole-product designs

Blend Modes

The adjustments.blend_mode parameter controls how artwork blends with the product surface:

multiply
Keeps the material texture visible. Best on light fabric (default)
normal
Reproduces the artwork colors exactly. Use it for brand colors
screen
Lightens the artwork against the surface. The default already adapts to a dark garment, so reach for this only when you want the lighter result
lighten
Keeps the artwork only where it is brighter than the surface
soft_light
A subtle, low-contrast finish that follows the surface
overlay
Deepens contrast so the artwork reads as part of the material
darken
Keeps the artwork only where it is darker than the surface

Pick the mode from the garment, not the artwork

Use 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

1.
Review the prepared placement
Check the prepared product surface and placement once in the dashboard. Adjust it only when the source photo needs a correction, then reuse the saved mockup.
2.
Use transparent PNG artwork
Artwork with a transparent background composites cleanly. JPG artwork will include its white background.
3.
Reuse one mockup for many designs
The same 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.
4.
Pick the sizing option that matches the target
On a surface, 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

To render many designs on the same mockup, send parallel requests that reuse the samemockup_uuid and target uuid or surface_uuid, and vary only the artwork_url.
Batch Rendering on One Mockup
1// JavaScript: Render multiple designs on the same mockup
2const 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];
9
10const 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);
24
25const results = await Promise.all(renders);

Need a feature that's not here? Request it or see what's planned.