SudoMock
REST

2D Mockups (Setup)

Place your artwork onto a product photo. Turn any apparel, poster, or packshot image into a reusable mockup, then render unlimited designs onto its print areas.

When to use this

Use the 2D Mockup API when you start from a flat product photo (a t-shirt, hoodie, poster, mug, or packaging shot) rather than a layered PSD template. If you already have PSD templates, use the Render (PSD) endpoint instead.

2D is a two-step flow

Step 1 is this page: set up a reusable mockup from a product photo. Step 2 is Render (2D): render any design onto that mockup. You set up once, then render as many artworks as you like.

How It Works

A 2D mockup is created once and reused for every design. Creating it is synchronous by default: the printable areas on your product photo are found and prepared, and the call returns the ready mockup — one call, no polling. Pass is_async: true for a queued job with webhook delivery instead. Rendering is always synchronous and returns a hosted image URL.

1
Create a mockup from a product photo
POST /api/v1/sudoai/2d-mockups returns the ready mockup with its print-area quads. Costs 25 credits.
2
Read the print-area quads
The create response carries the quads. With is_async: true, poll the job or receive a webhook first, then fetch the mockup.
3
Render artwork onto the print areas
POST /api/v1/sudoai/2d-mockups/{mockup_uuid}/render returns a hosted image. Costs 5 credits.

Create once, render forever

A mockup is reusable. You pay 25 credits to create it, then 5 credits per render for as many designs as you like. There is no watermark on 2D renders.

Authentication

Every request uses your API key in the x-api-key header. Get a key from your Dashboard.

x-api-keystringRequired

Your SudoMock API key, starting with sm_.

Content-TypestringRequired

Must be application/json for POST and PUT requests.

Idempotency-Keystring

Optional. Safely retry a create request without charging twice. Max 255 characters. Reusing a key with a different body returns 409.

Create a Mockup

POST/api/v1/sudoai/2d-mockups
25 credits

Send exactly one image source. By default the create is synchronous: the call blocks until the mockup is ready and returns it with a 201 Created — one call, no polling. Pass is_async: true to queue it instead and get a 202 Accepted job you can poll (or receive a webhook). Either way, if the image cannot be used for a mockup, the 25 credits are refunded automatically.

Request Body

source_urlstring

Public HTTPS URL of the product photo. Provide either source_url or source_base64, not both.

source_base64string

Base64-encoded product photo, with or without a data URL prefix. Provide either source_base64 or source_url, not both.

namestring

Optional display name for the mockup. Max 255 characters.

is_asyncboolean

Optional, default false. When false the call returns the finished mockup (201). When true it returns immediately with a 202 job to poll (or a webhook) — useful for batch creates.

Create request
1{
2 "source_url": "https://your-domain.com/product-photo.jpg",
3 "name": "Classic Tee - Front"
4}

Response (default, synchronous)

201Created
Response 201 Created
1{
2 "data": {
3 "mockup_id": "9b0a74cd-0ebb-4748-a748-976fec8cc000",
4 "name": "Classic Tee - Front",
5 "status": "ready",
6 "thumbnail_url": "https://cdn.sudomock.com/2d-mockups/9b0a74cd.../thumb.webp",
7 "source_width": 2000,
8 "source_height": 2400,
9 "quads": [
10 {
11 "print_area_id": "223e4567-e89b-12d3-a456-426614174001",
12 "points": [[420, 560], [1580, 560], [1600, 1840], [400, 1840]],
13 "sort_order": 0
14 }
15 ],
16 "version": 1,
17 "created_at": "2026-07-20T10:00:00Z",
18 "updated_at": "2026-07-20T10:00:12Z"
19 },
20 "success": true
21}

The synchronous response is the mockup itself, including its print-area quads — you can go straight to rendering. See Track and Fetch the Mockup below for the is_async: true job flow.

Track and Fetch the Mockup

GET/api/v1/sudoai/2d-mockups/{mockup_uuid}
Free

You only need this when you pass is_async: true — the synchronous default already returns the mockup. For an async create, poll the job at status_url until its status becomes succeeded (or receive a webhook); the completed job carries the new mockup_uuid. See the Jobs reference for the full poll contract.

