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

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

# Create a new Studio session

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

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const response = await fetch("https://api.sudomock.com/api/v1/studio/create-session", {
    method: "POST",
    headers: {
      "x-api-key": "sm_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "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"
    }),
  });

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

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

  $payload = <<<'JSON'
  {
    "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"
  }
  JSON;

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

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

  echo $response;
  ```

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

  payload = {
      "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"
  }

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

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

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

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

  request.body = <<~JSON
    {
      "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"
    }
  JSON

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

  puts response.body
  ```

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

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

  func main() {
  	payload := []byte(`{
    "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"
  }`)

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

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

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

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

  String payload = """
  {
    "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"
  }
  """;

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

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

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

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

  var payload = """
  {
    "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"
  }
  """;

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

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

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

  ```bash cURL theme={"theme":{"light":"github-light","dark":"vesper"}}
  curl -X POST "https://api.sudomock.com/api/v1/studio/create-session" \
    -H "x-api-key: sm_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "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"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "mockup_type": "psd",
    "session": "string",
    "expires_in": 1,
    "message_session_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "bootstrap_secret": "string"
  }
  ```
</ResponseExample>


## OpenAPI

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


    Every endpoint answers failures with the same envelope, so the status codes,
    the error_code values and the retry rule are documented once at
    https://sudomock.com/docs/errors rather than repeated per operation.
  version: 1.0.0
servers:
  - url: https://api.sudomock.com
    description: Production
security: []
tags:
  - name: PSD mockups
    description: Turn a Photoshop file into a reusable mockup, then render it.
  - name: Photo mockups
    description: Turn a product photo into a reusable mockup, then render artwork onto it.
  - name: Video mockups
    description: Render a mockup as a short video.
  - name: Fonts
    description: Upload and manage the fonts available to text layers.
  - name: Background removal
    description: Isolate a subject from its background as a standalone step.
  - name: Studio
    description: Open an embedded editor session and read what the customer produced in it.
  - name: Webhook endpoints
    description: Register signed endpoints and manage their secrets.
  - name: Webhook deliveries
    description: Inspect, replay and retry what those endpoints received.
  - name: Jobs
    description: Poll queued renders and read their results.
  - name: Account
    description: Read the current account, its plan and its remaining credits.
paths:
  /api/v1/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'
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: Node.js
          source: >-
            const response = await
            fetch("https://api.sudomock.com/api/v1/studio/create-session", {
              method: "POST",
              headers: {
                "x-api-key": "sm_your_api_key",
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                "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"
              }),
            });


            const data = await response.json();

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


            $payload = <<<'JSON'

            {
              "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"
            }

            JSON;


            $ch =
            curl_init("https://api.sudomock.com/api/v1/studio/create-session");

            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");

            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                "x-api-key: sm_your_api_key",
                "Content-Type: application/json",
            ]);

            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);


            $response = curl_exec($ch);

            curl_close($ch);


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

            payload = {
                "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"
            }

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

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

            require "uri"


            uri = URI("https://api.sudomock.com/api/v1/studio/create-session")

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

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

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


            request.body = <<~JSON
              {
                "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"
              }
            JSON


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


            puts response.body
        - lang: Go
          source: "package main\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n)\n\nfunc main() {\n\tpayload := []byte(`{\n  \"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;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;

            String payload = """
            {
              "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"
            }
            """;

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

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

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

            using System.Text;


            var payload = """

            {
              "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"
            }

            """;


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

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

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


            var client = new HttpClient();

            var response = await client.SendAsync(request);


            Console.WriteLine(await response.Content.ReadAsStringAsync());
        - lang: cURL
          source: >-
            curl -X POST "https://api.sudomock.com/api/v1/studio/create-session"
            \
              -H "x-api-key: sm_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "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"
              }'
