sudomock-com Video mockups API

Render a mockup as a short video.

Operations 1

POST /api/v1/renders/video Render a video mockup #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/sudomock-com:sudomock-com-video-mockups-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

sudomock-com-video-mockups-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: SudoMock Video mockups API
  description: 'Product mockup API. Render PSD templates, turn product photos into reusable mockups, create still images and videos, personalize text with fonts, and manage asynchronous jobs and signed webhooks.


    Every endpoint answers failures with the same envelope, so the status codes, the error_code values and the retry rule are documented once at https://sudomock.com/docs/errors rather than repeated per operation.'
  version: 1.0.0
servers:
- url: https://api.sudomock.com
  description: Production
tags:
- name: Video mockups
  description: Render a mockup as a short video.
paths:
  /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:
                $ref: '#/components/schemas/VideoRenderAcceptedResponse'
      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  }),\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}\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 = {'mockup_uuid': '123e4567-e89b-12d3-a456-426614174000',\n 'smart_objects': [{'asset': {'fit': 'fill',\n                              'url': 'https://example.com/user-design.png'},\n                    'uuid': '223e4567-e89b-12d3-a456-426614174001'}],\n 'video': {'audio': False,\n           'duration_seconds': 4,\n           'motion': 'ambient',\n           'advanced_model': None}}\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  }\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}`)\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}\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}\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  }'"
components:
  schemas:
    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
    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. The server fetches the image, so the request stays small: the right choice for large files.'
          examples:
          - https://example.com/user-design.png
        base64:
          anyOf:
          - type: string
          - type: 'null'
          description: 'Raw base64-encoded image bytes (no data: prefix). Either url or base64 must be provided. Saves the server-side fetch for small images already in memory. Base64 adds about a third to the file size and the whole request must finish uploading within 100 seconds, so send large files by url.'
        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: the box the artwork is fitted into, in the smart object''s own pixels. Width and height are both optional and each must be at least 1 pixel; an axis left out is the smart object''s own size on that axis, and a size with neither axis is ignored.'
        position:
          anyOf:
          - $ref: '#/components/schemas/AssetPosition'
          - type: 'null'
          description: 'Custom position override (top/left in pixels). With size, the top-left corner of the size box in the smart object''s own pixels, which stays axis-aligned: rotate turns the artwork inside it, never the box. Without size, it places the whole smart object on the mockup instead, its top-left corner at left/top in the template''s own pixels; a smart object in a clipping group or inside a masked group can stay where the template has it.'
        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
        tile:
          type: boolean
          description: Repeat the artwork as a pattern across the whole smart object. size is one tile, fit places the artwork inside each tile, and position sets where the grid starts. Requires size.
          default: false
        tile_spacing:
          type: number
          maximum: 100.0
          minimum: 0.0
          description: Gap between tiles as a percentage of the tile size, 0 to 100. The horizontal gap is that percent of the tile width, the vertical gap that percent of the tile height. Used only when tile is true.
          default: 0
      type: object
      title: AssetInput
      description: 'The image to place into a smart object, and how it should sit there.


        Image source priority: base64 > url (including data: URLs)

        - base64: Raw base64 string (no data: prefix). Suits small images already in memory.

        - url: HTTP/HTTPS URL or data:image/...;base64,... URL. Suits large files.'
      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
    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: Completion events (video.succeeded, video.failed) are delivered to the webhook endpoints on your account that subscribe to them. GET /api/v1/jobs/{job_id} stays the source of truth.
      type: object
      title: VideoRenderRequest
      description: 'Request body for POST /api/v1/renders/video.


        Supply exactly one of two input modes. Render mode (mockup_uuid and

        smart_objects, optionally export_options) mirrors a still render: the

        still is produced first, then animated. Raw-image mode

        (image_url) animates a public https png or jpg directly with no render

        step, and the render fields are ignored.


        Both modes take the video animation options and an optional completion

        webhook. The call always queues a job; poll GET /api/v1/jobs/{job_id} for

        the 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
    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: number
          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.

        Applied after fit transformation, does not affect PSD-level adjustments.'
    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'
    VideoRenderAcceptedResponse:
      properties:
        job_id:
          type: string
          description: Identifier of the accepted job, used to poll its status.
          examples:
          - 5f1c0b2a-7d43-4e9a-8c16-0b5d3f7a2e94
        kind:
          type: string
          const: video
          description: The kind of work accepted, which is always a video.
        status:
          type: string
          enum:
          - queued
          - dispatched
          - running
          - succeeded
          - failed
          - cancelled
          description: State of the job when this response was returned.
        status_url:
          type: string
          description: Path to poll for this job's status.
          examples:
          - /api/v1/jobs/5f1c0b2a-7d43-4e9a-8c16-0b5d3f7a2e94
        model:
          type: string
          description: The video model chosen for this clip.
        outcome_tier:
          type: string
          description: The quality level this clip is produced at.
          examples:
          - standard
        estimated_credits:
          anyOf:
          - type: integer
          - type: 'null'
          description: Credits this clip costs, which is null only when an accepted job's original quote is no longer known.
          examples:
          - 38
        duration_seconds:
          type: integer
          description: Length of the clip in seconds.
          examples:
          - 4
        audio:
          type: boolean
          description: Whether the clip is produced with sound.
          examples:
          - false
      type: object
      required:
      - job_id
      - kind
      - status
      - status_url
      - model
      - outcome_tier
      - duration_seconds
      - audio
      title: VideoRenderAcceptedResponse
      description: Acknowledgement that a video mockup was accepted and is being produced.
      example:
        audio: false
        duration_seconds: 4
        estimated_credits: 38
        job_id: 5f1c0b2a-7d43-4e9a-8c16-0b5d3f7a2e94
        kind: video
        model: veo-3.1-fast
        outcome_tier: standard
        status: queued
        status_url: /api/v1/jobs/5f1c0b2a-7d43-4e9a-8c16-0b5d3f7a2e94
    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.


        The still is produced from the same mockup_uuid + smart_objects payload as a

        normal render, then animated into a short video. SudoMock picks the best video

        model for the image automatically; `advanced_model` is an optional override.


        You choose `duration_seconds` and `audio`, and the credit cost scales with both.

        `duration_seconds` must be one of the chosen model''s allowed durations, or the

        endpoint returns 400 INVALID_VIDEO_DURATION otherwise. The 1..15 range here is a

        coarse guard; the exact allowed set depends on the model.'
    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:
          anyOf:
          - type: integer
            maximum: 10000.0
            minimum: 100.0
          - type: string
            const: original
          description: 'Output width in pixels (100-10000), or "original" to render a PSD template at its own size and resolution: the template''s own width and, unless dpi is set, the resolution the PSD was saved with. Height auto-calculated from the source aspect ratio. Renders on an account in trial are capped at 1024: a larger width 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
          examples:
          - 2048
          - original
        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. With image_size "original" and no dpi, the file carries the PSD''s own resolution. 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
    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.


        Fractional pixels are accepted.'
    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.


        Fractional pixels are accepted.'
  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