{
  "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.\n\nEvery 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"
  },
  "paths": {
    "/api/v1/psd/upload": {
      "post": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Create a mockup from a PSD",
        "description": "Ingests a PSD file from URL, extracts layers and smart objects, generates thumbnails.",
        "operationId": "upload_psd_api_v1_psd_upload_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UploadRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Upload PSD file"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/psd/upload\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n    \"psd_name\": \"Heavyweight tee front\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n  \"psd_name\": \"Heavyweight tee front\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/psd/upload\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n    \"psd_name\": \"Heavyweight tee front\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/psd/upload\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/psd/upload\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n    \"psd_name\": \"Heavyweight tee front\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n  \"psd_name\": \"Heavyweight tee front\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/psd/upload\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n  \"psd_name\": \"Heavyweight tee front\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/psd/upload\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n  \"psd_name\": \"Heavyweight tee front\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/psd/upload\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/psd/upload\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"psd_file_url\": \"https://example.com/heavyweight-tee.psd\",\n    \"psd_name\": \"Heavyweight tee front\"\n  }'"
          }
        ]
      }
    },
    "/api/v1/renders": {
      "post": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Render a PSD mockup",
        "description": "Renders a mockup by compositing layers with user-provided images.",
        "operationId": "render_mockup_api_v1_renders_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenderRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenderResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Render PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/renders\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"position\": {\n            \"left\": 100,\n            \"top\": 100\n          },\n          \"rotate\": 0,\n          \"size\": {\n            \"height\": 600,\n            \"width\": 800\n          },\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"color\": {\n          \"blending_mode\": \"multiply\",\n          \"hex\": \"#FFFFFF\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"position\": {\n          \"left\": 100,\n          \"top\": 100\n        },\n        \"rotate\": 0,\n        \"size\": {\n          \"height\": 600,\n          \"width\": 800\n        },\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"color\": {\n        \"blending_mode\": \"multiply\",\n        \"hex\": \"#FFFFFF\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/renders\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"export_options\": {\n        \"image_format\": \"webp\",\n        \"image_size\": 1920,\n        \"quality\": 95\n    },\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n        {\n            \"asset\": {\n                \"fit\": \"fill\",\n                \"position\": {\n                    \"left\": 100,\n                    \"top\": 100\n                },\n                \"rotate\": 0,\n                \"size\": {\n                    \"height\": 600,\n                    \"width\": 800\n                },\n                \"url\": \"https://example.com/user-design.png\"\n            },\n            \"color\": {\n                \"blending_mode\": \"multiply\",\n                \"hex\": \"#FFFFFF\"\n            },\n            \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n        }\n    ]\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/renders\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/renders\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"position\": {\n            \"left\": 100,\n            \"top\": 100\n          },\n          \"rotate\": 0,\n          \"size\": {\n            \"height\": 600,\n            \"width\": 800\n          },\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"color\": {\n          \"blending_mode\": \"multiply\",\n          \"hex\": \"#FFFFFF\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"position\": {\n          \"left\": 100,\n          \"top\": 100\n        },\n        \"rotate\": 0,\n        \"size\": {\n          \"height\": 600,\n          \"width\": 800\n        },\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"color\": {\n        \"blending_mode\": \"multiply\",\n        \"hex\": \"#FFFFFF\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/renders\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"position\": {\n          \"left\": 100,\n          \"top\": 100\n        },\n        \"rotate\": 0,\n        \"size\": {\n          \"height\": 600,\n          \"width\": 800\n        },\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"color\": {\n        \"blending_mode\": \"multiply\",\n        \"hex\": \"#FFFFFF\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/renders\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"position\": {\n          \"left\": 100,\n          \"top\": 100\n        },\n        \"rotate\": 0,\n        \"size\": {\n          \"height\": 600,\n          \"width\": 800\n        },\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"color\": {\n        \"blending_mode\": \"multiply\",\n        \"hex\": \"#FFFFFF\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/renders\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/renders\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"position\": {\n            \"left\": 100,\n            \"top\": 100\n          },\n          \"rotate\": 0,\n          \"size\": {\n            \"height\": 600,\n            \"width\": 800\n          },\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"color\": {\n          \"blending_mode\": \"multiply\",\n          \"hex\": \"#FFFFFF\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }'"
          }
        ]
      }
    },
    "/api/v1/remove-background": {
      "post": {
        "tags": [
          "Background removal"
        ],
        "summary": "Remove the background from an image",
        "description": "Isolates the subject of an image onto a transparent background and returns a clean PNG cutout URL, ready to use as render artwork. Costs 25 credits per image; credits are refunded automatically if processing fails.",
        "operationId": "remove_background_api_v1_remove_background_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BackgroundRemovalRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BackgroundRemovalResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Remove background"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/remove-background\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"url\": \"https://example.com/product-photo.jpg\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"url\": \"https://example.com/product-photo.jpg\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/remove-background\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"url\": \"https://example.com/product-photo.jpg\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/remove-background\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/remove-background\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"url\": \"https://example.com/product-photo.jpg\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"url\": \"https://example.com/product-photo.jpg\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/remove-background\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/remove-background\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/remove-background\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/remove-background\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"https://example.com/product-photo.jpg\"\n  }'"
          }
        ]
      }
    },
    "/api/v1/renders/video": {
      "post": {
        "tags": [
          "Video mockups"
        ],
        "summary": "Render a video mockup",
        "description": "Animates a mockup: produces a still render from the given smart objects, then animates it. Returns 202 with a job_id to poll (GET /api/v1/jobs/{job_id}).",
        "operationId": "render_video_api_v1_renders_video_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VideoRenderRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Render video mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/renders/video\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ],\n    \"video\": {\n      \"audio\": false,\n      \"duration_seconds\": 4,\n      \"motion\": \"ambient\",\n      \"advanced_model\": null\n    },\n    \"webhook\": {\n      \"url\": \"https://example.com/hooks/render-done\"\n    }\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ],\n  \"video\": {\n    \"audio\": false,\n    \"duration_seconds\": 4,\n    \"motion\": \"ambient\",\n    \"advanced_model\": null\n  },\n  \"webhook\": {\n    \"url\": \"https://example.com/hooks/render-done\"\n  }\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/renders/video\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n        {\n            \"asset\": {\n                \"fit\": \"fill\",\n                \"url\": \"https://example.com/user-design.png\"\n            },\n            \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n        }\n    ],\n    \"video\": {\n        \"audio\": false,\n        \"duration_seconds\": 4,\n        \"motion\": \"ambient\",\n        \"advanced_model\": null\n    },\n    \"webhook\": {\n        \"url\": \"https://example.com/hooks/render-done\"\n    }\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/renders/video\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/renders/video\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ],\n    \"video\": {\n      \"audio\": false,\n      \"duration_seconds\": 4,\n      \"motion\": \"ambient\",\n      \"advanced_model\": null\n    },\n    \"webhook\": {\n      \"url\": \"https://example.com/hooks/render-done\"\n    }\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ],\n  \"video\": {\n    \"audio\": false,\n    \"duration_seconds\": 4,\n    \"motion\": \"ambient\",\n    \"advanced_model\": null\n  },\n  \"webhook\": {\n    \"url\": \"https://example.com/hooks/render-done\"\n  }\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/renders/video\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ],\n  \"video\": {\n    \"audio\": false,\n    \"duration_seconds\": 4,\n    \"motion\": \"ambient\",\n    \"advanced_model\": null\n  },\n  \"webhook\": {\n    \"url\": \"https://example.com/hooks/render-done\"\n  }\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/renders/video\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n  \"smart_objects\": [\n    {\n      \"asset\": {\n        \"fit\": \"fill\",\n        \"url\": \"https://example.com/user-design.png\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ],\n  \"video\": {\n    \"audio\": false,\n    \"duration_seconds\": 4,\n    \"motion\": \"ambient\",\n    \"advanced_model\": null\n  },\n  \"webhook\": {\n    \"url\": \"https://example.com/hooks/render-done\"\n  }\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/renders/video\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/renders/video\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"mockup_uuid\": \"123e4567-e89b-12d3-a456-426614174000\",\n    \"smart_objects\": [\n      {\n        \"asset\": {\n          \"fit\": \"fill\",\n          \"url\": \"https://example.com/user-design.png\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ],\n    \"video\": {\n      \"audio\": false,\n      \"duration_seconds\": 4,\n      \"motion\": \"ambient\",\n      \"advanced_model\": null\n    },\n    \"webhook\": {\n      \"url\": \"https://example.com/hooks/render-done\"\n    }\n  }'"
          }
        ]
      }
    },
    "/api/v1/jobs": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Retrieve a list of jobs",
        "description": "List the caller's async jobs (render, video, upload, or 2D mockup creation), newest first and keyset-paginated. Optionally filter by kind and/or mockup_uuid (e.g. one mockup's videos). Each item has the SAME shape as GET /api/v1/jobs/{job_id} plus list display fields (duration_seconds/audio/mockup_name/poster_url).",
        "operationId": "list_jobs_api_v1_jobs_get",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by job kind: video | render | upload | 2d_create | 2d_render | photo_mockup_create | photo_mockup_render. A photo-mockup kind selects both spellings of that job, and the listed jobs are spelled the way you asked. Omit for all kinds, each spelled as it was submitted."
            },
            "description": "Filter by job kind: video | render | upload | 2d_create | 2d_render | photo_mockup_create | photo_mockup_render. A photo-mockup kind selects both spellings of that job, and the listed jobs are spelled the way you asked. Omit for all kinds, each spelled as it was submitted."
          },
          {
            "name": "mockup_uuid",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by source mockup UUID (e.g. a mockup's videos). Omit for all mockups. Raw-image videos (no source mockup) are never returned by this filter."
            },
            "description": "Filter by source mockup UUID (e.g. a mockup's videos). Omit for all mockups. Raw-image videos (no source mockup) are never returned by this filter."
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 50,
              "minimum": 1,
              "description": "Max jobs per page (1-50).",
              "default": 20
            },
            "description": "Max jobs per page (1-50)."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Opaque keyset cursor from a prior page's next_cursor."
            },
            "description": "Opaque keyset cursor from a prior page's next_cursor."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/jobs\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/jobs\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/jobs\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/jobs\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/jobs\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/jobs\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/jobs\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/jobs\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/jobs/{job_id}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "summary": "Retrieve a single job",
        "description": "Poll an async render, video, upload, or 2D mockup creation job. Returns its current status and result when available.",
        "operationId": "get_job_api_v1_jobs__job_id__get",
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/jobs/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/packages/plans": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Retrieve a list of plans",
        "description": "Returns all available subscription plans with pricing and API limits",
        "operationId": "get_plans_api_v1_packages_plans_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": true,
                  "type": "object",
                  "title": "Response Get Plans Api V1 Packages Plans Get"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "List subscription plans"
          }
        },
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/packages/plans\", {\n  method: \"GET\",\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/packages/plans\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/packages/plans\",\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/packages/plans\")\nrequest = Net::HTTP::Get.new(uri)\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/packages/plans\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/packages/plans\"))\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/packages/plans\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/packages/plans\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints": {
      "post": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Create a new webhook endpoint",
        "description": "Create an endpoint. The signing secret is returned in FULL here, once.",
        "operationId": "create_webhook_endpoint_api_v1_webhook_endpoints_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointCreateRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Create webhook"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"description\": \"Production render notifications\",\n    \"event_types\": [\n      \"render.succeeded\",\n      \"render.failed\"\n    ],\n    \"url\": \"https://your-app.example.com/hooks/sudomock\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"description\": \"Production render notifications\",\n  \"event_types\": [\n    \"render.succeeded\",\n    \"render.failed\"\n  ],\n  \"url\": \"https://your-app.example.com/hooks/sudomock\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"description\": \"Production render notifications\",\n    \"event_types\": [\n        \"render.succeeded\",\n        \"render.failed\"\n    ],\n    \"url\": \"https://your-app.example.com/hooks/sudomock\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"description\": \"Production render notifications\",\n    \"event_types\": [\n      \"render.succeeded\",\n      \"render.failed\"\n    ],\n    \"url\": \"https://your-app.example.com/hooks/sudomock\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"description\": \"Production render notifications\",\n  \"event_types\": [\n    \"render.succeeded\",\n    \"render.failed\"\n  ],\n  \"url\": \"https://your-app.example.com/hooks/sudomock\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/webhook-endpoints\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"description\": \"Production render notifications\",\n  \"event_types\": [\n    \"render.succeeded\",\n    \"render.failed\"\n  ],\n  \"url\": \"https://your-app.example.com/hooks/sudomock\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"description\": \"Production render notifications\",\n  \"event_types\": [\n    \"render.succeeded\",\n    \"render.failed\"\n  ],\n  \"url\": \"https://your-app.example.com/hooks/sudomock\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/webhook-endpoints\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/webhook-endpoints\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"description\": \"Production render notifications\",\n    \"event_types\": [\n      \"render.succeeded\",\n      \"render.failed\"\n    ],\n    \"url\": \"https://your-app.example.com/hooks/sudomock\"\n  }'"
          }
        ]
      },
      "get": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Retrieve a list of webhook endpoints",
        "operationId": "list_webhook_endpoints_api_v1_webhook_endpoints_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookEndpointResponse"
                  },
                  "title": "Response List Webhook Endpoints Api V1 Webhook Endpoints Get"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "List webhooks"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/events": {
      "get": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Retrieve a list of events",
        "description": "Reverse-chron delivery log spanning every endpoint the caller owns. The response groups rows by (job_id, event_type) into events.",
        "operationId": "list_events_api_v1_webhook_endpoints_events_get",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by event type. Either spelling of a photo-mockup event matches deliveries logged under the other."
            },
            "description": "Filter by event type. Either spelling of a photo-mockup event matches deliveries logged under the other."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 100
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDeliveryResponse"
                  },
                  "title": "Response List Events Api V1 Webhook Endpoints Events Get"
                }
              }
            },
            "headers": {
              "X-Webhook-Next-Cursor": {
                "description": "Opaque cursor for the next page; absent on the last page.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "title": "List recent delivery attempts across all of the user's endpoints",
            "sidebarTitle": "List all deliveries"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/events\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/events\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/events\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/events\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints/events\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/events\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints/events\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints/events\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/overview": {
      "get": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Retrieve the delivery overview",
        "description": "Window-scoped delivery rollup spanning every endpoint the caller owns: global total/failed COUNTs, a per-day sparkline, and a per-endpoint breakdown (total/failed/last_activity). The path is 'overview', not an endpoint id.",
        "operationId": "webhook_overview_api_v1_webhook_endpoints_overview_get",
        "parameters": [
          {
            "name": "period_days",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 90,
              "minimum": 1,
              "default": 7
            }
          },
          {
            "name": "tz_offset_minutes",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "title": "Delivery overview across all of the user's endpoints",
            "sidebarTitle": "Get delivery overview"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/overview\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/overview\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/overview\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/overview\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints/overview\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/overview\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints/overview\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints/overview\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}": {
      "get": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Retrieve a single webhook endpoint",
        "operationId": "get_webhook_endpoint_api_v1_webhook_endpoints__endpoint_id__get",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get webhook"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Update an existing webhook endpoint",
        "operationId": "update_webhook_endpoint_api_v1_webhook_endpoints__endpoint_id__patch",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEndpointUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Update webhook"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"PATCH\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"description\": \"Production render notifications\",\n    \"enabled\": true\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"description\": \"Production render notifications\",\n  \"enabled\": true\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PATCH\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"description\": \"Production render notifications\",\n    \"enabled\": true\n}\n\nresponse = requests.patch(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Patch.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"description\": \"Production render notifications\",\n    \"enabled\": true\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"description\": \"Production render notifications\",\n  \"enabled\": true\n}`)\n\n\treq, err := http.NewRequest(\"PATCH\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"description\": \"Production render notifications\",\n  \"enabled\": true\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .method(\"PATCH\", HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"description\": \"Production render notifications\",\n  \"enabled\": true\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Patch, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PATCH \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"description\": \"Production render notifications\",\n    \"enabled\": true\n  }'"
          }
        ]
      },
      "delete": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Remove an existing webhook endpoint",
        "description": "Hard delete (delivery log rows cascade).",
        "operationId": "delete_webhook_endpoint_api_v1_webhook_endpoints__endpoint_id__delete",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete webhook"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Rotate the signing secret",
        "description": "Generate a new secret, returned in FULL once.",
        "operationId": "rotate_webhook_secret_api_v1_webhook_endpoints__endpoint_id__rotate_secret_post",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpointSecretResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Rotate signing secret"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\", {\n  method: \"POST\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .method(\"POST\", HttpRequest.BodyPublishers.noBody())\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/rotate-secret\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/test": {
      "post": {
        "tags": [
          "Webhook endpoints"
        ],
        "summary": "Send a test event",
        "description": "Enqueue a synthetic webhook.test event through the REAL signed delivery path.",
        "operationId": "send_test_event_api_v1_webhook_endpoints__endpoint_id__test_post",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Send test event"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\", {\n  method: \"POST\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .method(\"POST\", HttpRequest.BodyPublishers.noBody())\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/test\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/deliveries": {
      "get": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Retrieve a list of deliveries",
        "operationId": "list_deliveries_api_v1_webhook_endpoints__endpoint_id__deliveries_get",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "event_type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by event type. Either spelling of a photo-mockup event matches deliveries logged under the other."
            },
            "description": "Filter by event type. Either spelling of a photo-mockup event matches deliveries logged under the other."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 200,
              "minimum": 1,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDeliveryResponse"
                  },
                  "title": "Response List Deliveries Api V1 Webhook Endpoints  Endpoint Id  Deliveries Get"
                }
              }
            },
            "headers": {
              "X-Webhook-Next-Cursor": {
                "description": "Opaque cursor for the next page; absent on the last page.",
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "List endpoint deliveries"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}": {
      "get": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Retrieve a single delivery",
        "description": "Full single delivery row including the captured request body + headers (every attempt) and, for failed/dead attempts, the response body + headers. Fetched on demand, so the LIST endpoints stay lean and never carry these large fields.",
        "operationId": "get_delivery_detail_api_v1_webhook_endpoints__endpoint_id__deliveries__delivery_id__get",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryDetailResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get delivery"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/deliveries/{delivery_id}/replay": {
      "post": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Replay a single delivery",
        "description": "Re-send a single delivery. Replays are idempotent, so re-sending is always safe.",
        "operationId": "replay_delivery_api_v1_webhook_endpoints__endpoint_id__deliveries__delivery_id__replay_post",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "delivery_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Replay delivery"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\", {\n  method: \"POST\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .method(\"POST\", HttpRequest.BodyPublishers.noBody())\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/3fa85f64-5717-4562-b3fc-2c963f66afa6/replay\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/webhook-endpoints/{endpoint_id}/deliveries/replay-failed": {
      "post": {
        "tags": [
          "Webhook deliveries"
        ],
        "summary": "Replay all failed deliveries",
        "operationId": "replay_failed_deliveries_api_v1_webhook_endpoints__endpoint_id__deliveries_replay_failed_post",
        "parameters": [
          {
            "name": "endpoint_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Replay failed deliveries"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\", {\n  method: \"POST\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .method(\"POST\", HttpRequest.BodyPublishers.noBody())\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/webhook-endpoints/3fa85f64-5717-4562-b3fc-2c963f66afa6/deliveries/replay-failed\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/psd-mockups": {
      "get": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Retrieve a list of PSD mockups",
        "description": "List your mockups, with pagination, filtering and sorting.",
        "operationId": "list_mockups_api_v1_psd_mockups_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Number of mockups to return (1-100)",
              "default": 20
            },
            "description": "Number of mockups to return (1-100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of mockups to skip",
              "default": 0
            },
            "description": "Number of mockups to skip"
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter mockups by name (case-insensitive contains)"
            },
            "description": "Filter mockups by name (case-insensitive contains)"
          },
          {
            "name": "created_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter mockups created after this date (ISO 8601)"
            },
            "description": "Filter mockups created after this date (ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter mockups created before this date (ISO 8601)"
            },
            "description": "Filter mockups created before this date (ISO 8601)"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(name|created_at|updated_at)$",
              "description": "Field to sort by",
              "default": "created_at"
            },
            "description": "Field to sort by"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(asc|desc)$",
              "description": "Sort order",
              "default": "desc"
            },
            "description": "Sort order"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MockupListResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "List PSD mockups"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/psd-mockups\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/psd-mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/psd-mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/psd-mockups\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/psd-mockups\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/psd-mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/psd-mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/psd-mockups\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/psd-mockups/{uuid}": {
      "get": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Retrieve a single PSD mockup",
        "description": "Read one mockup. The body matches what the upload endpoint returns.",
        "operationId": "get_mockup_detail_api_v1_psd_mockups__uuid__get",
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID"
            },
            "description": "Mockup UUID"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "patch": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Update an existing PSD mockup",
        "description": "Rename a mockup, or set the colours it answers to by name.",
        "operationId": "update_mockup_api_v1_psd_mockups__uuid__patch",
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID"
            },
            "description": "Mockup UUID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MockupUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Update PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"PATCH\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Updated Mockup Name\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Updated Mockup Name\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PATCH\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Updated Mockup Name\"\n}\n\nresponse = requests.patch(\n    \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Patch.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Updated Mockup Name\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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\": \"Updated Mockup Name\"\n}`)\n\n\treq, err := http.NewRequest(\"PATCH\", \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .method(\"PATCH\", HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Patch, \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PATCH \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Updated Mockup Name\"\n  }'"
          }
        ]
      }
    },
    "/api/v1/psd-mockups/{mockup_uuid}": {
      "delete": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Remove an existing PSD mockup",
        "description": "Delete a mockup and the files that belong to it. This cannot be undone.",
        "operationId": "delete_mockup_api_v1_psd_mockups__mockup_uuid__delete",
        "parameters": [
          {
            "name": "mockup_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID to delete"
            },
            "description": "Mockup UUID to delete"
          }
        ],
        "responses": {
          "204": {
            "description": "Mockup deleted successfully"
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/psd-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/mockups": {
      "get": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Retrieve a list of PSD mockups",
        "description": "List your mockups, with pagination, filtering and sorting.",
        "operationId": "list_mockups_api_v1_mockups_get",
        "deprecated": true,
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Number of mockups to return (1-100)",
              "default": 20
            },
            "description": "Number of mockups to return (1-100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Number of mockups to skip",
              "default": 0
            },
            "description": "Number of mockups to skip"
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter mockups by name (case-insensitive contains)"
            },
            "description": "Filter mockups by name (case-insensitive contains)"
          },
          {
            "name": "created_after",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter mockups created after this date (ISO 8601)"
            },
            "description": "Filter mockups created after this date (ISO 8601)"
          },
          {
            "name": "created_before",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time",
              "description": "Filter mockups created before this date (ISO 8601)"
            },
            "description": "Filter mockups created before this date (ISO 8601)"
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(name|created_at|updated_at)$",
              "description": "Field to sort by",
              "default": "created_at"
            },
            "description": "Field to sort by"
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(asc|desc)$",
              "description": "Sort order",
              "default": "desc"
            },
            "description": "Sort order"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MockupListResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "List PSD mockups"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/mockups\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/mockups\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/mockups\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/mockups\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/mockups/{uuid}": {
      "get": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Retrieve a single PSD mockup",
        "description": "Read one mockup. The body matches what the upload endpoint returns.",
        "operationId": "get_mockup_detail_api_v1_mockups__uuid__get",
        "deprecated": true,
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID"
            },
            "description": "Mockup UUID"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      },
      "patch": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Update an existing PSD mockup",
        "description": "Rename a mockup, or set the colours it answers to by name.",
        "operationId": "update_mockup_api_v1_mockups__uuid__patch",
        "deprecated": true,
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID"
            },
            "description": "Mockup UUID"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MockupUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Update PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"PATCH\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Updated Mockup Name\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Updated Mockup Name\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PATCH\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Updated Mockup Name\"\n}\n\nresponse = requests.patch(\n    \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Patch.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Updated Mockup Name\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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\": \"Updated Mockup Name\"\n}`)\n\n\treq, err := http.NewRequest(\"PATCH\", \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .method(\"PATCH\", HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Patch, \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PATCH \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Updated Mockup Name\"\n  }'"
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/mockups/{mockup_uuid}": {
      "delete": {
        "tags": [
          "PSD mockups"
        ],
        "summary": "Remove an existing PSD mockup",
        "description": "Delete a mockup and the files that belong to it. This cannot be undone.",
        "operationId": "delete_mockup_api_v1_mockups__mockup_uuid__delete",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 36,
              "description": "Mockup UUID to delete"
            },
            "description": "Mockup UUID to delete"
          }
        ],
        "responses": {
          "204": {
            "description": "Mockup deleted successfully"
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete PSD mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/fonts": {
      "get": {
        "tags": [
          "Fonts"
        ],
        "summary": "Retrieve a list of fonts",
        "description": "List available fonts for text layers: the shared system catalog plus your own uploaded fonts. Supports search, category filtering, and pagination.",
        "operationId": "list_fonts_api_v1_fonts_get",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "description": "Page number (1-based)",
              "default": 1
            },
            "description": "Page number (1-based)"
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Results per page (1-100)",
              "default": 50
            },
            "description": "Results per page (1-100)"
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by category, e.g. 'serif'"
            },
            "description": "Filter by category, e.g. 'serif'"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "description": "Filter by family name (case-insensitive contains)"
            },
            "description": "Filter by family name (case-insensitive contains)"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "pattern": "^(all|system|custom)$",
              "description": "Which fonts to return: 'all' (system + yours), 'system', or 'custom' (yours only)",
              "default": "all"
            },
            "description": "Which fonts to return: 'all' (system + yours), 'system', or 'custom' (yours only)"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FontListResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/fonts\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/fonts\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/fonts\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/fonts\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/fonts\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/fonts\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/fonts\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/fonts\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "post": {
        "tags": [
          "Fonts"
        ],
        "summary": "Create a new font",
        "description": "Upload a custom TTF or OTF font (Pro plan and above). Send either a multipart 'file' or a JSON body with a public 'url'. The font is validated and security-checked before it is stored.",
        "operationId": "upload_font_api_v1_fonts_post",
        "responses": {
          "201": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FontResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Upload custom font"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "file",
                  "license_confirmed"
                ],
                "properties": {
                  "file": {
                    "type": "string",
                    "format": "binary"
                  },
                  "license_confirmed": {
                    "type": "boolean"
                  }
                }
              }
            },
            "application/json": {
              "schema": {
                "description": "JSON body for POST /api/v1/fonts when uploading a font by URL. The\nalternative is a multipart 'file' upload. Send one or the other.",
                "example": {
                  "url": "https://example.com/fonts/MyBrand-Bold.ttf"
                },
                "properties": {
                  "url": {
                    "description": "Public URL of a TTF or OTF font file to fetch",
                    "maxLength": 2048,
                    "minLength": 1,
                    "title": "Url",
                    "type": "string"
                  },
                  "license_confirmed": {
                    "default": false,
                    "description": "Confirmation that you have the right to use and embed this font. Required.",
                    "title": "License Confirmed",
                    "type": "boolean"
                  }
                },
                "required": [
                  "url"
                ],
                "title": "FontUploadRequest",
                "type": "object"
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/fonts\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/fonts\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/fonts\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/fonts\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/fonts\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/fonts\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/fonts\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/fonts\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"url\": \"https://example.com/fonts/MyBrand-Bold.ttf\"\n  }'"
          }
        ]
      }
    },
    "/api/v1/fonts/{uuid}": {
      "get": {
        "tags": [
          "Fonts"
        ],
        "summary": "Retrieve a single font",
        "description": "Fetch a single font by id: a system font, or one of your own uploads.",
        "operationId": "get_font_api_v1_fonts__uuid__get",
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Font id"
            },
            "description": "Font id"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FontResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get font"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "delete": {
        "tags": [
          "Fonts"
        ],
        "summary": "Remove an existing font",
        "description": "Delete one of your own uploaded fonts. System fonts cannot be deleted.",
        "operationId": "delete_font_api_v1_fonts__uuid__delete",
        "parameters": [
          {
            "name": "uuid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Font id"
            },
            "description": "Font id"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete custom font"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/fonts/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/me": {
      "get": {
        "tags": [
          "Account"
        ],
        "summary": "Retrieve the current account",
        "description": "Returns account details, subscription info, usage statistics, and API key metadata for the authenticated user. Requires x-api-key header authentication.",
        "operationId": "get_current_user_info_api_v1_me_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MeResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get account"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/me\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/me\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/me\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/me\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/me\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/me\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/me\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/me\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/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"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Create photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/photo-mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/photo-mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/photo-mockups\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }'"
          }
        ]
      },
      "get": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Retrieve a list of photo mockups",
        "description": "Returns a paginated list of the user's photo mockups with print area summaries. Each mockup includes its status, thumbnail, dimensions, and print area names/bboxes. Ordered by creation date (newest first).",
        "operationId": "list_2d_mockups_api_v1_photo_mockups_get",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Items per page (max 100)",
              "default": 20
            },
            "description": "Items per page (max 100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Pagination offset",
              "default": 0
            },
            "description": "Pagination offset"
          },
          {
            "name": "customizable_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Return only mockups ready for customization",
              "default": false
            },
            "description": "Return only mockups ready for customization"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupList"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/photo-mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/photo-mockups\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/photo-mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/photo-mockups\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/photo-mockups/{mockup_id}/print-areas": {
      "put": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Replace the print areas of a photo mockup",
        "description": "Replaces a ready photo mockup's printable areas in the supplied order. Each area must be a convex four-point shape within the source image.",
        "operationId": "replace_public_2d_print_areas_api_v1_photo_mockups__mockup_id__print_areas_put",
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhotoMockupPrintAreasUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Replace print areas"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\", {\n  method: \"PUT\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PUT\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"print_areas\": [\n        {\n            \"points\": [\n                [\n                    200,\n                    150\n                ],\n                [\n                    600,\n                    150\n                ],\n                [\n                    620,\n                    550\n                ],\n                [\n                    180,\n                    550\n                ]\n            ]\n        }\n    ]\n}\n\nresponse = requests.put(\n    \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\")\nrequest = Net::HTTP::Put.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}`)\n\n\treq, err := http.NewRequest(\"PUT\", \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .PUT(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Put, \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PUT \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }'"
          }
        ]
      }
    },
    "/api/v1/photo-mockups/{mockup_id}": {
      "get": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Retrieve a single photo mockup",
        "description": "Returns mockup metadata and print-area summaries. Use the mockup_id with POST /api/v1/photo-mockups/{mockup_id}/render to render artwork.",
        "operationId": "get_2d_mockup_public_api_v1_photo_mockups__mockup_id__get",
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupDetailResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "patch": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Update an existing photo mockup",
        "description": "Rename a mockup and/or set the colours it answers to by name. A render may then send a name where it would send a hex code.",
        "operationId": "update_2d_mockup_api_v1_photo_mockups__mockup_id__patch",
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MockupUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupUpdateResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Update photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"PATCH\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Updated Mockup Name\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Updated Mockup Name\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PATCH\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Updated Mockup Name\"\n}\n\nresponse = requests.patch(\n    \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Patch.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Updated Mockup Name\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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\": \"Updated Mockup Name\"\n}`)\n\n\treq, err := http.NewRequest(\"PATCH\", \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .method(\"PATCH\", HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Patch, \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PATCH \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Updated Mockup Name\"\n  }'"
          }
        ]
      },
      "delete": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Remove an existing photo mockup",
        "description": "Permanently deletes the mockup and its print areas. This action cannot be undone.",
        "operationId": "delete_2d_mockup_api_v1_photo_mockups__mockup_id__delete",
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupDeleteResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      }
    },
    "/api/v1/photo-mockups/{mockup_id}/render": {
      "post": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Render a photo mockup",
        "description": "Renders artwork onto a previously created photo mockup identified by the path mockup_id. Artwork can target a saved print area or a whole product surface, and a product offers both. The mockup must be in 'ready' status. Costs 5 credits. Returns CDN URL(s) of the rendered image.",
        "operationId": "render_2d_mockup_public_api_v1_photo_mockups__mockup_id__render_post",
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhotoMockupRender"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupRenderResponse"
                }
              }
            }
          },
          "202": {
            "description": "Render queued (is_async=true): returns a job envelope with job_id + status_url to poll (or a webhook on completion)."
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Render photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"export_options\": {\n        \"image_format\": \"webp\",\n        \"image_size\": 1920,\n        \"quality\": 95\n    },\n    \"print_areas\": [\n        {\n            \"adjustments\": {\n                \"blend_mode\": \"multiply\",\n                \"opacity\": 90\n            },\n            \"artwork_url\": \"https://example.com/design.png\",\n            \"placement\": {\n                \"fit\": \"fit\",\n                \"position\": \"center\"\n            },\n            \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n        }\n    ]\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/photo-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }'"
          }
        ]
      }
    },
    "/api/v1/sudoai/2d-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_sudoai_2d_mockups_post",
        "deprecated": true,
        "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"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Create photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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/sudoai/2d-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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Front view\",\n  \"source_url\": \"https://example.com/product-photo.jpg\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Front view\",\n    \"source_url\": \"https://example.com/product-photo.jpg\"\n  }'"
          }
        ],
        "x-hidden": true
      },
      "get": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Retrieve a list of photo mockups",
        "description": "Returns a paginated list of the user's photo mockups with print area summaries. Each mockup includes its status, thumbnail, dimensions, and print area names/bboxes. Ordered by creation date (newest first).",
        "operationId": "list_2d_mockups_api_v1_sudoai_2d_mockups_get",
        "deprecated": true,
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "description": "Items per page (max 100)",
              "default": 20
            },
            "description": "Items per page (max 100)"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 0,
              "description": "Pagination offset",
              "default": 0
            },
            "description": "Pagination offset"
          },
          {
            "name": "customizable_only",
            "in": "query",
            "required": false,
            "schema": {
              "type": "boolean",
              "description": "Return only mockups ready for customization",
              "default": false
            },
            "description": "Return only mockups ready for customization"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupList"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/sudoai/2d-mockups\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/sudoai/2d-mockups/{mockup_id}/print-areas": {
      "put": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Replace the print areas of a photo mockup",
        "description": "Replaces a ready photo mockup's printable areas in the supplied order. Each area must be a convex four-point shape within the source image.",
        "operationId": "replace_public_2d_print_areas_api_v1_sudoai_2d_mockups__mockup_id__print_areas_put",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhotoMockupPrintAreasUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Replace print areas"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\", {\n  method: \"PUT\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PUT\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"print_areas\": [\n        {\n            \"points\": [\n                [\n                    200,\n                    150\n                ],\n                [\n                    600,\n                    150\n                ],\n                [\n                    620,\n                    550\n                ],\n                [\n                    180,\n                    550\n                ]\n            ]\n        }\n    ]\n}\n\nresponse = requests.put(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\")\nrequest = Net::HTTP::Put.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}`)\n\n\treq, err := http.NewRequest(\"PUT\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .PUT(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"print_areas\": [\n    {\n      \"points\": [\n        [\n          200,\n          150\n        ],\n        [\n          600,\n          150\n        ],\n        [\n          620,\n          550\n        ],\n        [\n          180,\n          550\n        ]\n      ]\n    }\n  ]\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Put, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PUT \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/print-areas\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"print_areas\": [\n      {\n        \"points\": [\n          [\n            200,\n            150\n          ],\n          [\n            600,\n            150\n          ],\n          [\n            620,\n            550\n          ],\n          [\n            180,\n            550\n          ]\n        ]\n      }\n    ]\n  }'"
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/sudoai/2d-mockups/{mockup_id}": {
      "get": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Retrieve a single photo mockup",
        "description": "Returns mockup metadata and print-area summaries. Use the mockup_id with POST /api/v1/photo-mockups/{mockup_id}/render to render artwork.",
        "operationId": "get_2d_mockup_public_api_v1_sudoai_2d_mockups__mockup_id__get",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupDetailResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Get photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      },
      "patch": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Update an existing photo mockup",
        "description": "Rename a mockup and/or set the colours it answers to by name. A render may then send a name where it would send a hex code.",
        "operationId": "update_2d_mockup_api_v1_sudoai_2d_mockups__mockup_id__patch",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MockupUpdateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupUpdateResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Update photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"PATCH\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"name\": \"Updated Mockup Name\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"name\": \"Updated Mockup Name\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PATCH\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"name\": \"Updated Mockup Name\"\n}\n\nresponse = requests.patch(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Patch.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"name\": \"Updated Mockup Name\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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\": \"Updated Mockup Name\"\n}`)\n\n\treq, err := http.NewRequest(\"PATCH\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .method(\"PATCH\", HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"name\": \"Updated Mockup Name\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Patch, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PATCH \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"name\": \"Updated Mockup Name\"\n  }'"
          }
        ],
        "x-hidden": true
      },
      "delete": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Remove an existing photo mockup",
        "description": "Permanently deletes the mockup and its print areas. This action cannot be undone.",
        "operationId": "delete_2d_mockup_api_v1_sudoai_2d_mockups__mockup_id__delete",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupDeleteResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Delete photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", {\n  method: \"DELETE\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"DELETE\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.delete(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\")\nrequest = Net::HTTP::Delete.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"DELETE\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .DELETE()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Delete, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X DELETE \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/sudoai/2d-mockups/{mockup_id}/render": {
      "post": {
        "tags": [
          "Photo mockups"
        ],
        "summary": "Render a photo mockup",
        "description": "Renders artwork onto a previously created photo mockup identified by the path mockup_id. Artwork can target a saved print area or a whole product surface, and a product offers both. The mockup must be in 'ready' status. Costs 5 credits. Returns CDN URL(s) of the rendered image.",
        "operationId": "render_2d_mockup_public_api_v1_sudoai_2d_mockups__mockup_id__render_post",
        "deprecated": true,
        "parameters": [
          {
            "name": "mockup_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhotoMockupRender"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhotoMockupRenderResponse"
                }
              }
            }
          },
          "202": {
            "description": "Render queued (is_async=true): returns a job envelope with job_id + status_url to poll (or a webhook on completion)."
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Render photo mockup"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"export_options\": {\n        \"image_format\": \"webp\",\n        \"image_size\": 1920,\n        \"quality\": 95\n    },\n    \"print_areas\": [\n        {\n            \"adjustments\": {\n                \"blend_mode\": \"multiply\",\n                \"opacity\": 90\n            },\n            \"artwork_url\": \"https://example.com/design.png\",\n            \"placement\": {\n                \"fit\": \"fit\",\n                \"position\": \"center\"\n            },\n            \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n        }\n    ]\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"export_options\": {\n    \"image_format\": \"webp\",\n    \"image_size\": 1920,\n    \"quality\": 95\n  },\n  \"print_areas\": [\n    {\n      \"adjustments\": {\n        \"blend_mode\": \"multiply\",\n        \"opacity\": 90\n      },\n      \"artwork_url\": \"https://example.com/design.png\",\n      \"placement\": {\n        \"fit\": \"fit\",\n        \"position\": \"center\"\n      },\n      \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n    }\n  ]\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/sudoai/2d-mockups/3fa85f64-5717-4562-b3fc-2c963f66afa6/render\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"export_options\": {\n      \"image_format\": \"webp\",\n      \"image_size\": 1920,\n      \"quality\": 95\n    },\n    \"print_areas\": [\n      {\n        \"adjustments\": {\n          \"blend_mode\": \"multiply\",\n          \"opacity\": 90\n        },\n        \"artwork_url\": \"https://example.com/design.png\",\n        \"placement\": {\n          \"fit\": \"fit\",\n          \"position\": \"center\"\n        },\n        \"uuid\": \"223e4567-e89b-12d3-a456-426614174001\"\n      }\n    ]\n  }'"
          }
        ],
        "x-hidden": true
      }
    },
    "/api/v1/studio/create-session": {
      "post": {
        "tags": [
          "Studio"
        ],
        "summary": "Create a new Studio session",
        "description": "Generates an opaque session token for the Studio iframe. Requires x-api-key header (WooCommerce, custom) or Shopify App Proxy HMAC. No unauthenticated access. API key never leaves the server.",
        "operationId": "create_studio_session_api_v1_studio_create_session_post",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSessionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSessionResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Create Studio session"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/studio/create-session\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"allowed_origin\": \"https://your-store.example.com\",\n    \"mockup_type\": \"psd\",\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"product_id\": \"8342019283\",\n    \"session_kind\": \"customize\",\n    \"variant_id\": \"44912837465\"\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"allowed_origin\": \"https://your-store.example.com\",\n  \"mockup_type\": \"psd\",\n  \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n  \"product_id\": \"8342019283\",\n  \"session_kind\": \"customize\",\n  \"variant_id\": \"44912837465\"\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/studio/create-session\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"allowed_origin\": \"https://your-store.example.com\",\n    \"mockup_type\": \"psd\",\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"product_id\": \"8342019283\",\n    \"session_kind\": \"customize\",\n    \"variant_id\": \"44912837465\"\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/studio/create-session\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/studio/create-session\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"allowed_origin\": \"https://your-store.example.com\",\n    \"mockup_type\": \"psd\",\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"product_id\": \"8342019283\",\n    \"session_kind\": \"customize\",\n    \"variant_id\": \"44912837465\"\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"allowed_origin\": \"https://your-store.example.com\",\n  \"mockup_type\": \"psd\",\n  \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n  \"product_id\": \"8342019283\",\n  \"session_kind\": \"customize\",\n  \"variant_id\": \"44912837465\"\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/studio/create-session\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"allowed_origin\": \"https://your-store.example.com\",\n  \"mockup_type\": \"psd\",\n  \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n  \"product_id\": \"8342019283\",\n  \"session_kind\": \"customize\",\n  \"variant_id\": \"44912837465\"\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/studio/create-session\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"allowed_origin\": \"https://your-store.example.com\",\n  \"mockup_type\": \"psd\",\n  \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n  \"product_id\": \"8342019283\",\n  \"session_kind\": \"customize\",\n  \"variant_id\": \"44912837465\"\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/studio/create-session\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/studio/create-session\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"allowed_origin\": \"https://your-store.example.com\",\n    \"mockup_type\": \"psd\",\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"product_id\": \"8342019283\",\n    \"session_kind\": \"customize\",\n    \"variant_id\": \"44912837465\"\n  }'"
          }
        ]
      }
    },
    "/api/v1/studio/config": {
      "get": {
        "tags": [
          "Studio"
        ],
        "summary": "Retrieve the Studio config",
        "description": "Returns the API key's complete effective Studio configuration. Requires the x-api-key header.",
        "operationId": "get_studio_config_api_v1_studio_config_get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioConfigResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/studio/config\", {\n  method: \"GET\",\n  headers: { \"x-api-key\": \"sm_your_api_key\" },\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/studio/config\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"GET\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n]);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\nresponse = requests.get(\n    \"https://api.sudomock.com/api/v1/studio/config\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/studio/config\")\nrequest = Net::HTTP::Get.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs response.body"
          },
          {
            "lang": "Go",
            "source": "package main\n\nimport (\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\treq, err := http.NewRequest(\"GET\", \"https://api.sudomock.com/api/v1/studio/config\", nil)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treq.Header.Set(\"x-api-key\", \"sm_your_api_key\")\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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/studio/config\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .GET()\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar request = new HttpRequestMessage(HttpMethod.Get, \"https://api.sudomock.com/api/v1/studio/config\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X GET \"https://api.sudomock.com/api/v1/studio/config\" \\\n  -H \"x-api-key: sm_your_api_key\""
          }
        ]
      },
      "put": {
        "tags": [
          "Studio"
        ],
        "summary": "Update the Studio config",
        "description": "Merchant updates Studio branding/features. Requires x-api-key header. Header controls may all be turned off, showClose included; when no visible control remains the header is not shown at all, and closing the editor becomes the host page's responsibility. This is accepted on purpose and is not rejected.",
        "operationId": "update_studio_config_api_v1_studio_config_put",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateStudioConfigRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioConfigResponse"
                }
              }
            }
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/studio/config\", {\n  method: \"PUT\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"config\": {\n      \"accentColor\": \"#FF5733\",\n      \"theme\": \"dark\"\n    },\n    \"config_version\": 3\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"config\": {\n    \"accentColor\": \"#FF5733\",\n    \"theme\": \"dark\"\n  },\n  \"config_version\": 3\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/studio/config\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"PUT\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"config\": {\n        \"accentColor\": \"#FF5733\",\n        \"theme\": \"dark\"\n    },\n    \"config_version\": 3\n}\n\nresponse = requests.put(\n    \"https://api.sudomock.com/api/v1/studio/config\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/studio/config\")\nrequest = Net::HTTP::Put.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"config\": {\n      \"accentColor\": \"#FF5733\",\n      \"theme\": \"dark\"\n    },\n    \"config_version\": 3\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"config\": {\n    \"accentColor\": \"#FF5733\",\n    \"theme\": \"dark\"\n  },\n  \"config_version\": 3\n}`)\n\n\treq, err := http.NewRequest(\"PUT\", \"https://api.sudomock.com/api/v1/studio/config\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"config\": {\n    \"accentColor\": \"#FF5733\",\n    \"theme\": \"dark\"\n  },\n  \"config_version\": 3\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/studio/config\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .PUT(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"config\": {\n    \"accentColor\": \"#FF5733\",\n    \"theme\": \"dark\"\n  },\n  \"config_version\": 3\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Put, \"https://api.sudomock.com/api/v1/studio/config\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X PUT \"https://api.sudomock.com/api/v1/studio/config\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"config\": {\n      \"accentColor\": \"#FF5733\",\n      \"theme\": \"dark\"\n    },\n    \"config_version\": 3\n  }'"
          }
        ]
      }
    },
    "/api/v1/studio/actions/consume": {
      "post": {
        "tags": [
          "Studio"
        ],
        "summary": "Consume a Studio action",
        "description": "Server-only exactly-once confirmation of a Studio action against its bound successful render.",
        "operationId": "consume_action_api_v1_studio_actions_consume_post",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudioActionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StudioActionResponse"
                }
              }
            }
          }
        },
        "x-mint": {
          "metadata": {
            "sidebarTitle": "Consume Studio action"
          }
        },
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "x-codeSamples": [
          {
            "lang": "Node.js",
            "source": "const response = await fetch(\"https://api.sudomock.com/api/v1/studio/actions/consume\", {\n  method: \"POST\",\n  headers: {\n    \"x-api-key\": \"sm_your_api_key\",\n    \"Content-Type\": \"application/json\",\n  },\n  body: JSON.stringify({\n    \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n    \"payload\": {\n      \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n      \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n    },\n    \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n    \"type\": \"studio.mockup-saved\",\n    \"version\": 1\n  }),\n});\n\nconst data = await response.json();\nconsole.log(data);"
          },
          {
            "lang": "PHP",
            "source": "<?php\n\n$payload = <<<'JSON'\n{\n  \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n  \"payload\": {\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n  },\n  \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n  \"type\": \"studio.mockup-saved\",\n  \"version\": 1\n}\nJSON;\n\n$ch = curl_init(\"https://api.sudomock.com/api/v1/studio/actions/consume\");\ncurl_setopt($ch, CURLOPT_CUSTOMREQUEST, \"POST\");\ncurl_setopt($ch, CURLOPT_RETURNTRANSFER, true);\ncurl_setopt($ch, CURLOPT_HTTPHEADER, [\n    \"x-api-key: sm_your_api_key\",\n    \"Content-Type: application/json\",\n]);\ncurl_setopt($ch, CURLOPT_POSTFIELDS, $payload);\n\n$response = curl_exec($ch);\ncurl_close($ch);\n\necho $response;"
          },
          {
            "lang": "Python",
            "source": "import requests\n\npayload = {\n    \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n    \"payload\": {\n        \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n        \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n    },\n    \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n    \"type\": \"studio.mockup-saved\",\n    \"version\": 1\n}\n\nresponse = requests.post(\n    \"https://api.sudomock.com/api/v1/studio/actions/consume\",\n    headers={\"x-api-key\": \"sm_your_api_key\"},\n    json=payload,\n)\n\nresponse.raise_for_status()\nprint(response.json())"
          },
          {
            "lang": "Ruby",
            "source": "require \"net/http\"\nrequire \"uri\"\n\nuri = URI(\"https://api.sudomock.com/api/v1/studio/actions/consume\")\nrequest = Net::HTTP::Post.new(uri)\nrequest[\"x-api-key\"] = \"sm_your_api_key\"\nrequest[\"Content-Type\"] = \"application/json\"\n\nrequest.body = <<~JSON\n  {\n    \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n    \"payload\": {\n      \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n      \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n    },\n    \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n    \"type\": \"studio.mockup-saved\",\n    \"version\": 1\n  }\nJSON\n\nresponse = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|\n  http.request(request)\nend\n\nputs 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  \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n  \"payload\": {\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n  },\n  \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n  \"type\": \"studio.mockup-saved\",\n  \"version\": 1\n}`)\n\n\treq, err := http.NewRequest(\"POST\", \"https://api.sudomock.com/api/v1/studio/actions/consume\", 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;\nimport java.net.http.HttpClient;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nString payload = \"\"\"\n{\n  \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n  \"payload\": {\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n  },\n  \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n  \"type\": \"studio.mockup-saved\",\n  \"version\": 1\n}\n\"\"\";\n\nHttpRequest request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https://api.sudomock.com/api/v1/studio/actions/consume\"))\n    .header(\"x-api-key\", \"sm_your_api_key\")\n    .header(\"Content-Type\", \"application/json\")\n    .POST(HttpRequest.BodyPublishers.ofString(payload))\n    .build();\n\nHttpResponse<String> response = HttpClient.newHttpClient()\n    .send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println(response.body());"
          },
          {
            "lang": ".NET",
            "source": "using System.Net.Http;\nusing System.Text;\n\nvar payload = \"\"\"\n{\n  \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n  \"payload\": {\n    \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n    \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n  },\n  \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n  \"type\": \"studio.mockup-saved\",\n  \"version\": 1\n}\n\"\"\";\n\nvar request = new HttpRequestMessage(HttpMethod.Post, \"https://api.sudomock.com/api/v1/studio/actions/consume\");\nrequest.Headers.Add(\"x-api-key\", \"sm_your_api_key\");\nrequest.Content = new StringContent(payload, Encoding.UTF8, \"application/json\");\n\nvar client = new HttpClient();\nvar response = await client.SendAsync(request);\n\nConsole.WriteLine(await response.Content.ReadAsStringAsync());"
          },
          {
            "lang": "cURL",
            "source": "curl -X POST \"https://api.sudomock.com/api/v1/studio/actions/consume\" \\\n  -H \"x-api-key: sm_your_api_key\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"message_session_id\": \"7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52\",\n    \"payload\": {\n      \"mockup_uuid\": \"c315f78f-d2c7-4541-b240-a9372842de94\",\n      \"render_uuid\": \"9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354\"\n    },\n    \"request_id\": \"0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33\",\n    \"type\": \"studio.mockup-saved\",\n    \"version\": 1\n  }'"
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "AdjustmentLayers": {
        "properties": {
          "brightness": {
            "type": "integer",
            "maximum": 150.0,
            "minimum": -150.0,
            "description": "Brightness adjustment (-150 to 150). 0=no change.",
            "default": 0
          },
          "contrast": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "description": "Contrast adjustment (-100 to 100). 0=no change.",
            "default": 0
          },
          "opacity": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "description": "Artwork opacity (0=fully transparent, 100=fully opaque). Default 100.",
            "default": 100
          },
          "saturation": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "description": "Saturation adjustment (-100 to 100). 0=no change, -100=grayscale.",
            "default": 0
          },
          "vibrance": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "description": "Vibrance adjustment (-100 to 100). Similar to saturation but preserves skin tones.",
            "default": 0
          },
          "blur": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "description": "Gaussian blur amount (0=sharp, 100=max blur). Useful for background effects.",
            "default": 0
          }
        },
        "type": "object",
        "title": "AdjustmentLayers",
        "description": "Image adjustment parameters applied to the user's artwork before blending into the mockup.\nApplied after fit transformation, does not affect PSD-level adjustments."
      },
      "AssetInput": {
        "properties": {
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL to the user's image (HTTP/HTTPS or data: URL). Either url or base64 must be provided. Server downloads the image, adding network latency.",
            "examples": [
              "https://example.com/user-design.png"
            ]
          },
          "base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Raw base64-encoded image bytes (no data: prefix). RECOMMENDED for best performance: eliminates server-side download latency (50-500ms faster than URL). Either url or base64 must be provided."
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^image/(png|jpeg|webp|gif)$"
              },
              {
                "type": "null"
              }
            ],
            "description": "MIME type when using base64 field. Supported: image/png, image/jpeg, image/webp, image/gif. Defaults to image/png if omitted.",
            "examples": [
              "image/png"
            ]
          },
          "fit": {
            "type": "string",
            "enum": [
              "fill",
              "fit",
              "crop"
            ],
            "description": "How the artwork meets the smart object area. 'fit' scales it until it fits inside, keeping proportions, which can leave empty space. 'fill' stretches it to the bounds and does not keep its proportions. 'crop' covers the area and cuts the overflow, keeping proportions. 'contain' and 'cover' are the older names for 'fit' and 'crop' and are still accepted. Defaults to 'fit': a caller who says nothing is not asking to have their artwork distorted, and a silently stretched design is a defect the caller cannot see.",
            "default": "fit"
          },
          "size": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AssetSize"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom size override in pixels. Width and height are both optional and each must be at least 1 pixel."
          },
          "position": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AssetPosition"
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom position override (top/left in pixels). The top-left corner of the size box, which stays axis-aligned: rotate turns the artwork inside it, never the box."
          },
          "rotate": {
            "type": "number",
            "maximum": 360.0,
            "minimum": -360.0,
            "description": "Rotation angle in degrees (clockwise positive). Applied to the artwork before it is fitted, so the turned artwork, corners included, is what fit places inside the still axis-aligned size box at position.",
            "default": 0,
            "examples": [
              15
            ]
          },
          "flip_horizontal": {
            "type": "boolean",
            "description": "Flip artwork horizontally (left-right mirror)",
            "default": false
          },
          "flip_vertical": {
            "type": "boolean",
            "description": "Flip artwork vertically (top-bottom mirror)",
            "default": false
          },
          "remove_background": {
            "type": "boolean",
            "description": "Remove the image background before placing the artwork; the subject is isolated onto a clean transparent cutout. Adds 25 credits per artwork to the render cost.",
            "default": false
          }
        },
        "type": "object",
        "title": "AssetInput",
        "description": "The image to place into a smart object, and how it should sit there.\n\nImage source priority: base64 > url (including data: URLs)\n- base64: Raw base64 string (no data: prefix). Most efficient for inline images.\n- url: HTTP/HTTPS URL or data:image/...;base64,... URL.",
        "example": {
          "fit": "fill",
          "flip_horizontal": false,
          "flip_vertical": false,
          "position": {
            "left": 20,
            "top": 10
          },
          "rotate": 15,
          "size": {
            "height": 600,
            "width": 800
          },
          "url": "https://example.com/user-design.png"
        }
      },
      "AssetPosition": {
        "properties": {
          "top": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Top offset in pixels",
            "examples": [
              100
            ]
          },
          "left": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Left offset in pixels",
            "examples": [
              100
            ]
          }
        },
        "type": "object",
        "title": "AssetPosition",
        "description": "Where the artwork sits inside the smart object.\n\nFractional pixels are accepted, for the same reason as AssetSize."
      },
      "AssetSize": {
        "properties": {
          "width": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom width in pixels",
            "examples": [
              800
            ]
          },
          "height": {
            "anyOf": [
              {
                "type": "number",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Custom height in pixels",
            "examples": [
              600
            ]
          }
        },
        "type": "object",
        "title": "AssetSize",
        "description": "How large the artwork is drawn inside the smart object.\n\nFractional pixels are accepted. A canvas editor places by dragging and\nscales by ratio, so the exact placement a seller sees is continuous; asking\nthem to round it first is asking them to send a placement that is not the\none on their screen. The renderer already carries these through the\nembedded-to-bbox transform as floats and rounds once at the end, which is\nstrictly more accurate than rounding before the transform."
      },
      "BackgroundRemovalData": {
        "properties": {
          "url": {
            "type": "string",
            "description": "URL of the transparent-PNG cutout"
          },
          "width": {
            "type": "integer",
            "description": "Cutout width in pixels"
          },
          "height": {
            "type": "integer",
            "description": "Cutout height in pixels"
          },
          "credits_charged": {
            "type": "integer",
            "description": "Credits charged for this operation"
          }
        },
        "type": "object",
        "required": [
          "url",
          "width",
          "height",
          "credits_charged"
        ],
        "title": "BackgroundRemovalData",
        "description": "Result payload for POST /api/v1/remove-background."
      },
      "BackgroundRemovalRequest": {
        "properties": {
          "url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL of the image to process (HTTP/HTTPS). Either url or base64 must be provided."
          },
          "base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Raw base64-encoded image bytes (no data: prefix). Either url or base64 must be provided."
          },
          "content_type": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^image/(png|jpeg|webp|gif)$"
              },
              {
                "type": "null"
              }
            ],
            "description": "MIME type when using base64 field. Defaults to image/png if omitted."
          },
          "idempotency_key": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "Retry-stable request identifier. Required in both this field and the Idempotency-Key header for Studio calls."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "BackgroundRemovalRequest",
        "description": "Body for POST /api/v1/remove-background.\n\nImage source priority mirrors AssetInput: base64 > url.",
        "example": {
          "url": "https://example.com/product-photo.jpg"
        }
      },
      "BackgroundRemovalResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/BackgroundRemovalData"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "BackgroundRemovalResponse",
        "description": "The cutout image and where to fetch it."
      },
      "ColorOverlay": {
        "properties": {
          "hex": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Hex color code (e.g., '#FF5733'). Send this or 'label'.",
            "examples": [
              "#FF5733"
            ]
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 32,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "One of the colours saved on this mockup, by the name you gave it. Send this instead of 'hex' to keep calling a colour what your own catalogue calls it. Names match exactly, and are set with PATCH /api/v1/psd-mockups/{uuid}."
          },
          "blending_mode": {
            "type": "string",
            "description": "Blend mode for color overlay. Common values: 'normal', 'multiply' (fabric/textile mockups), 'screen', 'overlay', 'soft_light'. All 27 Photoshop blend modes supported.",
            "default": "normal",
            "examples": [
              "multiply"
            ]
          }
        },
        "type": "object",
        "title": "ColorOverlay",
        "description": "A colour laid over the smart object, with a blending mode.",
        "example": {
          "blending_mode": "multiply",
          "hex": "#FF5733"
        }
      },
      "CreateSessionRequest": {
        "properties": {
          "mockup_type": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "psd",
                  "2d"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "session_kind": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "setup",
                  "customize"
                ]
              },
              {
                "type": "null"
              }
            ]
          },
          "mockup_uuid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of the mockup to customize",
            "examples": [
              "c315f78f-d2c7-4541-b240-a9372842de94"
            ]
          },
          "product_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "description": "Product ID from the platform",
            "examples": [
              "8342019283"
            ]
          },
          "variant_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "description": "Variant ID from the platform",
            "examples": [
              "44912837465"
            ]
          },
          "allowed_origin": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "https://your-store.example.com"
            ]
          },
          "config": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/StudioConfigPatch"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional session-only Studio config override. Not persisted."
          },
          "action_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "minLength": 1,
                "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "add-to-cart"
            ]
          },
          "artwork": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/StudioArtworkInput"
                },
                "type": "array"
              },
              {
                "$ref": "#/components/schemas/StudioArtworkInput"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional session-locked artwork: a list with one entry per target, up to 8. A single object is also accepted and locks one target. Every target must belong to the explicitly bound mockup, and no target may repeat. Base64 takes precedence over url. The customer may edit placement and appearance but cannot replace, remove, add, or retarget artwork."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CreateSessionRequest",
        "example": {
          "allowed_origin": "https://your-store.example.com",
          "mockup_type": "psd",
          "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
          "product_id": "8342019283",
          "session_kind": "customize",
          "variant_id": "44912837465"
        }
      },
      "CreateSessionResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          },
          "mockup_type": {
            "type": "string",
            "enum": [
              "psd",
              "2d"
            ]
          },
          "session": {
            "type": "string",
            "examples": [
              "sess_xQ8pM2vK7nR4tB1yH6zJ3wL5sD9fG0aC2eN8uV4iT7o"
            ]
          },
          "expires_in": {
            "type": "integer",
            "examples": [
              900
            ]
          },
          "message_session_id": {
            "type": "string",
            "examples": [
              "7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52"
            ]
          },
          "bootstrap_secret": {
            "type": "string"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "mockup_type",
          "session",
          "expires_in",
          "message_session_id",
          "bootstrap_secret"
        ],
        "title": "CreateSessionResponse"
      },
      "ExportOptions": {
        "properties": {
          "image_format": {
            "type": "string",
            "enum": [
              "png",
              "jpg",
              "webp"
            ],
            "description": "Output format: 'webp' (30-70% smaller, recommended), 'png' (lossless), 'jpg' (smallest, no transparency)",
            "default": "webp"
          },
          "image_size": {
            "type": "integer",
            "maximum": 10000.0,
            "minimum": 100.0,
            "description": "Output width in pixels (100-10000). Height auto-calculated from the source aspect ratio. Powers of 2 (1024, 2048, 4096) recommended for best quality. Renders on an account in trial are capped at 1024: a larger image_size is rejected with error_code OUTPUT_RESOLUTION_LIMIT (HTTP 402) and is never silently downscaled. Add a payment method to render at full width.",
            "default": 2048
          },
          "quality": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 1.0,
            "description": "Compression quality for JPG/WebP (1-100). Ignored for PNG (always lossless). Default: 90.",
            "default": 90
          },
          "dpi": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 2400.0,
                "minimum": 72.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Resolution tag stamped into the output file metadata (JPG/WebP via Exif XResolution, PNG via pHYs), e.g. 300 for print. This is metadata only: it does NOT change the pixels. Pixel dimensions are controlled by image_size: set image_size = print_size_inches * dpi for a true print-ready file (e.g. 12 in * 300 = 3600 px). Range 72-2400. Default: null (opt-in). Omitting it does not leave the file untagged: the encoder writes a default ~25.4 DPI (1 px/mm) tag. All three formats carry the tag, but for maximum print-tool compatibility prefer jpg or png, because WebP stores resolution in Exif and not every viewer surfaces it.",
            "examples": [
              300
            ]
          }
        },
        "type": "object",
        "title": "ExportOptions",
        "description": "Format, size and quality of the rendered file.",
        "example": {
          "image_format": "webp",
          "image_size": 2048,
          "quality": 95
        }
      },
      "FontListResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "default": true
          },
          "data": {
            "items": {
              "$ref": "#/components/schemas/FontResponse"
            },
            "type": "array"
          },
          "pagination": {
            "$ref": "#/components/schemas/FontPagination"
          }
        },
        "type": "object",
        "required": [
          "data",
          "pagination"
        ],
        "title": "FontListResponse",
        "description": "List response wrapper for GET /api/v1/fonts.",
        "example": {
          "data": [],
          "pagination": {
            "page": 1,
            "per_page": 50,
            "total": 0
          },
          "success": true
        }
      },
      "FontPagination": {
        "properties": {
          "page": {
            "type": "integer",
            "description": "Current page (1-based)"
          },
          "per_page": {
            "type": "integer",
            "description": "Results per page"
          },
          "total": {
            "type": "integer",
            "description": "Total fonts matching the query"
          }
        },
        "type": "object",
        "required": [
          "page",
          "per_page",
          "total"
        ],
        "title": "FontPagination",
        "description": "Pagination envelope for the font list."
      },
      "FontResponse": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Font id",
            "examples": [
              "7f3a2b1c-9d4e-4a6f-b8c2-1e5d7a0c3f94"
            ]
          },
          "family": {
            "type": "string",
            "description": "Font family name, e.g. 'Open Sans'",
            "examples": [
              "Open Sans"
            ]
          },
          "subfamily": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Style within the family, e.g. 'Bold Italic'",
            "examples": [
              "Regular"
            ]
          },
          "postscript_name": {
            "type": "string",
            "description": "PostScript name, the stable key used to reference this font when rendering text layers",
            "examples": [
              "OpenSans-Regular"
            ]
          },
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Catalog category, e.g. 'sans-serif', 'serif', 'display'",
            "examples": [
              "sans-serif"
            ]
          },
          "license": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "License identifier (system fonts)",
            "examples": [
              "OFL"
            ]
          },
          "is_premium": {
            "type": "boolean",
            "description": "Whether this is a premium catalog font",
            "default": false
          },
          "is_system": {
            "type": "boolean",
            "description": "True for the shared system catalog, False for a font you uploaded",
            "examples": [
              true
            ]
          },
          "preview_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Legacy rendered preview image, when available; new catalog entries no longer include one (use file_url for live previews)"
          },
          "file_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "URL of the web-optimized WOFF2 file for live @font-face preview: a public CDN URL for system fonts, a short-lived link for your own uploads. Null for premium fonts; the original TTF/OTF source is never exposed.",
            "examples": [
              "https://cdn.sudomock.com/mockup-assets/fonts/web/7f3a2b1c-9d4e-4a6f-b8c2-1e5d7a0c3f94.woff2"
            ]
          },
          "created_at": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "When the font was added",
            "examples": [
              "2026-07-13T09:14:22+00:00"
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "family",
          "postscript_name",
          "is_system"
        ],
        "title": "FontResponse",
        "description": "A single font in the catalog: a shared system font, or one of the\ncaller's own uploaded fonts.",
        "example": {
          "category": "sans-serif",
          "created_at": "2026-07-13T00:00:00+00:00",
          "family": "Open Sans",
          "file_url": "https://cdn.sudomock.com/mockup-assets/fonts/web/9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f.woff2",
          "is_premium": false,
          "is_system": true,
          "license": "OFL",
          "postscript_name": "OpenSans-Regular",
          "subfamily": "Regular",
          "uuid": "9f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
          "preview_url": null
        }
      },
      "GroupLayer": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the group layer",
            "examples": [
              "5e8b0c72-9a41-4d36-b7f8-2c60d1e94537"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name of the group layer",
            "examples": [
              "Outlined logo"
            ]
          },
          "has_stroke_effect": {
            "type": "boolean",
            "description": "Whether the group has at least one outline of its own",
            "default": true
          },
          "stroke_count": {
            "type": "integer",
            "minimum": 1.0,
            "description": "Number of outlines owned by this group, in front-to-back stroke_color order",
            "examples": [
              2
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "name",
          "stroke_count"
        ],
        "title": "GroupLayer",
        "description": "Group layer with editable outlines in upload/detail responses."
      },
      "GroupLayerInput": {
        "properties": {
          "uuid": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
            "description": "UUID of the group layer to update (from the upload/detail response group_layers list)",
            "examples": [
              "b2c14e08-5a7d-4f36-a91b-7e0d5c283a64"
            ]
          },
          "stroke_color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              }
            ],
            "description": "Color for the group's outlines. Send a hex value like \"#FFFFFF\" to recolor the front outline, or a list in stroke_count order (front to back). Use null to keep an outline's original color; extra entries are ignored. The change affects everything inside this group.",
            "examples": [
              "#FFFFFF",
              [
                "#FFFFFF",
                null
              ]
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "stroke_color"
        ],
        "title": "GroupLayerInput",
        "description": "Group outline override for rendering."
      },
      "MeAccountData": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "User UUID",
            "examples": [
              "c33f5fdf-346e-4c37-8686-9afcca4645ef"
            ]
          },
          "email": {
            "type": "string",
            "description": "User email address",
            "examples": [
              "user@example.com"
            ]
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Account/company name from user_metadata",
            "examples": [
              "Acme Corp"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Account creation timestamp",
            "examples": [
              "2025-06-15T10:30:00Z"
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "email",
          "created_at"
        ],
        "title": "MeAccountData",
        "description": "Account information in /me response",
        "example": {
          "created_at": "2025-06-15T10:30:00Z",
          "email": "user@example.com",
          "name": "Acme Corp",
          "uuid": "123e4567-e89b-12d3-a456-426614174000"
        }
      },
      "MeApiKeyData": {
        "properties": {
          "name": {
            "type": "string",
            "description": "API key name",
            "examples": [
              "Production Key"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "When the API key was created",
            "examples": [
              "2025-06-15T10:30:00Z"
            ]
          },
          "last_used_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "Last time the API key was used",
            "examples": [
              "2026-01-05T00:25:00Z"
            ]
          },
          "total_requests": {
            "type": "integer",
            "description": "Total credit-consuming operations recorded for this API key",
            "examples": [
              847293
            ]
          }
        },
        "type": "object",
        "required": [
          "name",
          "created_at",
          "total_requests"
        ],
        "title": "MeApiKeyData",
        "description": "API key metadata in /me response",
        "example": {
          "created_at": "2025-06-15T10:30:00Z",
          "last_used_at": "2026-01-05T00:25:00Z",
          "name": "Production Key",
          "total_requests": 847293
        }
      },
      "MeOrganizationData": {
        "properties": {
          "id": {
            "type": "string",
            "description": "Organization UUID",
            "examples": [
              "97d7a314-29be-47b5-997c-df7f0ca71eb8"
            ]
          },
          "name": {
            "type": "string",
            "description": "Organization name",
            "examples": [
              "Acme"
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "name"
        ],
        "title": "MeOrganizationData",
        "description": "Organization the request acts on in /me response",
        "example": {
          "id": "123e4567-e89b-12d3-a456-426614174000",
          "name": "Acme"
        }
      },
      "MeResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/MeResponseData",
            "description": "Response data"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true,
            "examples": [
              true
            ]
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "MeResponse",
        "description": "Your account, plan, usage and remaining credits.",
        "example": {
          "data": {
            "account": {
              "created_at": "2025-06-15T10:30:00Z",
              "email": "user@example.com",
              "name": "Acme Corp",
              "uuid": "123e4567-e89b-12d3-a456-426614174000"
            },
            "api_key": {
              "created_at": "2025-06-15T10:30:00Z",
              "last_used_at": "2026-01-05T00:25:00Z",
              "name": "Production Key",
              "total_requests": 847293
            },
            "organization": {
              "id": "123e4567-e89b-12d3-a456-426614174000",
              "name": "Acme"
            },
            "subscription": {
              "current_period_end": "2026-02-05T00:00:00Z",
              "plan": "pro",
              "status": "active",
              "tier": "pro"
            },
            "usage": {
              "billing_period_end": "2026-02-01T00:00:00Z",
              "billing_period_start": "2026-01-01T00:00:00Z",
              "credits_limit": 50000,
              "credits_remaining": 37153,
              "credits_used_this_month": 12847,
              "prepaid_balance": 0.0,
              "prepaid_balance_currency": "USD"
            }
          },
          "success": true
        }
      },
      "MeResponseData": {
        "properties": {
          "account": {
            "$ref": "#/components/schemas/MeAccountData",
            "description": "User account information"
          },
          "organization": {
            "$ref": "#/components/schemas/MeOrganizationData",
            "description": "Organization that owns the subscription and usage below"
          },
          "subscription": {
            "$ref": "#/components/schemas/MeSubscriptionData",
            "description": "Subscription details"
          },
          "usage": {
            "$ref": "#/components/schemas/MeUsageData",
            "description": "Usage statistics"
          },
          "api_key": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/MeApiKeyData"
              },
              {
                "type": "null"
              }
            ],
            "description": "Current API key metadata"
          }
        },
        "type": "object",
        "required": [
          "account",
          "organization",
          "subscription",
          "usage"
        ],
        "title": "MeResponseData",
        "description": "Data payload in /me response"
      },
      "MeSubscriptionData": {
        "properties": {
          "plan": {
            "type": "string",
            "description": "Plan slug (e.g., 'pro-25k', 'scale-100k', 'free')",
            "examples": [
              "pro-25k"
            ]
          },
          "tier": {
            "type": "string",
            "description": "Plan tier for feature gating (e.g., 'free', 'pro', 'scale')",
            "examples": [
              "pro"
            ]
          },
          "status": {
            "type": "string",
            "description": "Subscription status: 'active', 'cancelled', 'past_due', 'expired', 'paused'",
            "examples": [
              "active"
            ]
          },
          "current_period_end": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "description": "End of current billing period",
            "examples": [
              "2026-02-05T00:00:00Z"
            ]
          },
          "billing_channel": {
            "type": "string",
            "enum": [
              "shopify",
              "stripe",
              "none"
            ],
            "description": "Which billing channel currently owns this subscription. Frontend uses this for lock-to-channel UI gating.",
            "default": "none",
            "examples": [
              "stripe"
            ]
          }
        },
        "type": "object",
        "required": [
          "plan",
          "tier",
          "status"
        ],
        "title": "MeSubscriptionData",
        "description": "Subscription information in /me response",
        "example": {
          "billing_channel": "stripe",
          "current_period_end": "2026-02-05T00:00:00Z",
          "plan": "pro-25k",
          "status": "active",
          "tier": "pro"
        }
      },
      "MeUsageData": {
        "properties": {
          "credits_used_this_month": {
            "type": "integer",
            "description": "Credits used in current billing period",
            "examples": [
              12847
            ]
          },
          "credits_limit": {
            "type": "integer",
            "description": "Total credits available per month from plan",
            "examples": [
              50000
            ]
          },
          "credits_remaining": {
            "type": "integer",
            "description": "Credits remaining (calculated)",
            "examples": [
              37153
            ]
          },
          "billing_period_start": {
            "type": "string",
            "format": "date-time",
            "description": "Start of current billing period",
            "examples": [
              "2026-01-01T00:00:00Z"
            ]
          },
          "billing_period_end": {
            "type": "string",
            "format": "date-time",
            "description": "End of current billing period",
            "examples": [
              "2026-02-01T00:00:00Z"
            ]
          },
          "prepaid_balance": {
            "type": "number",
            "description": "Prepaid balance remaining, in prepaid_balance_currency. 0 when the account holds no balance (never null). Independent of the credits_* fields above, which count a subscription allotment.",
            "examples": [
              4.3
            ]
          },
          "prepaid_balance_currency": {
            "type": "string",
            "description": "ISO 4217 currency of prepaid_balance. Always USD today.",
            "examples": [
              "USD"
            ]
          }
        },
        "type": "object",
        "required": [
          "credits_used_this_month",
          "credits_limit",
          "credits_remaining",
          "billing_period_start",
          "billing_period_end",
          "prepaid_balance",
          "prepaid_balance_currency"
        ],
        "title": "MeUsageData",
        "description": "Usage statistics in /me response",
        "example": {
          "billing_period_end": "2026-02-01T00:00:00Z",
          "billing_period_start": "2026-01-01T00:00:00Z",
          "credits_limit": 50000,
          "credits_remaining": 37153,
          "credits_used_this_month": 12847,
          "prepaid_balance": 4.3,
          "prepaid_balance_currency": "USD"
        }
      },
      "MockupColour": {
        "properties": {
          "label": {
            "type": "string",
            "maxLength": 32,
            "minLength": 1,
            "description": "What you call this colour, e.g. 'blue jean'. Matched exactly when a render asks for it."
          },
          "hex": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$",
            "description": "The colour the name paints, e.g. '#6A8296'."
          }
        },
        "type": "object",
        "required": [
          "label",
          "hex"
        ],
        "title": "MockupColour",
        "description": "A name this mockup answers to, and the colour it paints."
      },
      "MockupListData": {
        "properties": {
          "mockups": {
            "items": {
              "$ref": "#/components/schemas/UploadResponseData"
            },
            "type": "array",
            "description": "List of mockup templates"
          },
          "total": {
            "type": "integer",
            "description": "Total number of mockups matching filters",
            "examples": [
              137
            ]
          },
          "limit": {
            "type": "integer",
            "description": "Results per page",
            "examples": [
              20
            ]
          },
          "offset": {
            "type": "integer",
            "description": "Pagination offset",
            "examples": [
              0
            ]
          }
        },
        "type": "object",
        "required": [
          "mockups",
          "total",
          "limit",
          "offset"
        ],
        "title": "MockupListData",
        "description": "Typed data payload for mockup list response"
      },
      "MockupListResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "default": true,
            "examples": [
              true
            ]
          },
          "data": {
            "$ref": "#/components/schemas/MockupListData"
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "MockupListResponse",
        "description": "List response wrapper for GET /api/v1/psd-mockups",
        "example": {
          "data": {
            "limit": 20,
            "mockups": [
              {
                "collections": [],
                "group_layers": [],
                "height": 5000,
                "name": "Heavyweight tee front",
                "smart_objects": [
                  {
                    "layer_name": "Front print",
                    "name": "Front print",
                    "position": {
                      "height": 3413,
                      "width": 3000,
                      "x": 512,
                      "y": 730
                    },
                    "print_area_presets": [
                      {
                        "name": "Default",
                        "position": {
                          "height": 3413,
                          "width": 3000,
                          "x": 0,
                          "y": 0
                        },
                        "size": {
                          "height": 3413,
                          "width": 3000
                        },
                        "thumbnails": [],
                        "uuid": "d07f5b18-2c94-4e83-a6b1-95f3c8e27a40"
                      }
                    ],
                    "size": {
                      "height": 3413,
                      "width": 3000
                    },
                    "uuid": "b41a7e52-93c8-4d61-8f07-2ae5c9d04713",
                    "blend_mode": null,
                    "quad": null
                  }
                ],
                "text_layers": [],
                "thumbnail": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_720.webp",
                "thumbnails": [
                  {
                    "url": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_720.webp",
                    "width": 720
                  }
                ],
                "uuid": "8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8",
                "width": 4000
              }
            ],
            "offset": 0,
            "total": 1
          },
          "success": true
        }
      },
      "MockupUpdateRequest": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "New mockup name"
          },
          "colors": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/MockupColour"
                },
                "type": "array",
                "maxItems": 96
              },
              {
                "type": "null"
              }
            ],
            "description": "The colours this mockup answers to by name. Replaces the whole list, so send every colour you want to keep. Send [] to clear it."
          }
        },
        "type": "object",
        "title": "MockupUpdateRequest",
        "description": "Update request for PATCH /api/v1/psd-mockups/{uuid}",
        "example": {
          "name": "Updated Mockup Name"
        }
      },
      "PaletteColour": {
        "properties": {
          "hex": {
            "type": "string",
            "pattern": "^#[0-9A-Fa-f]{6}$",
            "examples": [
              "#1a1a1a"
            ]
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 32
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "Black Heather"
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "hex"
        ],
        "title": "PaletteColour",
        "description": "One colour the editor offers, with your name for it."
      },
      "PhotoMockup": {
        "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
            ]
          },
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintArea"
            },
            "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": "PhotoMockup"
      },
      "PhotoMockupAdjustments": {
        "properties": {
          "brightness": {
            "type": "integer",
            "maximum": 150.0,
            "minimum": -150.0,
            "default": 0
          },
          "contrast": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "opacity": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "default": 100
          },
          "saturation": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "vibrance": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "blur": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "default": 0
          },
          "blend_mode": {
            "type": "string",
            "enum": [
              "multiply",
              "normal",
              "screen",
              "lighten",
              "soft_light",
              "overlay",
              "darken"
            ],
            "description": "How the artwork sits on the product surface. 'multiply' keeps the material texture visible and is the best choice on light fabric (default); 'normal' reproduces the artwork colors exactly, whatever the product color, and is the right choice when a brand color has to match the supplied file; 'screen' lightens the artwork against the surface, which is worth reaching for only when you want that lighter result, since the default already adapts to a dark garment; 'lighten' keeps the artwork only where it is brighter than the surface; 'soft_light' gives 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.",
            "default": "multiply"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PhotoMockupAdjustments",
        "description": "Outcome-level controls for the public 2D render API."
      },
      "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."
      },
      "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"
        }
      },
      "PhotoMockupDeleteData": {
        "properties": {
          "deleted": {
            "type": "string"
          }
        },
        "type": "object",
        "required": [
          "deleted"
        ],
        "title": "PhotoMockupDeleteData"
      },
      "PhotoMockupDeleteResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupDeleteData"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PhotoMockupDeleteResponse"
      },
      "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"
      },
      "PhotoMockupDetailResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupDetail"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PhotoMockupDetailResponse"
      },
      "PhotoMockupList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockup"
            },
            "type": "array"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data",
          "total",
          "limit",
          "offset"
        ],
        "title": "PhotoMockupList"
      },
      "PhotoMockupPlacement": {
        "properties": {
          "position": {
            "type": "string",
            "enum": [
              "center",
              "top_left",
              "top_center",
              "top_right",
              "center_left",
              "center_right",
              "left_center",
              "right_center",
              "bottom_left",
              "bottom_center",
              "bottom_right"
            ],
            "description": "Predefined position within print area",
            "default": "center"
          },
          "coverage": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": 10.0
              },
              {
                "type": "null"
              }
            ],
            "description": "How much of the product surface the artwork spans, 10 to 100. Spans the whole surface by default. Belongs to a surface_uuid target, and cannot be combined with an explicit width and height."
          },
          "fit": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "fill",
                  "fit",
                  "crop"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How the artwork meets the print area. 'fit' scales it until it fits inside and keeps its proportions, which is the default and can leave empty space. 'fill' stretches it to the edges and does not keep proportions. 'crop' covers the area and cuts the overflow, keeping proportions. 'contain' and 'cover' are the older names for 'fit' and 'crop' and are still accepted. Always targets the whole print area. Belongs to a uuid target, and cannot be combined with an explicit width and height."
          },
          "offset_x": {
            "type": "number",
            "description": "Horizontal offset in print-area pixels, measured from the anchor that 'position' picks, positive right. With the default position of 'center' that anchor is the middle of the print area.",
            "default": 0
          },
          "offset_y": {
            "type": "number",
            "description": "Vertical offset in print-area pixels, measured from the anchor that 'position' picks, positive down. With the default position of 'center' that anchor is the middle of the print area.",
            "default": 0
          },
          "width": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 30000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork width in target pixels. Must be sent together with 'height'. An exact box belongs to either kind of target: send it instead of 'fit' on a print area, or instead of 'coverage' on a surface. Width and height are independent, so any aspect ratio is allowed."
          },
          "height": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 30000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork height in target pixels. Must be sent together with 'width'. An exact box belongs to either kind of target: send it instead of 'fit' on a print area, or instead of 'coverage' on a surface. Width and height are independent, so any aspect ratio is allowed."
          },
          "rotation": {
            "type": "number",
            "maximum": 360.0,
            "minimum": -360.0,
            "description": "Rotation in degrees (clockwise positive)",
            "default": 0
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PhotoMockupPlacement",
        "description": "Where the artwork sits on the render target, and how big it is.\n\nSizing has exactly one spelling per target. On a product surface that is\ncoverage: how much of the surface the artwork spans. On a print area it is\neither fit, or an explicit width and height in print-area pixels; the two\naxes are independent, so stretching on one axis only is a supported\nplacement rather than an error, which is what makes this path as free as\nthe PSD path.\n\nEvery option has exactly one spelling: offset_x, offset_y and rotation.\nA second accepted spelling for the same option would let two callers write\nthe same placement two ways and force a precedence rule to break the tie,\nso unrecognised keys are rejected rather than translated.\n\nEvery pixel length here is a print-area pixel: the frame is the bounding\nbox of the print area's own four corner points, in the pixels of the\nproduct photo the mockup was built from. It is not a fraction of anything,\nand image_size does not change it. That bounding box is also the boundary\nthe artwork is composited within.\n\nrotation is applied before the artwork is positioned, and a rotated artwork\noccupies its rotated bounding box: a 100x50 box sent with rotation 45 lands\nas a 106x106 footprint. width and height describe the box before rotation."
      },
      "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"
      },
      "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."
      },
      "PhotoMockupPrintAreaRender": {
        "properties": {
          "uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of a saved print area, a bounded zone drawn on a product.",
            "examples": [
              "19be48d4-c810-4420-86e3-7ec2a4d85571"
            ]
          },
          "surface_uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of a printable product surface. A product carrying saved print areas still has one, and it is a separate render target from them.",
            "examples": [
              "733ee99a-f41f-4b9b-bf33-2ffa489f96db"
            ]
          },
          "base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Base64-encoded artwork image."
          },
          "artwork_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork image URL",
            "examples": [
              "https://example.com/design.png"
            ]
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Solid color as a hex code (e.g., '#FF0000'), or the name of a colour saved on this mockup (e.g., 'blue jean'). Names match exactly and are set with PATCH /api/v1/photo-mockups/{uuid}.",
            "examples": [
              "#6A8296"
            ]
          },
          "adjustments": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PhotoMockupAdjustments"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional visual adjustments for the artwork."
          },
          "placement": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PhotoMockupPlacement"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where the artwork sits and how big it is. position, offset_x, offset_y and rotation apply to either target. Sizing follows the target: coverage on a surface_uuid target, and either fit or an explicit width and height on a uuid target."
          },
          "flip_horizontal": {
            "type": "boolean",
            "description": "Flip artwork horizontally (left-right mirror)",
            "default": false
          },
          "flip_vertical": {
            "type": "boolean",
            "description": "Flip artwork vertically (top-bottom mirror)",
            "default": false
          },
          "remove_background": {
            "type": "boolean",
            "description": "Remove the image background before placing the artwork; the subject is isolated onto a clean transparent cutout. Adds 25 credits per artwork to the render cost.",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PhotoMockupPrintAreaRender",
        "description": "Per-print-area artwork configuration for 2D render.\nMirrors SmartObjectInput pattern from PSD render endpoint."
      },
      "PhotoMockupPrintAreasUpdate": {
        "properties": {
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintAreaInput"
            },
            "type": "array",
            "maxItems": 8,
            "minItems": 0,
            "description": "Up to eight printable areas; array order becomes sort order. An empty array saves the mockup without bounded placement zones."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "print_areas"
        ],
        "title": "PhotoMockupPrintAreasUpdate",
        "description": "Replace a mockup's printable areas in the supplied order.",
        "example": {
          "print_areas": [
            {
              "points": [
                [
                  200,
                  150
                ],
                [
                  600,
                  150
                ],
                [
                  620,
                  550
                ],
                [
                  180,
                  550
                ]
              ]
            }
          ]
        }
      },
      "PhotoMockupPrintFile": {
        "properties": {
          "export_path": {
            "type": "string",
            "description": "Public URL of the rendered output"
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Render duration in milliseconds"
          },
          "export_format": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Output format used (png, jpg, webp)"
          }
        },
        "type": "object",
        "required": [
          "export_path"
        ],
        "title": "PhotoMockupPrintFile",
        "description": "AI render output file"
      },
      "PhotoMockupRender": {
        "properties": {
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintAreaRender"
            },
            "type": "array",
            "maxItems": 8,
            "minItems": 1,
            "description": "Artwork configuration per render target. Use uuid for a saved print area, and surface_uuid for a whole product surface. A product can be rendered either way, and saving a print area on it does not take its surface away."
          },
          "export_options": {
            "$ref": "#/components/schemas/ExportOptions",
            "description": "Export configuration for format, size and quality. Every field has a default, so the whole object is optional."
          },
          "is_async": {
            "type": "boolean",
            "description": "If true, the render 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 rendered image URL on success. If false (default), the render runs synchronously and returns the result.",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "print_areas"
        ],
        "title": "PhotoMockupRender",
        "description": "Body for POST /api/v1/photo-mockups/{mockup_id}/render.\n\nThe mockup UUID is taken from the path; the body carries only per-print-area\nartwork configuration and export options.",
        "example": {
          "export_options": {
            "image_format": "webp",
            "image_size": 1920,
            "quality": 95
          },
          "print_areas": [
            {
              "adjustments": {
                "blend_mode": "multiply",
                "opacity": 90
              },
              "artwork_url": "https://example.com/design.png",
              "placement": {
                "fit": "fit",
                "position": "center"
              },
              "uuid": "223e4567-e89b-12d3-a456-426614174001"
            }
          ]
        }
      },
      "PhotoMockupRenderResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupRenderResult",
            "description": "Rendered output files"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PhotoMockupRenderResponse",
        "description": "The finished photo-mockup render and where to fetch it."
      },
      "PhotoMockupRenderResult": {
        "properties": {
          "print_files": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintFile"
            },
            "type": "array",
            "description": "List of rendered outputs"
          },
          "render_uuid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identifier for this render."
          }
        },
        "type": "object",
        "required": [
          "print_files"
        ],
        "title": "PhotoMockupRenderResult",
        "description": "Data payload in SudoAI render response"
      },
      "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.\n\nSend ``surface_uuid`` as a render target to print across the whole product."
      },
      "PhotoMockupUpdateData": {
        "properties": {
          "uuid": {
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "colors": {
            "items": {
              "$ref": "#/components/schemas/MockupColour"
            },
            "type": "array"
          }
        },
        "type": "object",
        "required": [
          "uuid"
        ],
        "title": "PhotoMockupUpdateData"
      },
      "PhotoMockupUpdateResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupUpdateData"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PhotoMockupUpdateResponse"
      },
      "Position": {
        "properties": {
          "x": {
            "type": "integer",
            "description": "Position on PSD canvas in pixels (top-left origin)."
          },
          "y": {
            "type": "integer",
            "description": "Position on PSD canvas in pixels (top-left origin)."
          },
          "width": {
            "type": "integer",
            "description": "Width in pixels"
          },
          "height": {
            "type": "integer",
            "description": "Height in pixels"
          }
        },
        "type": "object",
        "required": [
          "x",
          "y",
          "width",
          "height"
        ],
        "title": "Position",
        "description": "Position coordinates for smart objects (bounding box)"
      },
      "PrintAreaPreset": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the preset",
            "examples": [
              "d07f5b18-2c94-4e83-a6b1-95f3c8e27a40"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name of the preset (e.g., 'Default')",
            "examples": [
              "Default"
            ]
          },
          "thumbnails": {
            "items": {
              "$ref": "#/components/schemas/ThumbnailSize"
            },
            "type": "array",
            "description": "Thumbnail previews of the preset"
          },
          "size": {
            "$ref": "#/components/schemas/Size",
            "description": "Size dimensions of the print area"
          },
          "position": {
            "$ref": "#/components/schemas/Position",
            "description": "Position relative to smart object (x, y, width, height)"
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "name",
          "size",
          "position"
        ],
        "title": "PrintAreaPreset",
        "description": "Print area preset configuration for smart object"
      },
      "PrintFile": {
        "properties": {
          "export_path": {
            "type": "string",
            "description": "Path to the rendered output file",
            "examples": [
              "https://cdn.sudomock.com/mockup-assets/renders/c315f78f-d2c7-4541-b240-a9372842de94/render_5ec56e42-4afe-4267-bf21-6f8f586d16bb.webp"
            ]
          },
          "smart_object_uuid": {
            "type": "string",
            "description": "UUID of the first Smart Object in the request; an empty string for a render without Smart Objects, including text-only and group-only renders.",
            "examples": [
              "6bdc8897-3eee-4356-b717-8bc3c9249946"
            ]
          },
          "render_uuid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The render's transaction id (also the async job uuid). Returned so storefront/Studio fulfillment flows can correlate the render; null on legacy paths.",
            "examples": [
              "5ec56e42-4afe-4267-bf21-6f8f586d16bb"
            ]
          }
        },
        "type": "object",
        "required": [
          "export_path",
          "smart_object_uuid"
        ],
        "title": "PrintFile",
        "description": "Individual print file in render response",
        "example": {
          "export_path": "https://cdn.sudomock.com/mockup-assets/renders/c315f78f-d2c7-4541-b240-a9372842de94/render_8f2c1d4e.webp",
          "smart_object_uuid": "223e4567-e89b-12d3-a456-426614174001"
        }
      },
      "PublicTwoDAdjustments": {
        "properties": {
          "brightness": {
            "type": "integer",
            "maximum": 150.0,
            "minimum": -150.0,
            "default": 0
          },
          "contrast": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "opacity": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "default": 100
          },
          "saturation": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "vibrance": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": -100.0,
            "default": 0
          },
          "blur": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 0.0,
            "default": 0
          },
          "blend_mode": {
            "type": "string",
            "enum": [
              "multiply",
              "normal",
              "screen",
              "lighten",
              "soft_light",
              "overlay",
              "darken"
            ],
            "description": "How the artwork sits on the product surface. 'multiply' keeps the material texture visible and is the best choice on light fabric (default); 'normal' reproduces the artwork colors exactly, whatever the product color, and is the right choice when a brand color has to match the supplied file; 'screen' lightens the artwork against the surface, which is worth reaching for only when you want that lighter result, since the default already adapts to a dark garment; 'lighten' keeps the artwork only where it is brighter than the surface; 'soft_light' gives 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.",
            "default": "multiply"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicTwoDAdjustments",
        "description": "Deprecated name for `PhotoMockupAdjustments`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "PublicTwoDMockupCreateAcceptedResponse": {
        "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": "PublicTwoDMockupCreateAcceptedResponse",
        "description": "Deprecated name for `PhotoMockupCreateAcceptedResponse`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "PublicTwoDMockupDeleteData": {
        "properties": {
          "deleted": {
            "type": "string"
          }
        },
        "type": "object",
        "required": [
          "deleted"
        ],
        "title": "PublicTwoDMockupDeleteData",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupDeleteData`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDMockupDeleteResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupDeleteData"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PublicTwoDMockupDeleteResponse",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupDeleteResponse`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDMockupDetail": {
        "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": "PublicTwoDMockupDetail",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupDetail`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDMockupDetailResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupDetail"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "PublicTwoDMockupDetailResponse",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupDetailResponse`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDMockupListItem": {
        "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
            ]
          },
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintArea"
            },
            "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": "PublicTwoDMockupListItem",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockup`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDMockupListResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockup"
            },
            "type": "array"
          },
          "total": {
            "type": "integer"
          },
          "limit": {
            "type": "integer"
          },
          "offset": {
            "type": "integer"
          },
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data",
          "total",
          "limit",
          "offset"
        ],
        "title": "PublicTwoDMockupListResponse",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupList`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDPrintArea": {
        "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": "PublicTwoDPrintArea",
        "deprecated": true,
        "description": "Deprecated name for `PhotoMockupPrintArea`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has."
      },
      "PublicTwoDSurface": {
        "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": "PublicTwoDSurface",
        "description": "Deprecated name for `PhotoMockupSurface`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "RenderRequest": {
        "properties": {
          "mockup_uuid": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
            "description": "UUID of the mockup to render. Must be a valid UUID, for example c315f78f-d2c7-4541-b240-a9372842de94. Obtained from the POST /api/v1/psd/upload or GET /api/v1/psd-mockups response.",
            "examples": [
              "c315f78f-d2c7-4541-b240-a9372842de94"
            ]
          },
          "smart_objects": {
            "items": {
              "$ref": "#/components/schemas/SmartObjectInput"
            },
            "type": "array",
            "description": "List of smart objects with their assets. Required unless text_layers or group_layers is provided."
          },
          "text_layers": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/TextLayerInput"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "description": "Up to 50 text-layer overrides. Each entry targets a text-layer UUID and provides exactly one of text for a single-style layer or segments for a mixed-style layer. Omitted layers and styling fields keep their authored values."
          },
          "group_layers": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/GroupLayerInput"
                },
                "type": "array",
                "maxItems": 50
              },
              {
                "type": "null"
              }
            ],
            "description": "Group outline overrides. Each entry addresses a listed group by its own UUID; the change affects everything inside that group."
          },
          "export_options": {
            "$ref": "#/components/schemas/ExportOptions",
            "description": "Export configuration for format, size and quality. Every field has a default, so the whole object is optional."
          },
          "export_label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 100
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional label for export file naming (max 100 chars, alphanumeric + hyphen/underscore)",
            "examples": [
              "summer-tee-front"
            ]
          },
          "is_async": {
            "type": "boolean",
            "description": "If true, the render 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). If false (default), the render runs synchronously and returns the result.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "mockup_uuid"
        ],
        "title": "RenderRequest",
        "description": "What to render: which mockup, what goes into it, and how to export it.",
        "example": {
          "export_options": {
            "image_format": "webp",
            "image_size": 1920,
            "quality": 95
          },
          "mockup_uuid": "123e4567-e89b-12d3-a456-426614174000",
          "smart_objects": [
            {
              "asset": {
                "fit": "fill",
                "position": {
                  "left": 100,
                  "top": 100
                },
                "rotate": 0,
                "size": {
                  "height": 600,
                  "width": 800
                },
                "url": "https://example.com/user-design.png"
              },
              "color": {
                "blending_mode": "multiply",
                "hex": "#FFFFFF"
              },
              "uuid": "223e4567-e89b-12d3-a456-426614174001"
            }
          ]
        }
      },
      "RenderResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RenderResponseData",
            "description": "Response data"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true
          },
          "warnings": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/RenderWarning"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Non-fatal advisories about this render (e.g. requested size above the mockup's native resolution). Omitted when none.",
            "examples": [
              [
                {
                  "code": "OUTPUT_EXCEEDS_MAX_RESOLUTION",
                  "message": "Requested 4096px is above this mockup's native 3000px. The result is enlarged and may look softer than its native resolution. For the sharpest output, request 3000px or less."
                }
              ]
            ]
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "RenderResponse",
        "description": "The finished render and where to fetch it.",
        "example": {
          "data": {
            "print_files": [
              {
                "export_path": "https://cdn.sudomock.com/mockup-assets/renders/c315f78f-d2c7-4541-b240-a9372842de94/render_8f2c1d4e.webp",
                "smart_object_uuid": "223e4567-e89b-12d3-a456-426614174001"
              }
            ]
          },
          "success": true
        }
      },
      "RenderResponseData": {
        "properties": {
          "print_files": {
            "items": {
              "$ref": "#/components/schemas/PrintFile"
            },
            "type": "array",
            "description": "List of rendered print files"
          },
          "render_uuid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The render's transaction id (also the async job uuid). Echoed at the data level for convenience; null on legacy paths."
          }
        },
        "type": "object",
        "required": [
          "print_files"
        ],
        "title": "RenderResponseData",
        "description": "Data payload in render response"
      },
      "RenderWarning": {
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable advisory code"
          },
          "message": {
            "type": "string",
            "description": "Human-readable, non-fatal advisory"
          }
        },
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "title": "RenderWarning",
        "description": "Non-fatal advisory attached to a successful render."
      },
      "Size": {
        "properties": {
          "width": {
            "type": "integer",
            "description": "Width in pixels"
          },
          "height": {
            "type": "integer",
            "description": "Height in pixels"
          }
        },
        "type": "object",
        "required": [
          "width",
          "height"
        ],
        "title": "Size",
        "description": "Width and height in pixels."
      },
      "SmartObjectInput": {
        "properties": {
          "uuid": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
            "description": "UUID of the smart object to render",
            "examples": [
              "b41a7e52-93c8-4d61-8f07-2ae5c9d04713"
            ]
          },
          "asset": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AssetInput"
              },
              {
                "type": "null"
              }
            ],
            "description": "Asset configuration (image to place)"
          },
          "color": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ColorOverlay"
              },
              {
                "type": "null"
              }
            ],
            "description": "Color overlay configuration"
          },
          "adjustment_layers": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/AdjustmentLayers"
              },
              {
                "type": "null"
              }
            ],
            "description": "Image adjustments applied to your artwork after the fit transform and before it is blended into the mockup. PSD-level adjustment layers are not affected."
          }
        },
        "type": "object",
        "required": [
          "uuid"
        ],
        "title": "SmartObjectInput",
        "description": "One smart object and what goes into it.",
        "example": {
          "asset": {
            "fit": "fill",
            "rotate": 0,
            "url": "https://example.com/user-design.png"
          },
          "color": {
            "blending_mode": "multiply",
            "hex": "#FF5733"
          },
          "uuid": "223e4567-e89b-12d3-a456-426614174001"
        }
      },
      "SmartObjectResponse": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the smart object",
            "examples": [
              "b41a7e52-93c8-4d61-8f07-2ae5c9d04713"
            ]
          },
          "name": {
            "type": "string",
            "description": "Display name of the smart object",
            "examples": [
              "Front print"
            ]
          },
          "size": {
            "$ref": "#/components/schemas/Size",
            "description": "Size dimensions of the smart object"
          },
          "position": {
            "$ref": "#/components/schemas/Position",
            "description": "Position coordinates (x, y, width, height)"
          },
          "print_area_presets": {
            "items": {
              "$ref": "#/components/schemas/PrintAreaPreset"
            },
            "type": "array",
            "description": "Print area preset configurations"
          },
          "layer_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Original PSD layer name",
            "examples": [
              "Front print"
            ]
          },
          "quad": {
            "anyOf": [
              {
                "items": {
                  "items": {
                    "type": "number"
                  },
                  "type": "array"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Four display coordinates for the editable area. Only available on Scale tier plans (null on Free/Starter/Pro).",
            "examples": [
              [
                [
                  512.0,
                  742.0
                ],
                [
                  3512.0,
                  730.0
                ],
                [
                  3499.0,
                  4143.0
                ],
                [
                  524.0,
                  4131.0
                ]
              ]
            ]
          },
          "blend_mode": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The blend mode this smart object layer carries in the PSD, lowercase (e.g. 'normal', 'multiply', 'soft_light'). Null in the mockup list; request a single mockup to read it.",
            "examples": [
              "multiply"
            ]
          },
          "instance_count": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Number of PSD layers this input drives (smart object instancing); null/1 = single layer",
            "examples": [
              3
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "name",
          "size",
          "position",
          "print_area_presets"
        ],
        "title": "SmartObjectResponse",
        "description": "A smart object found in the uploaded file, with the UUID you address it by.",
        "example": {
          "blend_mode": "normal",
          "layer_name": "Smart Object 1",
          "name": "Main Design",
          "position": {
            "height": 600,
            "width": 800,
            "x": 100,
            "y": 100
          },
          "print_area_presets": [
            {
              "name": "Default",
              "position": {
                "height": 3413,
                "width": 3000,
                "x": 0,
                "y": 0
              },
              "size": {
                "height": 3413,
                "width": 3000
              },
              "thumbnails": [],
              "uuid": "preset-uuid-here"
            }
          ],
          "quad": [
            [
              100,
              100
            ],
            [
              900,
              100
            ],
            [
              900,
              700
            ],
            [
              100,
              700
            ]
          ],
          "size": {
            "height": 3413,
            "width": 3000
          },
          "uuid": "123e4567-e89b-12d3-a456-426614174000"
        }
      },
      "StudioActionContext": {
        "properties": {
          "shop": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "your-store.myshopify.com"
            ]
          },
          "product_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "8342019283"
            ]
          },
          "variant_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "44912837465"
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "StudioActionContext"
      },
      "StudioActionPayload": {
        "properties": {
          "mockup_uuid": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "c315f78f-d2c7-4541-b240-a9372842de94"
            ]
          },
          "render_uuid": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354"
            ]
          },
          "action_id": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "minLength": 1,
                "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "add-to-cart"
            ]
          },
          "action_context": {
            "$ref": "#/components/schemas/StudioActionContext"
          },
          "render_parameters": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Source-safe PSD or 2D render parameters emitted by the completed customize action."
          },
          "artwork_sources": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/StudioArtworkSource"
                },
                "type": "array",
                "maxItems": 8
              },
              {
                "type": "null"
              }
            ],
            "description": "Public artwork URLs per target, as emitted by Studio. Forwarded unchanged from the editor message; echoed back on the receipt."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "mockup_uuid",
          "render_uuid"
        ],
        "title": "StudioActionPayload"
      },
      "StudioActionReceipt": {
        "properties": {
          "version": {
            "type": "integer",
            "const": 1
          },
          "request_id": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33"
            ]
          },
          "message_session_id": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "studio.mockup-saved",
              "studio.design-submitted"
            ]
          },
          "mockup_type": {
            "type": "string",
            "enum": [
              "psd",
              "2d"
            ]
          },
          "session_kind": {
            "type": "string",
            "enum": [
              "setup",
              "customize"
            ]
          },
          "action_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "add-to-cart"
            ]
          },
          "action_context": {
            "$ref": "#/components/schemas/StudioActionContext"
          },
          "mockup_uuid": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "c315f78f-d2c7-4541-b240-a9372842de94"
            ]
          },
          "render_uuid": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354"
            ]
          },
          "render_parameters": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Server-confirmed, source-safe PSD or 2D parameters bound to the successful render."
          },
          "artwork_sources": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/StudioArtworkSource"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The artwork URLs supplied with this action, returned unchanged. Not stored and not server-confirmed: on a replayed action this echoes what the replay attempt sent, and a differing value does not make the action conflict."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "version",
          "request_id",
          "message_session_id",
          "type",
          "mockup_type",
          "session_kind",
          "action_context",
          "mockup_uuid",
          "render_uuid"
        ],
        "title": "StudioActionReceipt"
      },
      "StudioActionRequest": {
        "properties": {
          "version": {
            "type": "integer",
            "const": 1
          },
          "request_id": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33"
            ]
          },
          "message_session_id": {
            "type": "string",
            "format": "uuid",
            "examples": [
              "7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "studio.mockup-saved",
              "studio.design-submitted"
            ]
          },
          "payload": {
            "$ref": "#/components/schemas/StudioActionPayload"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "version",
          "request_id",
          "message_session_id",
          "type",
          "payload"
        ],
        "title": "StudioActionRequest",
        "example": {
          "message_session_id": "7d1b4a90-2e63-4f18-bb27-1c9a0e4d7f52",
          "payload": {
            "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
            "render_uuid": "9b2e5f31-4c8d-4a76-8f0b-2d7e6c1a9354"
          },
          "request_id": "0f9c2d1e-7b44-4a2f-9a0d-6c1f2b8e5d33",
          "type": "studio.mockup-saved",
          "version": 1
        }
      },
      "StudioActionResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "const": true,
            "default": true
          },
          "replayed": {
            "type": "boolean",
            "examples": [
              false
            ]
          },
          "receipt": {
            "$ref": "#/components/schemas/StudioActionReceipt"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "replayed",
          "receipt"
        ],
        "title": "StudioActionResponse"
      },
      "StudioArtworkInput": {
        "properties": {
          "target_uuid": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
            "description": "Smart Object id for PSD. For 2D, either a saved print area id or a product surface id. The same field accepts both.",
            "examples": [
              "7c1f4b02-9d3e-4a68-b5c1-0e2d9a6f83b4"
            ]
          },
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "description": "HTTPS artwork URL. Ignored when base64 is also supplied.",
            "examples": [
              "https://cdn.example.com/design.png"
            ]
          },
          "base64": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 89478488,
                "minLength": 4
              },
              {
                "type": "null"
              }
            ],
            "description": "Canonical raw base64 artwork, up to 64 MB decoded. Takes precedence when url is also supplied."
          },
          "placement": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/StudioSeedPlacement"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional opening placement for this design, in percentages of the target's own region. Omit it to open where the editor opens today."
          },
          "adjustments": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/StudioSeedAdjustments"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional opening appearance for this design. Send back what a finished session reported to carry a look from one mockup of a product to the next. Omit it to open at the editor's own values. A PSD target reads brightness, contrast, saturation, vibrance, opacity and blur; a photo target reads opacity and blend_mode."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "target_uuid"
        ],
        "title": "StudioArtworkInput"
      },
      "StudioArtworkSource": {
        "properties": {
          "uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "6f1c8d42-0b57-4e39-a6d8-3c95b1e740af"
            ]
          },
          "surface_uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "smart_object_uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ]
          },
          "url": {
            "type": "string",
            "maxLength": 2048,
            "examples": [
              "https://cdn.example.com/design-cutout.png"
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "url"
        ],
        "title": "StudioArtworkSource",
        "description": "Public URL of the artwork a shopper ended up with, per target.\n\nStudio emits this alongside render_parameters so the host page can keep the\nimage the shopper paid for -- background-removal cutouts in particular, which\nthe render request itself carries as inline data and therefore cannot name.\n\nIt is caller-supplied and echoed back verbatim, exactly like action_context:\nthe server does not attest that these URLs belong to this render, and does\nnot store them on the receipt. Never put a URL from here into\nrender_parameters -- those are hash-bound to the render and any edit there\nmakes the cart call fail."
      },
      "StudioConfigPatch": {
        "properties": {
          "primaryColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#0f172a"
          },
          "accentColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#da7756"
          },
          "backgroundColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#f1f5f9"
          },
          "panelBackground": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#ffffff"
          },
          "textColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#0f172a"
          },
          "borderColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#e2e8f0"
          },
          "successColor": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#[0-9A-Fa-f]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "default": "#16a34a"
          },
          "borderRadius": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 20.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "default": 10
          },
          "logoUrl": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "https://your-store.example.com/assets/logo.png"
            ]
          },
          "fontFamily": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 64,
                "minLength": 1,
                "pattern": "^[A-Za-z0-9][A-Za-z0-9 ,._-]*$"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "Inter, sans-serif"
            ]
          },
          "headerText": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96
              },
              {
                "type": "null"
              }
            ],
            "default": "Customize Your Design"
          },
          "uploadText": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Drop image or click to upload"
          },
          "secondaryActionLabel": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Render Preview"
          },
          "loadingText": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Adding..."
          },
          "successText": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Added!"
          },
          "psdPrimaryActionLabel": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Add to Cart"
          },
          "twoDSetupPrimaryActionLabel": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Save Mockup"
          },
          "twoDCustomizePrimaryActionLabel": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 96,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "default": "Add to Cart"
          },
          "psdShowAdjustments": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowColorOverlay": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowTextLayers": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowFitMode": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowPosition": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowSize": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowRotation": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowFlip": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowExportOptions": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowZoomControls": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdShowUndoRedo": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdAutoRender": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "psdAutoRenderDelay": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 3000.0,
                "minimum": 300.0
              },
              {
                "type": "null"
              }
            ],
            "default": 800
          },
          "autoDesignCallback": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": false
          },
          "psdLayout": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "full",
                  "compact"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": "full"
          },
          "twoDShowArtwork": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowFill": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowBlend": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowOpacity": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowTransform": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowZoom": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowExport": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "twoDShowBackgroundRemoval": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "colorPalette": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PaletteColour"
                },
                "type": "array",
                "maxItems": 96,
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              [
                {
                  "hex": "#1a1a1a",
                  "label": "Black"
                },
                {
                  "hex": "#f5f5f5",
                  "label": "Natural"
                }
              ]
            ]
          },
          "showClose": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": true
          },
          "theme": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "light",
                  "dark"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": "light"
          },
          "locale": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "en",
                  "tr"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": "en"
          },
          "maxFileSize": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 50.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "default": 15
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "StudioConfigPatch"
      },
      "StudioConfigResponse": {
        "properties": {
          "success": {
            "type": "boolean",
            "default": true
          },
          "config": {
            "additionalProperties": true,
            "type": "object",
            "default": {}
          },
          "config_version": {
            "type": "integer",
            "default": 0,
            "examples": [
              3
            ]
          }
        },
        "type": "object",
        "title": "StudioConfigResponse"
      },
      "StudioSeedAdjustments": {
        "properties": {
          "brightness": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": -100.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Brightness, -100 to 100. Omit for the editor's own.",
            "examples": [
              10
            ]
          },
          "contrast": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": -100.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Contrast, -100 to 100. Omit for the editor's own.",
            "examples": [
              8
            ]
          },
          "saturation": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": -100.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Saturation, -100 to 100. Omit for the editor's own.",
            "examples": [
              -5
            ]
          },
          "vibrance": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": -100.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Vibrance, -100 to 100. Omit for the editor's own.",
            "examples": [
              15
            ]
          },
          "opacity": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Opacity, 0 to 100. Omit for the editor's own.",
            "examples": [
              80
            ]
          },
          "blur": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 20.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Blur, 0 to 20, in half steps. Omit for the editor's own.",
            "examples": [
              2.5
            ]
          },
          "blend_mode": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "multiply",
                  "normal",
                  "screen",
                  "lighten",
                  "soft_light",
                  "overlay",
                  "darken"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How the artwork sits on the product surface. Photo targets only. Omit for the editor's own."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "StudioSeedAdjustments",
        "description": "How a design looks when the editor opens it.\n\nOne spelling for both target kinds, because this is a request rather than\na report: the merchant asks for an opening appearance and the session\neither honours it or refuses to open. Which keys a target can honour\ndiffers, and `reject_unsupported_adjustments` is where that is decided --\nthe same division the placement beside it already uses, and for the same\nreason. A model per surface would put the difference in the type system,\nwhere the single response that echoes this has no way to consult it.\n\nNothing carries a default. A placement can afford them because `box` is\nrequired, so that object never exists half-filled; this one has no\nrequired key at all, so a default would be a value the merchant never\nsent, echoed back as though they had. That is the shape of the outage the\nplacement echo was rewritten to stop.\n\nThe bounds are the ones the editor's own controls span, not the wider set\nthe finished image accepts. Seeding a brightness the control cannot reach\nopens a session whose preview disagrees with its result from the first\nframe, and the shopper -- the only person present -- has no way to know.\nRefusing is the answer `reject_unsupported_placement` already gives to a\nseed the surface cannot honour."
      },
      "StudioSeedAutoBox": {
        "properties": {
          "mode": {
            "type": "string",
            "const": "auto"
          },
          "coverage": {
            "type": "integer",
            "maximum": 100.0,
            "minimum": 10.0,
            "description": "Percentage of the target region the design is allowed to fill.",
            "examples": [
              85
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "mode",
          "coverage"
        ],
        "title": "StudioSeedAutoBox",
        "description": "An allowance. The artwork keeps its own proportions inside it."
      },
      "StudioSeedManualBox": {
        "properties": {
          "mode": {
            "type": "string",
            "const": "manual"
          },
          "width_percent": {
            "type": "number",
            "maximum": 300.0,
            "exclusiveMinimum": 0.0,
            "description": "Percentage of the target region's WIDTH.",
            "examples": [
              80.0
            ]
          },
          "height_percent": {
            "type": "number",
            "maximum": 300.0,
            "exclusiveMinimum": 0.0,
            "description": "Percentage of the target region's HEIGHT.",
            "examples": [
              60.0
            ]
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "mode",
          "width_percent",
          "height_percent"
        ],
        "title": "StudioSeedManualBox",
        "description": "The box itself. The only spelling that can carry a ratio of its own."
      },
      "StudioSeedPlacement": {
        "properties": {
          "box": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StudioSeedAutoBox"
              },
              {
                "$ref": "#/components/schemas/StudioSeedManualBox"
              }
            ],
            "description": "How large the design starts: an allowance, or the box itself.",
            "examples": [
              {
                "coverage": 85,
                "mode": "auto"
              }
            ],
            "discriminator": {
              "propertyName": "mode",
              "mapping": {
                "auto": "#/components/schemas/StudioSeedAutoBox",
                "manual": "#/components/schemas/StudioSeedManualBox"
              }
            }
          },
          "fit": {
            "type": "string",
            "enum": [
              "fill",
              "fit",
              "crop"
            ],
            "description": "How the artwork's pixels meet the box.",
            "default": "fit"
          },
          "offset_x_percent": {
            "type": "number",
            "maximum": 100.0,
            "minimum": -100.0,
            "description": "Percentage of the region WIDTH, from the region centre, positive right.",
            "default": 0,
            "examples": [
              12.5
            ]
          },
          "offset_y_percent": {
            "type": "number",
            "maximum": 100.0,
            "minimum": -100.0,
            "description": "Percentage of the region HEIGHT, from the region centre, positive down.",
            "default": 0,
            "examples": [
              -8.0
            ]
          },
          "rotation": {
            "type": "number",
            "maximum": 360.0,
            "minimum": -360.0,
            "description": "Degrees about the box centre, clockwise positive.",
            "default": 0,
            "examples": [
              -15.0
            ]
          },
          "flip_horizontal": {
            "type": "boolean",
            "description": "Flip artwork horizontally (left-right mirror)",
            "default": false
          },
          "flip_vertical": {
            "type": "boolean",
            "description": "Flip artwork vertically (top-bottom mirror)",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "box"
        ],
        "title": "StudioSeedPlacement",
        "description": "Where a locked design starts, in the units of the region that holds it.\n\nEvery length here is a percentage of the target's own region -- the print\narea's bounding box for 2D, the Smart Object's embedded frame for PSD --\nbecause that is the one denominator both sides already have without a\nsecond round trip. Offsets run from the region CENTRE, positive right and\ndown, and the unit lives in the field name so a reader who has only ever\nseen an example still cannot mistake it for pixels.\n\n``box`` is one branch or the other, never a mixture: a width with no height\nis not a smaller request, it is an unanswerable one, and the branch makes\nit unsendable rather than merely rejected.\n\nThis is a starting point, not a lock. The customer may move it afterwards."
      },
      "SudoAIPlacement": {
        "properties": {
          "position": {
            "type": "string",
            "enum": [
              "center",
              "top_left",
              "top_center",
              "top_right",
              "center_left",
              "center_right",
              "left_center",
              "right_center",
              "bottom_left",
              "bottom_center",
              "bottom_right"
            ],
            "description": "Predefined position within print area",
            "default": "center"
          },
          "coverage": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 100.0,
                "minimum": 10.0
              },
              {
                "type": "null"
              }
            ],
            "description": "How much of the product surface the artwork spans, 10 to 100. Spans the whole surface by default. Belongs to a surface_uuid target, and cannot be combined with an explicit width and height."
          },
          "fit": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "fill",
                  "fit",
                  "crop"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "How the artwork meets the print area. 'fit' scales it until it fits inside and keeps its proportions, which is the default and can leave empty space. 'fill' stretches it to the edges and does not keep proportions. 'crop' covers the area and cuts the overflow, keeping proportions. 'contain' and 'cover' are the older names for 'fit' and 'crop' and are still accepted. Always targets the whole print area. Belongs to a uuid target, and cannot be combined with an explicit width and height."
          },
          "offset_x": {
            "type": "number",
            "description": "Horizontal offset in print-area pixels, measured from the anchor that 'position' picks, positive right. With the default position of 'center' that anchor is the middle of the print area.",
            "default": 0
          },
          "offset_y": {
            "type": "number",
            "description": "Vertical offset in print-area pixels, measured from the anchor that 'position' picks, positive down. With the default position of 'center' that anchor is the middle of the print area.",
            "default": 0
          },
          "width": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 30000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork width in target pixels. Must be sent together with 'height'. An exact box belongs to either kind of target: send it instead of 'fit' on a print area, or instead of 'coverage' on a surface. Width and height are independent, so any aspect ratio is allowed."
          },
          "height": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 30000.0,
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork height in target pixels. Must be sent together with 'width'. An exact box belongs to either kind of target: send it instead of 'fit' on a print area, or instead of 'coverage' on a surface. Width and height are independent, so any aspect ratio is allowed."
          },
          "rotation": {
            "type": "number",
            "maximum": 360.0,
            "minimum": -360.0,
            "description": "Rotation in degrees (clockwise positive)",
            "default": 0
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "SudoAIPlacement",
        "description": "Deprecated name for `PhotoMockupPlacement`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "SudoAIPrintFile": {
        "properties": {
          "export_path": {
            "type": "string",
            "description": "Public URL of the rendered output"
          },
          "duration_ms": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Render duration in milliseconds"
          },
          "export_format": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Output format used (png, jpg, webp)"
          }
        },
        "type": "object",
        "required": [
          "export_path"
        ],
        "title": "SudoAIPrintFile",
        "description": "Deprecated name for `PhotoMockupPrintFile`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "SudoAIRenderResponseData": {
        "properties": {
          "print_files": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintFile"
            },
            "type": "array",
            "description": "List of rendered outputs"
          },
          "render_uuid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Identifier for this render."
          }
        },
        "type": "object",
        "required": [
          "print_files"
        ],
        "title": "SudoAIRenderResponseData",
        "description": "Deprecated name for `PhotoMockupRenderResult`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "TextLayer": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the text layer",
            "examples": [
              "c7d41f6a-2b58-4e93-9a10-6f83b2c5d417"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name of the text layer",
            "examples": [
              "Brand name"
            ]
          },
          "text_content": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Current text content of the layer",
            "examples": [
              "SUMMER CLUB"
            ]
          },
          "font_postscript_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "PostScript name of the font used by this layer",
            "examples": [
              "Montserrat-Bold"
            ]
          },
          "font_size": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Effective font size in pixels at the PSD's native resolution",
            "examples": [
              120.0
            ]
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Text color as hex (e.g. #FFFFFF)",
            "examples": [
              "#FFFFFF"
            ]
          },
          "font_available": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether the layer's font is available for editable rendering. When false, edits render with a default font unless a font is supplied."
          },
          "is_editable": {
            "type": "boolean",
            "description": "Whether this layer's text can be replaced at render time",
            "default": false
          },
          "segment_count": {
            "type": "integer",
            "description": "Number of styled segments in this layer. 1 = single-style (edit with 'text'); 2+ = styled segments (edit with 'segments', each segment keeps its own styling)",
            "default": 1
          },
          "segments": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/TextSegment"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "The layer's styled segments, present when segment_count > 1. Override any subset by index at render time; omitted segments keep their original text."
          },
          "visible": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether the layer is shown by default in the source file. A hidden layer can still be targeted; its text then renders. Null when unknown (older mockups)."
          },
          "has_stroke_effect": {
            "type": "boolean",
            "description": "Whether this text layer has at least one outline of its own.",
            "default": false
          },
          "stroke_count": {
            "type": "integer",
            "description": "Number of outlines owned by this text layer, in front-to-back stroke_color order.",
            "default": 0
          },
          "has_color_overlay": {
            "type": "boolean",
            "description": "Whether the layer's visible color comes from a color effect. When true, a color override changes that effect's color.",
            "default": false
          },
          "has_clipped_artwork": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether some content in the design is clipped to this layer's letters. When true, replacing this text also re-shapes that clipped content to the new letters. Null when it could not be determined for this mockup."
          },
          "suggested_edit_together": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUIDs of other text layers that carry the same text stacked with this one, such as a fill plus an outline copy. Sending the same replacement text to all of them keeps the design consistent. Advisory only: each layer is still edited on its own by UUID, never linked automatically. Null when it could not be determined.",
            "examples": [
              [
                "a2f9c481-30d7-4b6e-8c52-1d9e7f34ab60"
              ]
            ]
          },
          "enclosing_group_layers": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUIDs of enclosing group layers whose outlines also affect this text layer, nearest first. Advisory only: each group is edited separately through group_layers. Null when it could not be determined.",
            "examples": [
              [
                "5e8b0c72-9a41-4d36-b7f8-2c60d1e94537"
              ]
            ]
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "name"
        ],
        "title": "TextLayer",
        "description": "Text layer metadata in upload/detail responses"
      },
      "TextLayerInput": {
        "properties": {
          "uuid": {
            "type": "string",
            "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
            "description": "UUID of the text layer to update (from the upload/detail response text_layers list)",
            "examples": [
              "4d7f1a2e-6c83-4b19-9e5a-2f0c8d3b6471"
            ]
          },
          "text": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 500,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "Replacement text (1-500 characters) for single-style layers (segment_count = 1)",
            "examples": [
              "Isabella"
            ]
          },
          "segments": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/TextSegmentInput"
                },
                "type": "array",
                "maxItems": 32,
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "Styled-segment overrides for multi-style layers (segment_count > 1). Override any subset by index; omitted segments keep their original text."
          },
          "font": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "description": "Font to render with: a font uuid from GET /fonts, or a PostScript name. Single-style layers only. Omit to keep the layer's original font.",
            "examples": [
              "OpenSans-Bold"
            ]
          },
          "font_size": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 2000.0,
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "description": "Font size in pixels at the mockup's native resolution. Single-style layers only. Omit to keep the original size.",
            "examples": [
              48.0
            ]
          },
          "color": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^#?[0-9a-fA-F]{6}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "Text color as hex, e.g. #1A1A1A. Single-style layers only. Applies to the color you see: when the layer's visible color comes from a color effect, that effect takes the new color. Omit to keep the original color.",
            "examples": [
              "#1A1A1A"
            ]
          },
          "stroke_color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Color for this text layer's own outlines. Send a hex value like \"#FFFFFF\" to recolor the front outline, or a list in stroke_count order (front to back). Use null to keep an outline's original color; extra entries are ignored. Layers with no outlines ignore this value with a warning. Single-style layers only. Omit to keep all original outline colors.",
            "examples": [
              "#FFFFFF",
              [
                "#FFFFFF",
                null
              ]
            ]
          },
          "fit": {
            "type": "string",
            "enum": [
              "shrink",
              "clip",
              "overflow"
            ],
            "description": "How longer replacement text is handled for single-style point text: 'overflow' (default) preserves the designed size and may extend beyond the original area; 'shrink' scales the text down to fit; 'clip' preserves the size and cuts it at the last character that fits. Paragraph text continues to wrap within its box.",
            "default": "overflow"
          },
          "vertical_align": {
            "type": "string",
            "enum": [
              "top",
              "bottom",
              "center"
            ],
            "description": "Where text that 'fit': 'shrink' scaled down sits vertically within the original text area: 'top' (default) keeps the designed position, 'center' centers it in the area, 'bottom' aligns it to the area's bottom edge. Only applies when shrinking actually occurs; single-style point text only.",
            "default": "top"
          }
        },
        "type": "object",
        "required": [
          "uuid"
        ],
        "title": "TextLayerInput",
        "description": "Text layer override for rendering",
        "example": {
          "color": "#FFFFFF",
          "text": "Isabella",
          "uuid": "323e4567-e89b-12d3-a456-426614174002"
        }
      },
      "TextSegment": {
        "properties": {
          "index": {
            "type": "integer",
            "description": "Stable segment position within the layer (0-based)"
          },
          "text": {
            "type": "string",
            "description": "The segment's current text",
            "default": ""
          },
          "font_postscript_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "PostScript name of the segment's font"
          },
          "font_size": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "description": "Segment font size in pixels at the PSD's native resolution"
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Segment text color as hex (e.g. #FFFFFF)"
          }
        },
        "type": "object",
        "required": [
          "index"
        ],
        "title": "TextSegment",
        "description": "One styled segment of a multi-style text layer (upload/detail responses)."
      },
      "TextSegmentInput": {
        "properties": {
          "index": {
            "type": "integer",
            "maximum": 31.0,
            "minimum": 0.0,
            "description": "Segment to replace (0-based, from the layer's segments list)"
          },
          "text": {
            "type": "string",
            "maxLength": 200,
            "minLength": 1,
            "description": "Replacement text for this segment (1-200 characters). The segment keeps its own font, size, and color."
          }
        },
        "type": "object",
        "required": [
          "index",
          "text"
        ],
        "title": "TextSegmentInput",
        "description": "One styled-segment override for a multi-style text layer."
      },
      "ThumbnailSize": {
        "properties": {
          "width": {
            "type": "integer",
            "description": "Thumbnail width in pixels"
          },
          "url": {
            "type": "string",
            "description": "Public URL to the thumbnail image"
          }
        },
        "type": "object",
        "required": [
          "width",
          "url"
        ],
        "title": "ThumbnailSize",
        "description": "Thumbnail with size and URL"
      },
      "TwoDMockupCreateRequest": {
        "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": "TwoDMockupCreateRequest",
        "description": "Deprecated name for `PhotoMockupCreateRequest`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "example": {
          "name": "Front view",
          "source_url": "https://example.com/product-photo.jpg"
        },
        "deprecated": true
      },
      "TwoDMockupPrintAreaRender": {
        "properties": {
          "uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of a saved print area, a bounded zone drawn on a product.",
            "examples": [
              "19be48d4-c810-4420-86e3-7ec2a4d85571"
            ]
          },
          "surface_uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "UUID of a printable product surface. A product carrying saved print areas still has one, and it is a separate render target from them.",
            "examples": [
              "733ee99a-f41f-4b9b-bf33-2ffa489f96db"
            ]
          },
          "base64": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Base64-encoded artwork image."
          },
          "artwork_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Artwork image URL",
            "examples": [
              "https://example.com/design.png"
            ]
          },
          "color": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Solid color as a hex code (e.g., '#FF0000'), or the name of a colour saved on this mockup (e.g., 'blue jean'). Names match exactly and are set with PATCH /api/v1/photo-mockups/{uuid}.",
            "examples": [
              "#6A8296"
            ]
          },
          "adjustments": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PhotoMockupAdjustments"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional visual adjustments for the artwork."
          },
          "placement": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PhotoMockupPlacement"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where the artwork sits and how big it is. position, offset_x, offset_y and rotation apply to either target. Sizing follows the target: coverage on a surface_uuid target, and either fit or an explicit width and height on a uuid target."
          },
          "flip_horizontal": {
            "type": "boolean",
            "description": "Flip artwork horizontally (left-right mirror)",
            "default": false
          },
          "flip_vertical": {
            "type": "boolean",
            "description": "Flip artwork vertically (top-bottom mirror)",
            "default": false
          },
          "remove_background": {
            "type": "boolean",
            "description": "Remove the image background before placing the artwork; the subject is isolated onto a clean transparent cutout. Adds 25 credits per artwork to the render cost.",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "TwoDMockupPrintAreaRender",
        "description": "Deprecated name for `PhotoMockupPrintAreaRender`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "TwoDMockupRenderByPathRequest": {
        "properties": {
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintAreaRender"
            },
            "type": "array",
            "maxItems": 8,
            "minItems": 1,
            "description": "Artwork configuration per render target. Use uuid for a saved print area, and surface_uuid for a whole product surface. A product can be rendered either way, and saving a print area on it does not take its surface away."
          },
          "export_options": {
            "$ref": "#/components/schemas/ExportOptions",
            "description": "Export configuration for format, size and quality. Every field has a default, so the whole object is optional."
          },
          "is_async": {
            "type": "boolean",
            "description": "If true, the render 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 rendered image URL on success. If false (default), the render runs synchronously and returns the result.",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "print_areas"
        ],
        "title": "TwoDMockupRenderByPathRequest",
        "description": "Deprecated name for `PhotoMockupRender`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "example": {
          "export_options": {
            "image_format": "webp",
            "image_size": 1920,
            "quality": 95
          },
          "print_areas": [
            {
              "adjustments": {
                "blend_mode": "multiply",
                "opacity": 90
              },
              "artwork_url": "https://example.com/design.png",
              "placement": {
                "fit": "fit",
                "position": "center"
              },
              "uuid": "223e4567-e89b-12d3-a456-426614174001"
            }
          ]
        },
        "deprecated": true
      },
      "TwoDMockupRenderResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/PhotoMockupRenderResult",
            "description": "Rendered output files"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "TwoDMockupRenderResponse",
        "description": "Deprecated name for `PhotoMockupRenderResponse`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "TwoDPrintAreaInput": {
        "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": "TwoDPrintAreaInput",
        "description": "Deprecated name for `PhotoMockupPrintAreaInput`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "deprecated": true
      },
      "TwoDPrintAreasUpdateRequest": {
        "properties": {
          "print_areas": {
            "items": {
              "$ref": "#/components/schemas/PhotoMockupPrintAreaInput"
            },
            "type": "array",
            "maxItems": 8,
            "minItems": 0,
            "description": "Up to eight printable areas; array order becomes sort order. An empty array saves the mockup without bounded placement zones."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "print_areas"
        ],
        "title": "TwoDPrintAreasUpdateRequest",
        "description": "Deprecated name for `PhotoMockupPrintAreasUpdate`. Same shape, kept so a client generated from an earlier spec keeps the type name it already has.",
        "example": {
          "print_areas": [
            {
              "points": [
                [
                  200,
                  150
                ],
                [
                  600,
                  150
                ],
                [
                  620,
                  550
                ],
                [
                  180,
                  550
                ]
              ]
            }
          ]
        },
        "deprecated": true
      },
      "UpdateStudioConfigRequest": {
        "properties": {
          "config_version": {
            "type": "integer",
            "minimum": 0.0,
            "examples": [
              3
            ]
          },
          "config": {
            "$ref": "#/components/schemas/StudioConfigPatch"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "config_version",
          "config"
        ],
        "title": "UpdateStudioConfigRequest",
        "example": {
          "config": {
            "accentColor": "#FF5733",
            "theme": "dark"
          },
          "config_version": 3
        }
      },
      "UploadRequest": {
        "properties": {
          "psd_file_url": {
            "type": "string",
            "minLength": 1,
            "description": "URL to the PSD file to upload. HTTP/HTTPS URLs only. Supports up to Adobe's official PSD file size limit, 300s download timeout.",
            "examples": [
              "https://example.com/heavyweight-tee.psd"
            ]
          },
          "psd_name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ],
            "description": "Name for the mockup template (auto-generated if not provided)",
            "examples": [
              "Heavyweight tee front"
            ]
          },
          "is_async": {
            "type": "boolean",
            "description": "If true, the upload 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 upload runs synchronously and returns the mockup.",
            "default": false
          }
        },
        "type": "object",
        "required": [
          "psd_file_url"
        ],
        "title": "UploadRequest",
        "description": "The PSD to ingest and what to call it.",
        "example": {
          "psd_file_url": "https://example.com/heavyweight-tee.psd",
          "psd_name": "Heavyweight tee front"
        }
      },
      "UploadResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UploadResponseData",
            "description": "Response data"
          },
          "success": {
            "type": "boolean",
            "description": "Success status",
            "default": true
          },
          "message": {
            "type": "string",
            "description": "Optional message about the operation",
            "default": ""
          },
          "warnings": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/UploadWarning"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "description": "Non-fatal advisories about this upload (e.g. hidden smart object layers that are not exposed for personalization). Omitted when none."
          }
        },
        "type": "object",
        "required": [
          "data"
        ],
        "title": "UploadResponse",
        "description": "The ingested mockup with every layer you can address in a render. specification",
        "example": {
          "data": {
            "collections": [],
            "group_layers": [],
            "height": 5000,
            "name": "Heavyweight tee front",
            "smart_objects": [
              {
                "blend_mode": "multiply",
                "layer_name": "Front print",
                "name": "Front print",
                "position": {
                  "height": 3413,
                  "width": 3000,
                  "x": 512,
                  "y": 730
                },
                "print_area_presets": [
                  {
                    "name": "Default",
                    "position": {
                      "height": 3413,
                      "width": 3000,
                      "x": 0,
                      "y": 0
                    },
                    "size": {
                      "height": 3413,
                      "width": 3000
                    },
                    "thumbnails": [],
                    "uuid": "d07f5b18-2c94-4e83-a6b1-95f3c8e27a40"
                  }
                ],
                "quad": [
                  [
                    512.0,
                    742.0
                  ],
                  [
                    3512.0,
                    730.0
                  ],
                  [
                    3499.0,
                    4143.0
                  ],
                  [
                    524.0,
                    4131.0
                  ]
                ],
                "size": {
                  "height": 3413,
                  "width": 3000
                },
                "uuid": "b41a7e52-93c8-4d61-8f07-2ae5c9d04713"
              }
            ],
            "text_layers": [],
            "thumbnail": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_720.webp",
            "thumbnails": [
              {
                "url": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_720.webp",
                "width": 720
              },
              {
                "url": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_480.webp",
                "width": 480
              },
              {
                "url": "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_240.webp",
                "width": 240
              }
            ],
            "uuid": "8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8",
            "width": 4000
          },
          "message": "",
          "success": true
        }
      },
      "UploadResponseData": {
        "properties": {
          "uuid": {
            "type": "string",
            "description": "Unique identifier for the mockup",
            "examples": [
              "8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8"
            ]
          },
          "name": {
            "type": "string",
            "description": "Name of the mockup",
            "examples": [
              "Heavyweight tee front"
            ]
          },
          "thumbnail": {
            "type": "string",
            "description": "Main thumbnail URL (720px width). Empty string if generation failed.",
            "default": "",
            "examples": [
              "https://cdn.sudomock.com/mockup-assets/8f2c1d90-6b4e-4a37-9e55-0d1c7a3f21b8/thumbnails/thumb_720.webp"
            ]
          },
          "width": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Always populated after successful upload. Represents original PSD canvas width in pixels.",
            "examples": [
              4000
            ]
          },
          "height": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "description": "Always populated after successful upload. Represents original PSD canvas height in pixels.",
            "examples": [
              5000
            ]
          },
          "smart_objects": {
            "items": {
              "$ref": "#/components/schemas/SmartObjectResponse"
            },
            "type": "array",
            "description": "List of smart objects in the PSD"
          },
          "text_layers": {
            "items": {
              "$ref": "#/components/schemas/TextLayer"
            },
            "type": "array",
            "description": "Text layers detected in the PSD. Editable layers accept text replacement at render time."
          },
          "group_layers": {
            "items": {
              "$ref": "#/components/schemas/GroupLayer"
            },
            "type": "array",
            "description": "Group layers whose outlines can be recolored. Changing a group outline affects everything inside that group; groups not listed keep their authored effects."
          },
          "collections": {
            "items": {},
            "type": "array",
            "description": "Reserved for future use. Currently always empty."
          },
          "thumbnails": {
            "items": {
              "$ref": "#/components/schemas/ThumbnailSize"
            },
            "type": "array",
            "description": "Array of thumbnail URLs at different sizes"
          }
        },
        "type": "object",
        "required": [
          "uuid",
          "name",
          "smart_objects"
        ],
        "title": "UploadResponseData",
        "description": "Data payload in upload response"
      },
      "UploadWarning": {
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable advisory code (PSD_HIDDEN_SMART_OBJECTS, FREE_PSD_RETENTION, PSD_LIGHT_ADJUSTMENT_UNSUPPORTED)"
          },
          "message": {
            "type": "string",
            "description": "Human-readable, non-fatal advisory"
          }
        },
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "title": "UploadWarning",
        "description": "Non-fatal advisory attached to a successful upload.\n\nThree codes today, and they are INDEPENDENT -- one upload can earn several:\n  - PSD_LIGHT_ADJUSTMENT_UNSUPPORTED: the PSD carries a Photoshop 27.10 Light\n    adjustment layer, which renders read as plain Brightness/Contrast and so\n    drop its exposure lift (renders come out darker than Photoshop).\n  - PSD_HIDDEN_SMART_OBJECTS: the PSD carries hidden smart object layers that\n    are not exposed for personalization.\n  - FREE_PSD_RETENTION: the account is in trial, so this uploaded template is\n    removed after N days without a render. Emitted only for an account the\n    retention sweep can actually reach; a funded account never sees it.\n\n`code` is API surface -- integrators switch on it, so it is stable, and the\nmessage is the part that may be reworded."
      },
      "VideoOptions": {
        "properties": {
          "duration_seconds": {
            "type": "integer",
            "maximum": 15.0,
            "minimum": 1.0,
            "description": "Clip length in seconds chosen by the customer. Must be one of the supported durations; the endpoint rejects an unsupported value with 400. The credit cost scales with this value.",
            "default": 4
          },
          "audio": {
            "type": "boolean",
            "description": "Generate sound with the clip. Default OFF (muted clips are cheaper). Audio increases the credit cost on models that charge an audio premium. Note: motion='showcase' always includes sound, so the endpoint treats it as audio=true and prices it accordingly.",
            "default": false
          },
          "motion": {
            "type": "string",
            "enum": [
              "ambient",
              "showcase"
            ],
            "description": "'ambient' = subtle looping hero motion that keeps the print readable (muted unless audio=true); 'showcase' = one deliberate cinematic camera/product move, always with sound (priced as audio=true).",
            "default": "ambient"
          },
          "advanced_model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Advanced override for the automatic quality selection. Unsupported values are rejected. null = automatic (recommended)."
          }
        },
        "type": "object",
        "title": "VideoOptions",
        "description": "Animation options for a POST /renders/video request.\n\nThe still is produced from the same mockup_uuid + smart_objects payload as a\nnormal render, then animated into a short video. SudoMock picks the best video\nmodel for the image automatically; `advanced_model` is an optional override.\n\nYou choose `duration_seconds` and `audio`, and the credit cost scales with both.\n`duration_seconds` must be one of the chosen model's allowed durations, or the\nendpoint returns 400 INVALID_VIDEO_DURATION otherwise. The 1..15 range here is a\ncoarse guard; the exact allowed set depends on the model."
      },
      "VideoRenderRequest": {
        "properties": {
          "mockup_uuid": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
              },
              {
                "type": "null"
              }
            ],
            "description": "RENDER MODE: UUID of the mockup to animate (from GET /api/v1/psd-mockups or POST /api/v1/psd/upload). Required in render mode; omit in raw-image mode."
          },
          "smart_objects": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/SmartObjectInput"
                },
                "type": "array",
                "minItems": 1
              },
              {
                "type": "null"
              }
            ],
            "description": "RENDER MODE: smart objects with their assets, identical to a still render (at least 1 required). Required in render mode; omit in raw-image mode."
          },
          "export_options": {
            "$ref": "#/components/schemas/ExportOptions",
            "description": "RENDER MODE: still-render export configuration (the i2v input frame). Format/size/quality. Ignored in raw-image mode."
          },
          "image_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "RAW-IMAGE MODE: a public https png/jpg URL to animate directly (general image-to-video, no render). Supply this OR (mockup_uuid + smart_objects), never both."
          },
          "video": {
            "$ref": "#/components/schemas/VideoOptions",
            "description": "Animation options (duration, audio, motion, optional advanced_model override)."
          },
          "webhook": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "description": "Optional completion webhook, e.g. {\"url\": \"https://...\"}. Best-effort push; poll (GET /api/v1/jobs/{job_id}) remains the source of truth."
          }
        },
        "type": "object",
        "title": "VideoRenderRequest",
        "description": "Request body for POST /api/v1/renders/video.\n\nSupply exactly one of two input modes. Render mode (mockup_uuid and\nsmart_objects, optionally export_options) mirrors a still render: the\nstill is produced first, then animated. Raw-image mode\n(image_url) animates a public https png or jpg directly with no render\nstep, and the render fields are ignored.\n\nBoth modes take the video animation options and an optional completion\nwebhook. The call always queues a job; poll GET /api/v1/jobs/{job_id} for\nthe result. Sending both modes, or neither, returns 400.",
        "example": {
          "mockup_uuid": "123e4567-e89b-12d3-a456-426614174000",
          "smart_objects": [
            {
              "asset": {
                "fit": "fill",
                "url": "https://example.com/user-design.png"
              },
              "uuid": "223e4567-e89b-12d3-a456-426614174001"
            }
          ],
          "video": {
            "audio": false,
            "duration_seconds": 4,
            "motion": "ambient",
            "advanced_model": null
          },
          "webhook": {
            "url": "https://example.com/hooks/render-done"
          }
        }
      },
      "WebhookDeliveryDetailResponse": {
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "3d682132-5477-4ffc-b33d-6e750c9c9f1f"
            ]
          },
          "endpoint_id": {
            "type": "string",
            "examples": [
              "b5cd6284-f6a0-4cfc-94df-781353e30dfd"
            ]
          },
          "job_id": {
            "type": "string",
            "examples": [
              "4a4bfe21-d9d2-43a4-9877-b6ca4aec4349"
            ]
          },
          "event_type": {
            "type": "string",
            "examples": [
              "render.succeeded"
            ]
          },
          "status": {
            "type": "string",
            "examples": [
              "failed"
            ]
          },
          "http_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              500
            ]
          },
          "attempt": {
            "type": "integer",
            "examples": [
              0
            ]
          },
          "last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "non-2xx response: 500"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "examples": [
              "2026-09-18T09:24:12.615000Z"
            ]
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "2026-09-18T09:24:12.983000Z"
            ]
          },
          "request_body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "{\"created_at\":\"2026-09-18T09:24:11.482713+00:00\",\"error\":null,\"event\":\"render.succeeded\",\"job_id\":\"4a4bfe21-d9d2-43a4-9877-b6ca4aec4349\",\"kind\":\"render\",\"result_url\":\"https://cdn.sudomock.com/mockup-assets/renders/c315f78f-d2c7-4541-b240-a9372842de94/render_8f2c1d4e.webp\",\"status\":\"succeeded\"}"
            ]
          },
          "request_headers": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "{\"Content-Type\":\"application/json\",\"User-Agent\":\"SudoMock-Webhook/1.0\",\"X-SudoMock-Signature\":\"2b4ddbe7024e2e0e732fb27374c3e0dedda3dbf2392abe78e9785c836f54832b\",\"X-SudoMock-Timestamp\":\"1789723451\"}"
            ]
          },
          "response_body": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "Internal Server Error"
            ]
          },
          "response_headers": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "{\"content-type\":\"text/plain;charset=UTF-8\"}"
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "endpoint_id",
          "job_id",
          "event_type",
          "status",
          "attempt",
          "created_at"
        ],
        "title": "WebhookDeliveryDetailResponse",
        "description": "A single delivery row WITH the captured request/response detail.\n\nReturned ONLY by the per-delivery detail endpoint; the LIST endpoints\n(/deliveries, /events) stay lean: these large fields are fetched on demand,\nnever carried per row. Capture rules (latest attempt; a retry overwrites the\nsame row):\n  - request_body / request_headers  -> captured on EVERY delivery attempt.\n  - response_body / response_headers -> captured ONLY on failed/dead attempts\n    (NULL on success, because a 2xx body is intentionally not stored). response_body\n    is truncated to 16384 chars.\n\nHeaders are stored as JSON strings (both backends; the CF/D1 path stores them\nthe same way) and passed through as strings here, not re-parsed."
      },
      "WebhookDeliveryResponse": {
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "3d682132-5477-4ffc-b33d-6e750c9c9f1f"
            ]
          },
          "endpoint_id": {
            "type": "string",
            "examples": [
              "b5cd6284-f6a0-4cfc-94df-781353e30dfd"
            ]
          },
          "job_id": {
            "type": "string",
            "examples": [
              "4a4bfe21-d9d2-43a4-9877-b6ca4aec4349"
            ]
          },
          "event_type": {
            "type": "string",
            "examples": [
              "render.succeeded"
            ]
          },
          "status": {
            "type": "string",
            "examples": [
              "delivered"
            ]
          },
          "http_status": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              200
            ]
          },
          "attempt": {
            "type": "integer",
            "examples": [
              0
            ]
          },
          "last_error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "examples": [
              "2026-09-18T09:24:12.615000Z"
            ]
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "2026-09-18T09:24:12.983000Z"
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "endpoint_id",
          "job_id",
          "event_type",
          "status",
          "attempt",
          "created_at"
        ],
        "title": "WebhookDeliveryResponse",
        "description": "A single delivery-attempt log row."
      },
      "WebhookEndpointCreateRequest": {
        "properties": {
          "url": {
            "type": "string",
            "maxLength": 2048,
            "minLength": 1,
            "description": "https endpoint URL"
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ]
          },
          "event_types": {
            "items": {
              "type": "string",
              "enum": [
                "render.succeeded",
                "render.failed",
                "upload.succeeded",
                "video.succeeded",
                "video.failed",
                "2d_mockup.ready",
                "2d_mockup.rejected",
                "2d_mockup.failed",
                "2d_render.succeeded",
                "2d_render.failed",
                "photo_mockup.ready",
                "photo_mockup.rejected",
                "photo_mockup.failed",
                "photo_mockup_render.succeeded",
                "photo_mockup_render.failed",
                "webhook.test"
              ]
            },
            "type": "array",
            "description": "Subscribed event types; empty = all events (wildcard)."
          },
          "event_naming": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "legacy",
                  "current"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Which spelling of the photo-mockup events this endpoint receives: 'current' (photo_mockup.*, photo_mockup_render.*) or 'legacy' (2d_mockup.*, 2d_render.*). The payload's kind follows. Omit it and the endpoint is pinned to the spelling event_types is written in: the family names for a list that subscribes to them, otherwise 'legacy', the spelling this contract publishes."
          }
        },
        "type": "object",
        "required": [
          "url"
        ],
        "title": "WebhookEndpointCreateRequest",
        "description": "Create a webhook endpoint. URL SSRF-validation happens in the route (it\nneeds DNS resolution and returns a clean 400); here we only enforce shape.",
        "example": {
          "description": "Production render notifications",
          "event_types": [
            "render.succeeded",
            "render.failed"
          ],
          "url": "https://your-app.example.com/hooks/sudomock"
        }
      },
      "WebhookEndpointResponse": {
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "b5cd6284-f6a0-4cfc-94df-781353e30dfd"
            ]
          },
          "url": {
            "type": "string",
            "examples": [
              "https://your-app.example.com/hooks/sudomock"
            ]
          },
          "secret": {
            "type": "string",
            "description": "Masked: whsec_****<last4>",
            "examples": [
              "whsec_****e865"
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "Production render notifications"
            ]
          },
          "event_types": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "examples": [
              [
                "render.succeeded",
                "render.failed"
              ]
            ]
          },
          "enabled": {
            "type": "boolean",
            "examples": [
              true
            ]
          },
          "event_naming": {
            "type": "string",
            "description": "The event-name spelling this endpoint is pinned to: 'legacy' or 'current'.",
            "default": "legacy"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "examples": [
              "2026-09-18T09:24:11.482713Z"
            ]
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "2026-09-18T09:31:02.117845Z"
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "secret",
          "enabled",
          "created_at"
        ],
        "title": "WebhookEndpointResponse",
        "description": "Endpoint metadata with the secret MASKED (`whsec_****<last4>`)."
      },
      "WebhookEndpointSecretResponse": {
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "b5cd6284-f6a0-4cfc-94df-781353e30dfd"
            ]
          },
          "url": {
            "type": "string",
            "examples": [
              "https://your-app.example.com/hooks/sudomock"
            ]
          },
          "secret": {
            "type": "string",
            "description": "FULL signing secret. Shown only once.",
            "examples": [
              "whsec_cb79146988c2f928cc0760c737c67368080948cdadf7a20c14311290682ee865"
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "Production render notifications"
            ]
          },
          "event_types": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "examples": [
              [
                "render.succeeded",
                "render.failed"
              ]
            ]
          },
          "enabled": {
            "type": "boolean",
            "examples": [
              true
            ]
          },
          "event_naming": {
            "type": "string",
            "description": "The event-name spelling this endpoint is pinned to: 'legacy' or 'current'.",
            "default": "legacy"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "examples": [
              "2026-09-18T09:24:11.482713Z"
            ]
          },
          "updated_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "examples": [
              "2026-09-18T09:31:02.117845Z"
            ]
          }
        },
        "type": "object",
        "required": [
          "id",
          "url",
          "secret",
          "enabled",
          "created_at"
        ],
        "title": "WebhookEndpointSecretResponse",
        "description": "Returned ONLY by create + rotate-secret: the FULL plaintext secret.\n\nOverrides the masked `secret` field with the real value (shown once)."
      },
      "WebhookEndpointUpdateRequest": {
        "properties": {
          "url": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 2048,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ]
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255
              },
              {
                "type": "null"
              }
            ]
          },
          "event_types": {
            "anyOf": [
              {
                "items": {
                  "type": "string",
                  "enum": [
                    "render.succeeded",
                    "render.failed",
                    "upload.succeeded",
                    "video.succeeded",
                    "video.failed",
                    "2d_mockup.ready",
                    "2d_mockup.rejected",
                    "2d_mockup.failed",
                    "2d_render.succeeded",
                    "2d_render.failed",
                    "photo_mockup.ready",
                    "photo_mockup.rejected",
                    "photo_mockup.failed",
                    "photo_mockup_render.succeeded",
                    "photo_mockup_render.failed",
                    "webhook.test"
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ]
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ]
          },
          "event_naming": {
            "anyOf": [
              {
                "type": "string",
                "enum": [
                  "legacy",
                  "current"
                ]
              },
              {
                "type": "null"
              }
            ],
            "description": "Re-pin the endpoint to 'current' or 'legacy' event names once its handler is ready for them."
          }
        },
        "type": "object",
        "title": "WebhookEndpointUpdateRequest",
        "description": "Partial update. Any subset of fields; all optional.",
        "example": {
          "description": "Production render notifications",
          "enabled": true
        }
      }
    },
    "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"
      }
    }
  },
  "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."
    }
  ],
  "servers": [
    {
      "url": "https://api.sudomock.com",
      "description": "Production"
    }
  ]
}