Create response with is_async: true — 202 Accepted
1{
2 "job_id": "b7f2c1a0-9e34-4d21-8f0a-1c2b3d4e5f60",
3 "kind": "2d_create",
4 "status": "queued",
5 "status_url": "/api/v1/jobs/b7f2c1a0-9e34-4d21-8f0a-1c2b3d4e5f60"
6}
GET /api/v1/jobs/{job_id} once ready
1{
2 "job_id": "b7f2c1a0-9e34-4d21-8f0a-1c2b3d4e5f60",
3 "kind": "2d_create",
4 "status": "succeeded",
5 "result_url": "/api/v1/sudoai/2d-mockups/9b0a74cd-0ebb-4748-a748-976fec8cc000",
6 "mockup_uuid": "9b0a74cd-0ebb-4748-a748-976fec8cc000",
7 "error": null,
8 "created_at": "2026-07-20T10:00:00Z",
9 "updated_at": "2026-07-20T10:00:12Z"
10}

Then fetch the mockup itself to read its print areas. Each print area is a four-corner quad in image coordinates, returned in the quads array.

GET /api/v1/sudoai/2d-mockups/{mockup_uuid}
1{
2 "data": {
3 "mockup_id": "9b0a74cd-0ebb-4748-a748-976fec8cc000",
4 "name": "Classic Tee - Front",
5 "status": "ready",
6 "thumbnail_url": "https://cdn.sudomock.com/2d-mockups/9b0a74cd.../thumb.webp",
7 "source_width": 2000,
8 "source_height": 2400,
9 "quads": [
10 {
11 "print_area_id": "223e4567-e89b-12d3-a456-426614174001",
12 "points": [[420, 560], [1580, 560], [1600, 1840], [400, 1840]],
13 "sort_order": 0
14 }
15 ],
16 "version": 1,
17 "created_at": "2026-07-20T10:00:00Z",
18 "updated_at": "2026-07-20T10:00:12Z"
19 },
20 "success": true
21}

Mockup Fields

data.mockup_idstringRequired

UUID of the mockup. Pass it in the render URL path.

data.namestringRequired

Display name of the mockup.

data.statusstringRequired

Mockup state: draft, processing, ready, or error. Print areas are usable once ready.

data.thumbnail_urlstring

Preview thumbnail URL.

data.source_widthinteger

Source photo width in pixels. Print-area points are in this coordinate space.

data.source_heightinteger

Source photo height in pixels.

data.quadsarrayRequired

Print areas detected on the photo. Each entry has print_area_id, points, and sort_order.

data.quads[].print_area_idstringRequired

UUID of the print area. Pass this as uuid inside the render print_areas array.

data.quads[].pointsarrayRequired

Four [x, y] corner points, ordered top-left, top-right, bottom-right, bottom-left.

data.quads[].sort_orderintegerRequired

Display order of the print area, starting at 0.

PUT/api/v1/sudoai/2d-mockups/{mockup_uuid}/print-areas
Free

The print areas prepared at creation work out of the box. Use this endpoint only when you want to override them with your own placement. It replaces all print areas in the order you send, so include every area you want to keep. Available once the mockup is ready.

Prefer to place them visually? A Studio 2d-setup session opens a setup toolbar where you refine the product area, draw the print areas, and preview placement before saving. See Setting up print areas.

print_areasarrayRequired

One to eight print areas. Array order becomes the sort order.

print_areas[].pointsarrayRequired

Exactly four [x, y] corner points, in image coordinates, ordered top-left, top-right, bottom-right, bottom-left. Each area must be a convex four-point shape inside the source image.

Replace print areas
1{
2 "print_areas": [
3 {
4 "points": [[420, 560], [1580, 560], [1600, 1840], [400, 1840]]
5 }
6 ]
7}
200OK
Response 200 OK
1{
2 "data": {
3 "mockup_id": "9b0a74cd-0ebb-4748-a748-976fec8cc000",
4 "print_areas": [
5 {
6 "print_area_id": "223e4567-e89b-12d3-a456-426614174001",
7 "points": [[420, 560], [1580, 560], [1600, 1840], [400, 1840]],
8 "sort_order": 0
9 }
10 ]
11 },
12 "success": true
13}

Render Artwork

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

Render one or more designs onto a mockup you created earlier. Each print area takes an artwork image, a solid color, or both. The response returns a hosted image URL. This call is synchronous.

Request Body

mockup_uuidstringRequired

Path parameter in the URL, not the body: UUID of the 2D mockup to render, from the create job or the get-mockup response.

print_areasarrayRequired

One to eight print-area configurations. Each is matched to the mockup by its uuid.

export_optionsobject

