> ## 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 webhook endpoint

> Create an endpoint. The signing secret is returned in FULL here, once.

<RequestExample>
  ```js Node.js theme={"theme":{"light":"github-light","dark":"vesper"}}
  const response = await fetch("https://api.sudomock.com/api/v1/webhook-endpoints", {
    method: "POST",
    headers: {
      "x-api-key": "sm_your_api_key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      "description": "Production render notifications",
      "event_types": [
        "render.succeeded",
        "render.failed"
      ],
      "url": "https://your-app.example.com/hooks/sudomock"
    }),
  });

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

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

  $payload = <<<'JSON'
  {
    "description": "Production render notifications",
    "event_types": [
      "render.succeeded",
      "render.failed"
    ],
    "url": "https://your-app.example.com/hooks/sudomock"
  }
  JSON;

  $ch = curl_init("https://api.sudomock.com/api/v1/webhook-endpoints");
  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 = {
      "description": "Production render notifications",
      "event_types": [
          "render.succeeded",
          "render.failed"
      ],
      "url": "https://your-app.example.com/hooks/sudomock"
  }

  response = requests.post(
      "https://api.sudomock.com/api/v1/webhook-endpoints",
      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/webhook-endpoints")
  request = Net::HTTP::Post.new(uri)
  request["x-api-key"] = "sm_your_api_key"
  request["Content-Type"] = "application/json"

  request.body = <<~JSON
    {
      "description": "Production render notifications",
      "event_types": [
        "render.succeeded",
        "render.failed"
      ],
      "url": "https://your-app.example.com/hooks/sudomock"
    }
  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(`{
    "description": "Production render notifications",
    "event_types": [
      "render.succeeded",
      "render.failed"
    ],
    "url": "https://your-app.example.com/hooks/sudomock"
  }`)

  	req, err := http.NewRequest("POST", "https://api.sudomock.com/api/v1/webhook-endpoints", 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 = """
  {
    "description": "Production render notifications",
    "event_types": [
      "render.succeeded",
      "render.failed"
    ],
    "url": "https://your-app.example.com/hooks/sudomock"
  }
  """;

  HttpRequest request = HttpRequest.newBuilder()
      .uri(URI.create("https://api.sudomock.com/api/v1/webhook-endpoints"))
      .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 = """
  {
    "description": "Production render notifications",
    "event_types": [
      "render.succeeded",
      "render.failed"
    ],
    "url": "https://your-app.example.com/hooks/sudomock"
  }
  """;

  var request = new HttpRequestMessage(HttpMethod.Post, "https://api.sudomock.com/api/v1/webhook-endpoints");
  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/webhook-endpoints" \
    -H "x-api-key: sm_your_api_key" \
    -H "Content-Type: application/json" \
    -d '{
      "description": "Production render notifications",
      "event_types": [
        "render.succeeded",
        "render.failed"
      ],
      "url": "https://your-app.example.com/hooks/sudomock"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={"theme":{"light":"github-light","dark":"vesper"}}
  {
    "id": "string",
    "url": "https://example.com/artwork.png",
    "secret": "string",
    "enabled": false,
    "created_at": "2026-01-01T00:00:00Z"
  }
  ```
</ResponseExample>


## OpenAPI

````yaml openapi.json POST /api/v1/webhook-endpoints
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/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'
      security:
        - ApiKeyAuth: []
      x-codeSamples:
        - lang: Node.js
          source: >-
            const response = await
            fetch("https://api.sudomock.com/api/v1/webhook-endpoints", {
              method: "POST",
              headers: {
                "x-api-key": "sm_your_api_key",
                "Content-Type": "application/json",
              },
              body: JSON.stringify({
                "description": "Production render notifications",
                "event_types": [
                  "render.succeeded",
                  "render.failed"
                ],
                "url": "https://your-app.example.com/hooks/sudomock"
              }),
            });


            const data = await response.json();

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


            $payload = <<<'JSON'

            {
              "description": "Production render notifications",
              "event_types": [
                "render.succeeded",
                "render.failed"
              ],
              "url": "https://your-app.example.com/hooks/sudomock"
            }

            JSON;


            $ch =
            curl_init("https://api.sudomock.com/api/v1/webhook-endpoints");

            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 = {
                "description": "Production render notifications",
                "event_types": [
                    "render.succeeded",
                    "render.failed"
                ],
                "url": "https://your-app.example.com/hooks/sudomock"
            }

            response = requests.post(
                "https://api.sudomock.com/api/v1/webhook-endpoints",
                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/webhook-endpoints")

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

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

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


            request.body = <<~JSON
              {
                "description": "Production render notifications",
                "event_types": [
                  "render.succeeded",
                  "render.failed"
                ],
                "url": "https://your-app.example.com/hooks/sudomock"
              }
            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  \"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;
            import java.net.http.HttpClient;
            import java.net.http.HttpRequest;
            import java.net.http.HttpResponse;

            String payload = """
            {
              "description": "Production render notifications",
              "event_types": [
                "render.succeeded",
                "render.failed"
              ],
              "url": "https://your-app.example.com/hooks/sudomock"
            }
            """;

            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.sudomock.com/api/v1/webhook-endpoints"))
                .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 = """

            {
              "description": "Production render notifications",
              "event_types": [
                "render.succeeded",
                "render.failed"
              ],
              "url": "https://your-app.example.com/hooks/sudomock"
            }

            """;


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

            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/webhook-endpoints" \
              -H "x-api-key: sm_your_api_key" \
              -H "Content-Type: application/json" \
              -d '{
                "description": "Production render notifications",
                "event_types": [
                  "render.succeeded",
                  "render.failed"
                ],
                "url": "https://your-app.example.com/hooks/sudomock"
              }'
components:
  schemas:
    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

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

        Overrides the masked `secret` field with the real value (shown once).
  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

````