components:
  schemas:
    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
    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
              minimum: 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
              minimum: 300
            - 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
              minimum: 1
            - type: 'null'
          default: 15
      additionalProperties: false
      type: object
      title: StudioConfigPatch
    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
    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.
    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:
                $ref: '#/components/schemas/StudioSeedAutoBox'
              manual:
                $ref: '#/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
          minimum: -100
          description: >-
            Percentage of the region WIDTH, from the region centre, positive
            right.
          default: 0
          examples:
            - 12.5
        offset_y_percent:
          type: number
          maximum: 100
          minimum: -100
          description: >-
            Percentage of the region HEIGHT, from the region centre, positive
            down.
          default: 0
          examples:
            - -8
        rotation:
          type: number
          maximum: 360
          minimum: -360
          description: Degrees about the box centre, clockwise positive.
          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
      additionalProperties: false
      type: object
      required:
        - box
      title: StudioSeedPlacement
      description: >-
        Where a locked design starts, in the units of the region that holds it.


        Every length here is a percentage of the target's own region -- the
        print

        area's bounding box for 2D, the Smart Object's embedded frame for PSD --

        because that is the one denominator both sides already have without a

        second round trip. Offsets run from the region CENTRE, positive right
        and

        down, and the unit lives in the field name so a reader who has only ever

        seen an example still cannot mistake it for pixels.


        ``box`` is one branch or the other, never a mixture: a width with no
        height

        is not a smaller request, it is an unanswerable one, and the branch
        makes

        it unsendable rather than merely rejected.


        This is a starting point, not a lock. The customer may move it
        afterwards.
    StudioSeedAdjustments:
      properties:
        brightness:
          anyOf:
            - type: integer
              maximum: 100
              minimum: -100
            - type: 'null'
          description: Brightness, -100 to 100. Omit for the editor's own.
          examples:
            - 10
        contrast:
          anyOf:
            - type: integer
              maximum: 100
              minimum: -100
            - type: 'null'
          description: Contrast, -100 to 100. Omit for the editor's own.
          examples:
            - 8
        saturation:
          anyOf:
            - type: integer
              maximum: 100
              minimum: -100
            - type: 'null'
          description: Saturation, -100 to 100. Omit for the editor's own.
          examples:
            - -5
        vibrance:
          anyOf:
            - type: integer
              maximum: 100
              minimum: -100
            - type: 'null'
          description: Vibrance, -100 to 100. Omit for the editor's own.
          examples:
            - 15
        opacity:
          anyOf:
            - type: integer
              maximum: 100
              minimum: 0
            - type: 'null'
          description: Opacity, 0 to 100. Omit for the editor's own.
          examples:
            - 80
        blur:
          anyOf:
            - type: number
              maximum: 20
              minimum: 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.


        One spelling for both target kinds, because this is a request rather
        than

        a report: the merchant asks for an opening appearance and the session

        either honours it or refuses to open. Which keys a target can honour

        differs, and `reject_unsupported_adjustments` is where that is decided
        --

        the same division the placement beside it already uses, and for the same

        reason. A model per surface would put the difference in the type system,

        where the single response that echoes this has no way to consult it.


        Nothing carries a default. A placement can afford them because `box` is

        required, so that object never exists half-filled; this one has no

        required key at all, so a default would be a value the merchant never

        sent, echoed back as though they had. That is the shape of the outage
        the

        placement echo was rewritten to stop.


        The bounds are the ones the editor's own controls span, not the wider
        set

        the finished image accepts. Seeding a brightness the control cannot
        reach

        opens a session whose preview disagrees with its result from the first

        frame, and the shopper -- the only person present -- has no way to know.

        Refusing is the answer `reject_unsupported_placement` already gives to a

        seed the surface cannot honour.
    StudioSeedAutoBox:
      properties:
        mode:
          type: string
          const: auto
        coverage:
          type: integer
          maximum: 100
          minimum: 10
          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
          exclusiveMinimum: 0
          description: Percentage of the target region's WIDTH.
          examples:
            - 80
        height_percent:
          type: number
          maximum: 300
          exclusiveMinimum: 0
          description: Percentage of the target region's HEIGHT.
          examples:
            - 60
      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.
  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

````