Output format, size, and quality. Optional; sensible defaults apply.

Artwork or color required

Each print area must include at least an artwork_url (or base64) or a color. You can supply both to tint the artwork.
uuidstringRequired

The print_area_id from the get-mockup response, identifying which area to fill.

artwork_urlstring

URL of the artwork image to place. Provide artwork_url or base64.

base64string

Base64-encoded artwork image. Skips the download step. Provide base64 or artwork_url.

colorstring

Solid color overlay in #RRGGBB format (e.g. '#FF0000'). Can be used alone or to tint the artwork.

adjustmentsobject

Per-artwork image adjustments. See Adjustments below.

placementobject

How the artwork sits inside the print area. See Placement below.

Adjustments

brightnessinteger= 0

Brightness (-150 to 150). 0 = no change.

contrastinteger= 0

Contrast (-100 to 100). 0 = no change.

saturationinteger= 0

Saturation (-100 to 100). -100 = grayscale.

vibranceinteger= 0

Vibrance (-100 to 100). Boosts muted tones while protecting skin tones.

opacityinteger= 100

Artwork opacity (0 to 100). 0 = transparent, 100 = opaque.

blurinteger= 0

Gaussian blur (0 to 100). 0 = sharp.

blend_modestring= multiply

How the artwork blends with the product surface. 'multiply' keeps the fabric or material texture visible; 'normal' lays the artwork flat.

warp_strengthnumber= 1.5

How strongly the artwork follows the product's surface curves (0 to 2). 0 disables it.

edge_expandinteger= 0

Fills thin gaps at the artwork border (0 to 50). 0 disables it.

texture_strengthinteger= 0

How strongly the artwork picks up the product surface texture (0 to 100). 0 disables it.

Placement

positionenum= center

Anchor within the print area: center, top_left, top_center, top_right, center_left, center_right, bottom_left, bottom_center, bottom_right.

coverageinteger= 70

Percent of the print area the artwork covers (10 to 100). Ignored when scale is set.

fitenum= contain

How the artwork fits its box: 'contain' fits inside preserving aspect ratio, 'fill' stretches to the bounds, 'cover' fills and crops excess.

scalenumber

Scale multiplier for the artwork (0.01 to 10). Overrides coverage and fit sizing.

rotationnumber= 0

Rotation in degrees, clockwise positive.

offset_xinteger= 0

Horizontal pixel offset from the anchor position.

offset_yinteger= 0

Vertical pixel offset from the anchor position.

Export Options

image_formatenum= webp

Output format: webp (30-70% smaller, recommended), png (lossless, quality ignored), or jpg (smallest, no transparency).

image_sizeinteger= 2048

Output width in pixels (100 to 10000). Height is derived from the source aspect ratio. Powers of two (1024, 2048, 4096) are recommended.

qualityinteger= 90

Compression quality for JPG and WebP (1 to 100). Ignored for PNG.

dpiinteger= null

Print resolution tag written into the file metadata (72 to 2400). Metadata only; image_size controls the real pixels. For a print file, size image_size = print_inches x dpi.

Full render request
1{
2 "print_areas": [
3 {
4 "uuid": "223e4567-e89b-12d3-a456-426614174001",
5 "artwork_url": "https://your-domain.com/design.png",
6 "adjustments": {
7 "blend_mode": "multiply",
8 "opacity": 95
9 },
10 "placement": {
11 "position": "center",
12 "coverage": 80,
13 "fit": "contain"
14 }
15 }
16 ],
17 "export_options": {
18 "image_format": "png",
19 "image_size": 2048,
20 "quality": 95
21 }
22}

Response

200OK
Response 200 OK
1{
2 "data": {
3 "render_uuid": "9adcc828-1f4e-4a2b-9c3d-2e6f8b0a1d77",
4 "print_files": [
5 {
6 "export_path": "https://cdn.sudomock.com/renders/2d/9b0a74cd.../render.png",
7 "duration_ms": 1180,
8 "export_format": "png"
9 }
10 ]
11 },
12 "success": true
13}
data.render_uuidstring

Identifier for this render.

data.print_filesarrayRequired

Rendered output files.

data.print_files[].export_pathstringRequired

Hosted URL of the rendered image.

data.print_files[].duration_msinteger

Render duration in milliseconds.

data.print_files[].export_formatstring

Output format used (png, jpg, or webp).

No watermark

