> ## Documentation Index
> Fetch the complete documentation index at: https://sudomock.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> The base URL is https://api.sudomock.com.
> Authenticate every request with the x-api-key header. Keys begin with sm_.
> A render returns the finished image at data.print_files[0].export_path. A request sent with is_async true returns a job_id to poll at GET /api/v1/jobs/{job_id}.
> Prefer the official SDKs over hand-written HTTP calls: npm install sudomock for Node, pip install sudomock for Python.

# Create a mockup from a product photo

> Turns one product photo into a reusable mockup. By default the request returns the ready mockup; set is_async=true to receive a job URL. Costs 25 credits.

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const response = await fetch("https://api.sudomock.com/api/v1/photo-mockups", {
    method: "POST",
    headers: {
      "x-api-key": "sm_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "name": "Front view",
      "source_url": "https://example.com/product-photo.jpg"
    }),
  });

  const data = await response.json();
  console.log(data);
  ```

  ```php PHP theme={"theme":{"light":"github-light","dark":"vesper"}}
  <?php

  $payload = <<<'JSON'
  {
    "name": "Front view",
    "source_url": "https://example.com/product-photo.jpg"
  }
  JSON;

  $ch = curl_init("https://api.sudomock.com/api/v1/photo-mockups");
  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_HTTPHEADER, [
      "x-api-key: sm_your_api_key",
      "Content-Type: application/json",
  ]);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

  $response = curl_exec($ch);
  curl_close($ch);

  echo $response;
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vesper"}}
  import requests

  payload = {
      "name": "Front view",
      "source_url": "https://example.com/product-photo.jpg"
  }

  response = requests.post(
      "https://api.sudomock.com/api/v1/photo-mockups",
      headers={"x-api-key": "sm_your_api_key"},
      json=payload,
  )

  response.raise_for_status()
  print(response.json())
  ```

  ```ruby Ruby theme={"theme":{"light":"github-light","dark":"vesper"}}
  require "net/http"
  require "uri"

  uri = URI("https://api.sudomock.com/api/v1/photo-mockups")
  request = Net::HTTP::Post.new(uri)
  request["x-api-key"] = "sm_your_api_key"
  request["Content-Type"] = "application/json"

  request.body = <<~JSON
    {
      "name": "Front view",
      "source_url": "https://example.com/product-photo.jpg"
    }
  JSON

  response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    http.request(request)
  end

  puts response.body
  ```

  ```go Go theme={"theme":{"light":"github-light","dark":"vesper"}}
  package main

  import (
  	"bytes"
  	"fmt"
  	"io"
  	"net/http"
  )

  func main() {
  	payload := []byte(`{
    "name": "Front view",
    "source_url": "https://example.com/product-photo.jpg"
  }`)

  	req, err := http.NewRequest("POST", "https://api.sudomock.com/api/v1/photo-mockups", bytes.NewBuffer(payload))
  	if err != nil {
  		panic(err)
  	}
  	req.Header.Set("x-api-key", "sm_your_api_key")
  	req.Header.Set("Content-Type", "application/json")

  	res, err := http.DefaultClient.Do(req)
  	if err != nil {
  		panic(err)
  	}
  	defer res.Body.Close()

  	body, _ := io.ReadAll(res.Body)
  	fmt.Println(string(body))
  }
  ```

  ```java Java theme={"theme":{"light":"github-light","dark":"vesper"}}
  import java.net.URI;
  import java.net.http.HttpClient;
  import java.net.http.HttpRequest;
  import java.net.http.HttpResponse;

  String payload = """
  {
    "name": "Front view",
    "source_url": "https://example.com/product-photo.jpg"
  }
  """;

  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.sudomock.com/api/v1/photo-mockups"))
      .header("x-api-key", "sm_your_api_key")
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(payload))
      .build();

  HttpResponse<String> response = HttpClient.newHttpClient()
      .send(request, HttpResponse.BodyHandlers.ofString());

  System.out.println(response.body());
  ```

  ```csharp .NET theme={"theme":{"light":"github-light","dark":"vesper"}}
  using System.Net.Http;
  using System.Text;

  var payload = """
  {
    "name": "Front view",
    "source_url": "https://example.com/product-photo.jpg"
  }
  """;

  var request = new HttpRequestMessage(HttpMethod.Post, "https://api.sudomock.com/api/v1/photo-mockups");
  request.Headers.Add("x-api-key", "sm_your_api_key");
  request.Content = new StringContent(payload, Encoding.UTF8, "application/json");

  var client = new HttpClient();
  var response = await client.SendAsync(request);

  Console.WriteLine(await response.Content.ReadAsStringAsync());
  ```

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST "https://api.sudomock.com/api/v1/photo-mockups" \
    -H "x-api-key: sm_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Front view",
      "source_url": "https://example.com/product-photo.jpg"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "data": {
      "mockup_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "My mockup",
      "status": "string",
      "customizable": false,
      "created_at": "2026-01-01T00:00:00Z",
      "updated_at": "2026-01-01T00:00:00Z"
    }
  }
  ```
</ResponseExample>


## OpenAPI