2D renders are delivered without a watermark. The output URL is ready to use in your store, catalog, or fulfillment flow.

Prefer no backend? Embed Studio

If you want your customers to place their own artwork on this mockup, embed the Studio editor with one iframe. Studio handles upload, placement, live preview, and add to cart, so you skip building a render frontend.

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.

Code Examples

Create and render a 2D mockup
bash
1# 1. Create a reusable 2D mockup (synchronous: the call returns the ready mockup)
2curl -X POST "https://api.sudomock.com/api/v1/sudoai/2d-mockups" \
3 -H "Content-Type: application/json" \
4 -H "x-api-key: sm_your_api_key" \
5 -d '{
6 "source_url": "https://your-domain.com/product-photo.jpg",
7 "name": "Classic Tee - Front"
8 }'
9# -> 201 { "data": { "mockup_id": "...", "quads": [{ "print_area_id": "...", ... }] } }
10# Add "is_async": true to get a 202 { "job_id", "status_url" } job to poll instead.
11
12# 2. Render your artwork onto a print area
13curl -X POST "https://api.sudomock.com/api/v1/sudoai/2d-mockups/MOCKUP_UUID/render" \
14 -H "Content-Type: application/json" \
15 -H "x-api-key: sm_your_api_key" \
16 -d '{
17 "print_areas": [{
18 "uuid": "PRINT_AREA_ID",
19 "artwork_url": "https://your-domain.com/design.png",
20 "placement": { "position": "center", "coverage": 80 }
21 }],
22 "export_options": { "image_format": "png", "image_size": 2048 }
23 }'

Webhooks

Instead of polling, configure a webhook endpoint to be notified when a creation job finishes. Set it up and verify signatures on the Webhooks page. The 2D creation flow emits these events:

2d_mockup.readyevent

The mockup was created and its print areas are ready to render.

2d_mockup.rejectedevent

The image was not suitable for a mockup. The payload includes a reason. Credits are refunded.

2d_mockup.failedevent

The creation job failed unexpectedly. Credits are refunded.

2d_mockup.ready payload
1{
2 "mockup_id": "9b0a74cd-0ebb-4748-a748-976fec8cc000",
3 "name": "Classic Tee - Front",
4 "status": "ready",
5 "print_areas": [
6 {
7 "print_area_id": "223e4567-e89b-12d3-a456-426614174001",
8 "points": [[420, 560], [1580, 560], [1600, 1840], [400, 1840]],
9 "sort_order": 0
10 }
11 ]
12}

Idempotent by design

A delivery may arrive more than once. Match on mockup_id and the event name so a repeated delivery is a safe no-op.

Error Responses

400Bad Request

Invalid input, such as both or neither image source on create, or a print area outside the source image.

json
1{
2 "error_code": "INVALID_SOURCE",
3 "message": "Provide exactly one of source_url or source_base64.",
4 "detail": "Remove one source field, or add the missing source field.",
5 "success": false
6}
401Unauthorized

Missing or invalid API key.

json
1{
2 "detail": "Not authenticated",
3 "success": false
4}
402Payment Required

Not enough credits. Create needs 25 credits, render needs 5. The response includes actionable links and the credit reset time.

json
1{
2 "error": "credits_exhausted",
3 "message": "You've run out of credits for this billing period.",
4 "actions": [
5 { "label": "Enable Pay-As-You-Go", "url": "https://sudomock.com/dashboard/billing?action=enable-payg" },
6 { "label": "Upgrade Plan", "url": "https://sudomock.com/pricing" }
7 ],
8 "credits_reset_at": "2026-08-01T00:00:00Z"
9}
404Not Found

The mockup UUID does not exist or is not owned by your account.

json
1{
2 "detail": "Failed to retrieve mockup",
3 "success": false
4}
409Conflict

Print areas can only be changed after the mockup is ready, or an Idempotency-Key was reused with a different request body.

json
1{
2 "error_code": "MOCKUP_NOT_SETTABLE",
3 "message": "Print areas can only be changed after the mockup is ready.",
4 "suggestion": "Wait for the creation job to finish and try again."
5}
429Too Many Requests

Rate limit or concurrent render limit exceeded. Retry after the indicated delay.

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 "retry_after": 30,
7 "resource": "api"
8 }
9}

Try It Live

POST/api/v1/sudoai/2d-mockups/your-mockup-uuid/render

Render artwork onto a 2D mockup you already created.

Get your API key from the Dashboard

Path Parameters