````yaml openapi.json POST /api/v1/photo-mockups
openapi: 3.1.0
info:
  title: SudoMock API
  description: >-
    Product mockup API. Render PSD templates, turn product photos into reusable
    mockups, create still images and videos, personalize text with fonts, and
    manage asynchronous jobs and signed webhooks.


    Every endpoint answers failures with the same envelope, so the status codes,
    the error_code values and the retry rule are documented once at
    https://sudomock.com/docs/errors rather than repeated per operation.
  version: 1.0.0
servers:
  - url: https://api.sudomock.com
    description: Production
security: []
tags:
  - name: PSD mockups
    description: Turn a Photoshop file into a reusable mockup, then render it.
  - name: Photo mockups
    description: Turn a product photo into a reusable mockup, then render artwork onto it.
  - name: Video mockups
    description: Render a mockup as a short video.
  - name: Fonts
    description: Upload and manage the fonts available to text layers.
  - name: Background removal
    description: Isolate a subject from its background as a standalone step.
  - name: Studio
    description: Open an embedded editor session and read what the customer produced in it.
  - name: Webhook endpoints
    description: Register signed endpoints and manage their secrets.
  - name: Webhook deliveries
    description: Inspect, replay and retry what those endpoints received.
  - name: Jobs
    description: Poll queued renders and read their results.
  - name: Account
    description: Read the current account, its plan and its remaining credits.
paths:
  /api/v1/photo-mockups:
    post:
      tags:
        - Photo mockups
      summary: Create a mockup from a product photo
      description: >-
        Turns one product photo into a reusable mockup. By default the request
        returns the ready mockup; set is_async=true to receive a job URL. Costs
        25 credits.
      operationId: create_public_2d_mockup_api_v1_photo_mockups_post
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PhotoMockupCreateRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhotoMockupDetailResponse'
        '202':
          description: Async creation job accepted
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PhotoMockupCreateAcceptedResponse'
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: Node.js
          source: >-
            const response = await
            fetch("https://api.sudomock.com/api/v1/photo-mockups", {
              method: "POST",
              headers: {
                "x-api-key": "sm_your_api_key",
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                "name": "Front view",
                "source_url": "https://example.com/product-photo.jpg"
              }),
            });


            const data = await response.json();

            console.log(data);
        - lang: PHP
          source: |-
            <?php

            $payload = <<<'JSON'
            {
              "name": "Front view",
              "source_url": "https://example.com/product-photo.jpg"
            }
            JSON;

            $ch = curl_init("https://api.sudomock.com/api/v1/photo-mockups");
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                "x-api-key: sm_your_api_key",
                "Content-Type: application/json",
            ]);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);

            $response = curl_exec($ch);
            curl_close($ch);

            echo $response;
        - lang: Python
          source: |-
            import requests

            payload = {
                "name": "Front view",
                "source_url": "https://example.com/product-photo.jpg"
            }

            response = requests.post(
                "https://api.sudomock.com/api/v1/photo-mockups",
                headers={"x-api-key": "sm_your_api_key"},
                json=payload,
            )

            response.raise_for_status()
            print(response.json())
        - lang: Ruby
          source: >-
            require "net/http"

            require "uri"


            uri = URI("https://api.sudomock.com/api/v1/photo-mockups")

            request = Net::HTTP::Post.new(uri)

            request["x-api-key"] = "sm_your_api_key"

            request["Content-Type"] = "application/json"


            request.body = <<~JSON
              {
                "name": "Front view",
                "source_url": "https://example.com/product-photo.jpg"
              }
            JSON


            response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do
            |http|
              http.request(request)
            end


            puts response.body
        - lang: Go
          source: "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\tpayload := []byte(`{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/photo-mockups\", bytes.NewBuffer(payload))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\n\tres, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer res.Body.Close()\n\n\tbody, _ := io.ReadAll(res.Body)\n\tfmt.Println(string(body))\n}"
        - lang: Java
          source: |-
            import java.net.URI;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;

            String payload = """
            {
              "name": "Front view",
              "source_url": "https://example.com/product-photo.jpg"
            }
            """;

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.sudomock.com/api/v1/photo-mockups"))
                .header("x-api-key", "sm_your_api_key")
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(payload))
                .build();

            HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());

            System.out.println(response.body());
        - lang: .NET
          source: >-
            using System.Net.Http;

            using System.Text;


            var payload = """

            {
              "name": "Front view",
              "source_url": "https://example.com/product-photo.jpg"
            }

            """;


            var request = new HttpRequestMessage(HttpMethod.Post,
            "https://api.sudomock.com/api/v1/photo-mockups");

            request.Headers.Add("x-api-key", "sm_your_api_key");

            request.Content = new StringContent(payload, Encoding.UTF8,
            "application/json");


            var client = new HttpClient();

            var response = await client.SendAsync(request);


            Console.WriteLine(await response.Content.ReadAsStringAsync());
        - lang: cURL
          source: |-
            curl -X POST "https://api.sudomock.com/api/v1/photo-mockups" \
              -H "x-api-key: sm_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "name": "Front view",
                "source_url": "https://example.com/product-photo.jpg"
              }'
components:
  schemas:
    PhotoMockupCreateRequest:
      properties:
        source_url:
          anyOf:
            - type: string
            - type: 'null'
          description: Public HTTPS URL of the source image.
          examples:
            - https://example.com/product-photo.jpg
        source_base64:
          anyOf:
            - type: string
            - type: 'null'
          description: Base64-encoded source image, with or without a data URL prefix.
        name:
          anyOf:
            - type: string
              maxLength: 255
            - type: 'null'
          description: Optional display name for the mockup.
          examples:
            - Front view
        is_async:
          type: boolean
          description: >-
            If true, the mockup is QUEUED and the call returns 202 immediately
            with a job_id (poll GET /api/v1/jobs/{job_id}, or receive a webhook
            if one is configured); result_url carries the new mockup_uuid on
            success. If false (default), the create runs synchronously and
            returns the mockup.
          default: false
        print_areas:
          anyOf:
            - items:
                $ref: '#/components/schemas/PhotoMockupPrintAreaInput'
              type: array
              maxItems: 8
              minItems: 1
            - type: 'null'
          description: >-
            Optional: 1-8 convex four-point printable areas in source-image
            pixels. When provided, these areas are used verbatim and automatic
            print-area detection is skipped.
      additionalProperties: false
      type: object
      title: PhotoMockupCreateRequest
      description: Create a reusable 2D mockup from one source image.
      example:
        name: Front view
        source_url: https://example.com/product-photo.jpg
    PhotoMockupDetailResponse:
      properties:
        data:
          $ref: '#/components/schemas/PhotoMockupDetail'
        success:
          type: boolean
          const: true
          default: true
      type: object
      required:
        - data
      title: PhotoMockupDetailResponse
    PhotoMockupCreateAcceptedResponse:
      properties:
        job_id:
          type: string
        kind:
          type: string
          enum:
            - 2d_create
            - photo_mockup_create
        status:
          type: string
          enum:
            - queued
            - dispatched
            - running
            - succeeded
            - failed
            - cancelled
        status_url:
          type: string
      type: object
      required:
        - job_id
        - kind
        - status
        - status_url
      title: PhotoMockupCreateAcceptedResponse
      description: Async 2D create acknowledgement.
    PhotoMockupPrintAreaInput:
      properties:
        points:
          items:
            items:
              type: number
            type: array
          type: array
          maxItems: 4
          minItems: 4
          description: Four [x, y] points in image coordinates.
        name:
          anyOf:
            - type: string
              maxLength: 120
            - type: 'null'
          description: Optional print-area label, e.g. "Front" or "Back".
      additionalProperties: false
      type: object
      required:
        - points
      title: PhotoMockupPrintAreaInput
      description: Four image coordinates defining one printable area.
    PhotoMockupDetail:
      properties:
        mockup_id:
          type: string
          examples:
            - 893ea326-278b-480b-b130-87dd6aee06dc
        name:
          type: string
          examples:
            - Front view
        status:
          type: string
          examples:
            - ready
        customizable:
          type: boolean
        thumbnail_url:
          anyOf:
            - type: string
            - type: 'null'
        source_width:
          anyOf:
            - type: integer
            - type: 'null'
          examples:
            - 2048
        source_height:
          anyOf:
            - type: integer
            - type: 'null'
          examples:
            - 2048
        quads:
          items:
            $ref: '#/components/schemas/PhotoMockupPrintArea'
          type: array
        surfaces:
          items:
            $ref: '#/components/schemas/PhotoMockupSurface'
          type: array
        version:
          type: integer
          default: 1
        created_at:
          type: string
          format: date-time
          examples:
            - '2026-09-18T10:24:31.482913Z'
        updated_at:
          type: string
          format: date-time
          examples:
            - '2026-09-18T10:41:07.118204Z'
      type: object
      required:
        - mockup_id
        - name
        - status
        - customizable
        - created_at
        - updated_at
      title: PhotoMockupDetail
    PhotoMockupPrintArea:
      properties:
        print_area_id:
          type: string
          examples:
            - 19be48d4-c810-4420-86e3-7ec2a4d85571
        points:
          anyOf:
            - items:
                items:
                  type: number
                type: array
              type: array
            - type: 'null'
          examples:
            - - - 512
                - 640
              - - 1536
                - 640
              - - 1536
                - 1664
              - - 512
                - 1664
        name:
          anyOf:
            - type: string
            - type: 'null'
          examples:
            - Front
        sort_order:
          type: integer
          default: 0
      type: object
      required:
        - print_area_id
      title: PhotoMockupPrintArea
    PhotoMockupSurface:
      properties:
        surface_uuid:
          type: string
        points:
          anyOf:
            - items:
                items:
                  type: number
                type: array
              type: array
            - type: 'null'
        bbox:
          anyOf:
            - additionalProperties:
                type: number
              type: object
            - type: 'null'
      type: object
      required:
        - surface_uuid
      title: PhotoMockupSurface
      description: >-
        One printable product in the photo, addressed by its own id.


        Send ``surface_uuid`` as a render target to print across the whole
        product.
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key with sm_ prefix. Get your key at
        https://sudomock.com/dashboard/api-keys

````