{
  "openapi": "3.1.0",
  "info": {
    "title": "Print.App API",
    "version": "2.1.0",
    "description": "Server-to-server API for Print.App integrations: designs and their page content, folders, files, fonts, palettes, product assignments, projects and editor links. Authenticate every request with a secret key: `Authorization: Bearer sk_…`. Never call it from a browser."
  },
  "servers": [
    {
      "url": "https://api.print.app",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The account a secret key belongs to."
    },
    {
      "name": "Designs",
      "description": "The designs (templates) your customers start from: create them at a size, manage their pages, and place text, images and shapes on them."
    },
    {
      "name": "Design folders",
      "description": "Folders that organise your designs. A design can sit in more than one folder."
    },
    {
      "name": "Files",
      "description": "Your own images and graphics, used in designs and offered to customers in the editor."
    },
    {
      "name": "Graphic folders",
      "description": "Folders of files, shown in the editor under Pictures, Backgrounds, Textures or Frames."
    },
    {
      "name": "Fonts",
      "description": "The fonts your designs and customers can use: the built-in set, imported Google fonts and fonts you upload."
    },
    {
      "name": "Palettes",
      "description": "Colour palettes offered in the editor."
    },
    {
      "name": "Products",
      "description": "Which designs open for each product (and variant) in your store."
    },
    {
      "name": "Projects",
      "description": "Your customers' saved designs."
    },
    {
      "name": "Links",
      "description": "Shareable editor links that open a design or project at create.print.app."
    }
  ],
  "paths": {
    "/v2/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getAccount",
        "summary": "Get the account",
        "description": "Returns the account (domain) the secret key belongs to. The quickest way to check a key works.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Account"
                },
                "example": {
                  "object": "account",
                  "id": "dom_01KA1WFS6BSCBQQV1H3EVTAXEA",
                  "hostnames": [
                    "shop.example.com"
                  ],
                  "created": "2026-03-02T10:15:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs": {
      "get": {
        "tags": [
          "Designs"
        ],
        "operationId": "listDesigns",
        "summary": "List designs",
        "description": "Lists your account's designs. Folders are not listed; see Design folders.",
        "parameters": [
          {
            "required": false,
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Items per page."
          },
          {
            "required": false,
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "The `nextCursor` of the previous page. Keep the other parameters the same between pages."
          },
          {
            "required": false,
            "name": "folderId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only the designs in this folder (`root` for the top level). Without it, every design in id order."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "design",
                      "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                      "title": "Business Card",
                      "unit": "mm",
                      "pages": [
                        {
                          "index": 0,
                          "title": "Front",
                          "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                        },
                        {
                          "index": 1,
                          "title": "Back",
                          "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                        }
                      ],
                      "tags": [
                        "cards"
                      ],
                      "created": "2026-09-02T14:05:11Z",
                      "modified": "2026-10-11T08:40:27Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Designs"
        ],
        "operationId": "createDesign",
        "summary": "Create a design",
        "description": "Creates a design with blank pages at a trim size, with optional bleed and safe margin, in a folder (the top level by default). Place content on it with `POST /v2/designs/{id}/ops`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignCreate"
              },
              "example": {
                "title": "Business card",
                "unit": "mm",
                "width": 85,
                "height": 55,
                "pages": 2,
                "pageTitles": [
                  "Front",
                  "Back"
                ],
                "bleed": 3,
                "safeMargin": 3
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}": {
      "get": {
        "tags": [
          "Designs"
        ],
        "operationId": "getDesign",
        "summary": "Get a design",
        "description": "Returns one of your account's designs. Another account's design answers 404, like one that doesn't exist.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Designs"
        ],
        "operationId": "updateDesign",
        "summary": "Update a design",
        "description": "Changes a design's title or tags. Only the fields you send change.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Designs"
        ],
        "operationId": "deleteDesign",
        "summary": "Delete a design",
        "description": "Deletes a design and takes it out of every folder. Products still pointing at it stop opening it. It can be restored by support for 30 days.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}/duplicate": {
      "post": {
        "tags": [
          "Designs"
        ],
        "operationId": "duplicateDesign",
        "summary": "Duplicate a design",
        "description": "Copies a design, its pages and their content into a new design.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The design to copy."
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignDuplicate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}/content": {
      "get": {
        "tags": [
          "Designs"
        ],
        "operationId": "getDesignContent",
        "summary": "Get page content",
        "description": "Describes what is on each page: every item's id, type, box, text, font and colour, measured in the design's unit from the top-left of the trim. Use the item ids as `target` in `POST /v2/designs/{id}/ops`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignContent"
                },
                "example": {
                  "object": "design_content",
                  "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "id": "page_5b1e",
                      "title": "Front",
                      "width": 85,
                      "height": 55,
                      "bleed": 3,
                      "safeMargin": 3,
                      "items": [
                        {
                          "id": "itm_7f3a",
                          "ref": "band",
                          "type": "rect",
                          "box": [
                            0,
                            0,
                            85,
                            14
                          ],
                          "fill": "#1f2a44",
                          "lock": "decor"
                        },
                        {
                          "id": "itm_7f3b",
                          "ref": "name",
                          "type": "text",
                          "box": [
                            6,
                            22,
                            73,
                            10
                          ],
                          "text": "Ada Lovelace",
                          "font": "open sans",
                          "weight": 700,
                          "size": 14,
                          "align": "left",
                          "color": "#1f2a44",
                          "field": {
                            "title": "Name"
                          },
                          "lock": "field"
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}/ops": {
      "post": {
        "tags": [
          "Designs"
        ],
        "operationId": "applyOps",
        "summary": "Edit page content",
        "description": "Adds, changes and removes text, images, shapes, frames, QR codes and other items on a design's pages, as one batch of operations. The batch is checked against the operation schemas first and refused as a whole if any operation is malformed (400). It then runs in order; if any operation fails, nothing is saved (422). With `dryRun: true` it runs without saving.\n\nPlace images and SVG graphics as files: upload them with `POST /v2/files` (from a URL) or `POST /v2/files/uploads`, then give the file id as `asset`. An SVG file stays vector in print. Don't send SVG markup inline (`svg`): the firewall in front of the API refuses request bodies that carry markup, with an HTML 403.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OpsBatch"
              },
              "example": {
                "units": "mm",
                "ops": [
                  {
                    "op": "shape.add",
                    "ref": "band",
                    "kind": "rect",
                    "box": [
                      0,
                      0,
                      85,
                      14
                    ],
                    "fill": "#1f2a44"
                  },
                  {
                    "op": "text.add",
                    "ref": "name",
                    "box": [
                      6,
                      22,
                      73,
                      10
                    ],
                    "content": "Ada Lovelace",
                    "font": "open sans",
                    "size": 14,
                    "weight": 700,
                    "align": "left",
                    "color": "#1f2a44",
                    "field": {
                      "title": "Name",
                      "maxTextCount": 30
                    }
                  },
                  {
                    "op": "graphic.add",
                    "ref": "logo",
                    "box": [
                      62,
                      3,
                      18,
                      8
                    ],
                    "asset": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OpsResult"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "422": {
            "description": "An operation failed while the batch ran. Nothing was saved; `details` holds every operation's result.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "ops_failed",
                  "message": "ops[1] (item.update) failed: no item 'logo'. Nothing was saved.",
                  "param": "ops",
                  "requestId": "FZn-uhymjoEEJow=",
                  "details": [
                    {
                      "index": 0,
                      "op": "text.add",
                      "ok": true,
                      "id": "itm_7f3b",
                      "ref": "name"
                    },
                    {
                      "index": 1,
                      "op": "item.update",
                      "ok": false,
                      "error": "no item 'logo'"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}/pages": {
      "post": {
        "tags": [
          "Designs"
        ],
        "operationId": "addPages",
        "summary": "Add pages",
        "description": "Adds blank pages, the same size as the design's first page.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PagesCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/designs/{id}/pages/{index}": {
      "patch": {
        "tags": [
          "Designs"
        ],
        "operationId": "updatePage",
        "summary": "Update a page",
        "description": "Renames a page or moves it to another position.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          },
          {
            "name": "index",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "The page index, from 0."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PageUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Designs"
        ],
        "operationId": "deletePage",
        "summary": "Delete a page",
        "description": "Removes a page from the design. A design keeps at least one page.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          },
          {
            "name": "index",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "The page index, from 0."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Design"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "title": "Business Card",
                  "unit": "mm",
                  "pages": [
                    {
                      "index": 0,
                      "title": "Front",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "title": "Back",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
                    }
                  ],
                  "tags": [
                    "cards"
                  ],
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/design-folders": {
      "get": {
        "tags": [
          "Design folders"
        ],
        "operationId": "listDesignFolders",
        "summary": "List design folders",
        "description": "Lists your design folders. The top level is the folder `root`, which is not listed itself.",
        "parameters": [
          {
            "required": false,
            "name": "parentId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only the folders directly inside this one (`root` for the top level)."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolderList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "design_folder",
                      "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                      "title": "Business cards",
                      "parentId": "root",
                      "created": "2026-09-02T14:05:11Z",
                      "modified": "2026-10-11T08:40:27Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Design folders"
        ],
        "operationId": "createDesignFolder",
        "summary": "Create a design folder",
        "description": "Creates a folder, at the top level or inside another folder.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignFolderCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolder"
                },
                "example": {
                  "object": "design_folder",
                  "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                  "title": "Business cards",
                  "parentId": "root",
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/design-folders/{id}": {
      "get": {
        "tags": [
          "Design folders"
        ],
        "operationId": "getDesignFolder",
        "summary": "Get a design folder",
        "description": "Returns a folder. List its designs with `GET /v2/designs?folderId=`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id, or `root`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolder"
                },
                "example": {
                  "object": "design_folder",
                  "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                  "title": "Business cards",
                  "parentId": "root",
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Design folders"
        ],
        "operationId": "updateDesignFolder",
        "summary": "Update a design folder",
        "description": "Renames a folder or moves it into another folder.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DesignFolderUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolder"
                },
                "example": {
                  "object": "design_folder",
                  "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                  "title": "Business cards",
                  "parentId": "root",
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Design folders"
        ],
        "operationId": "deleteDesignFolder",
        "summary": "Delete a design folder",
        "description": "Deletes an empty folder. A folder that still holds designs or folders answers 409 `folder_not_empty`.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/design-folders/{id}/designs": {
      "post": {
        "tags": [
          "Design folders"
        ],
        "operationId": "addDesignToFolder",
        "summary": "Add a design to a folder",
        "description": "Puts a design in a folder. It stays in any folders it was already in.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id, or `root`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderDesign"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolder"
                },
                "example": {
                  "object": "design_folder",
                  "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                  "title": "Business cards",
                  "parentId": "root",
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/design-folders/{id}/designs/{designId}": {
      "delete": {
        "tags": [
          "Design folders"
        ],
        "operationId": "removeDesignFromFolder",
        "summary": "Remove a design from a folder",
        "description": "Takes a design out of a folder. The design itself is not deleted.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id, or `root`."
          },
          {
            "name": "designId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `designId`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DesignFolder"
                },
                "example": {
                  "object": "design_folder",
                  "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
                  "title": "Business cards",
                  "parentId": "root",
                  "created": "2026-09-02T14:05:11Z",
                  "modified": "2026-10-11T08:40:27Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/files": {
      "get": {
        "tags": [
          "Files"
        ],
        "operationId": "listFiles",
        "summary": "List files",
        "description": "Lists the images and graphics you uploaded, newest first. Files your customers uploaded in the editor are not listed.",
        "parameters": [
          {
            "required": false,
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Items per page."
          },
          {
            "required": false,
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "The `nextCursor` of the previous page. Keep the other parameters the same between pages."
          },
          {
            "required": false,
            "name": "folderId",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only the files in this graphic folder, in folder order."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "file",
                      "id": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                      "title": "Logo",
                      "contentType": "image/png",
                      "size": 48211,
                      "width": 1200,
                      "height": 800,
                      "url": "https://d3f4dd8gq49w54.cloudfront.net/file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Ffile_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png&size=300",
                      "tags": [],
                      "created": "2026-10-27T10:00:00Z",
                      "modified": "2026-10-27T10:00:00Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Files"
        ],
        "operationId": "createFile",
        "summary": "Upload a file from a URL",
        "description": "Downloads an image (PNG, JPEG, WebP, GIF, SVG, TIFF or PDF, up to 50 MB) from a public URL into your files, optionally into a graphic folder. For a file that is not online, use `POST /v2/files/uploads`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FileCreate"
              },
              "example": {
                "url": "https://example.com/logo.png",
                "title": "Logo",
                "folderId": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                },
                "example": {
                  "object": "file",
                  "id": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "title": "Logo",
                  "contentType": "image/png",
                  "size": 48211,
                  "width": 1200,
                  "height": 800,
                  "url": "https://d3f4dd8gq49w54.cloudfront.net/file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Ffile_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png&size=300",
                  "tags": [],
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "413": {
            "description": "A body or a downloaded file is over its size limit.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "payload_too_large",
                  "message": "The file at url is larger than 50 MB.",
                  "param": "url",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/files/uploads": {
      "post": {
        "tags": [
          "Files"
        ],
        "operationId": "createFileUpload",
        "summary": "Start a direct upload",
        "description": "Returns a presigned form to upload one file straight to storage: POST `upload.fields` plus the file as `file` (multipart/form-data) to `upload.url` within 10 minutes. The file then appears under `fileId` within a few seconds; poll `GET /v2/files/{id}`.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FileUploadCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FileUpload"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "413": {
            "description": "A body or a downloaded file is over its size limit.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "payload_too_large",
                  "message": "The file at url is larger than 50 MB.",
                  "param": "url",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/files/{id}": {
      "get": {
        "tags": [
          "Files"
        ],
        "operationId": "getFile",
        "summary": "Get a file",
        "description": "Returns one of your files.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The file id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                },
                "example": {
                  "object": "file",
                  "id": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "title": "Logo",
                  "contentType": "image/png",
                  "size": 48211,
                  "width": 1200,
                  "height": 800,
                  "url": "https://d3f4dd8gq49w54.cloudfront.net/file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Ffile_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png&size=300",
                  "tags": [],
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Files"
        ],
        "operationId": "updateFile",
        "summary": "Update a file",
        "description": "Changes a file's title or tags.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The file id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FileUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/File"
                },
                "example": {
                  "object": "file",
                  "id": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "title": "Logo",
                  "contentType": "image/png",
                  "size": 48211,
                  "width": 1200,
                  "height": 800,
                  "url": "https://d3f4dd8gq49w54.cloudfront.net/file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
                  "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Ffile_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png&size=300",
                  "tags": [],
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Files"
        ],
        "operationId": "deleteFile",
        "summary": "Delete a file",
        "description": "Deletes a file. Designs that already use it keep showing it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The file id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/graphic-folders": {
      "get": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "listGraphicFolders",
        "summary": "List graphic folders",
        "description": "Lists the folders of graphics your editor shows, panel by panel, including the ones Print.App provides.",
        "parameters": [
          {
            "required": false,
            "name": "panel",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "pictures",
                "backgrounds",
                "textures",
                "frames"
              ]
            },
            "description": "Only the folders shown under this editor panel."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolderList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "graphic_folder",
                      "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                      "title": "Logos",
                      "panel": "pictures",
                      "fileIds": [
                        "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                      ],
                      "builtIn": false,
                      "created": "2026-10-27T10:00:00Z",
                      "modified": "2026-10-27T10:05:00Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "createGraphicFolder",
        "summary": "Create a graphic folder",
        "description": "Creates a folder in an editor panel (Pictures by default), at the top of the panel.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GraphicFolderCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolder"
                },
                "example": {
                  "object": "graphic_folder",
                  "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                  "title": "Logos",
                  "panel": "pictures",
                  "fileIds": [
                    "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:05:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/graphic-folders/{id}": {
      "get": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "getGraphicFolder",
        "summary": "Get a graphic folder",
        "description": "Returns a folder with the ids of its files, in the order the editor shows them.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolder"
                },
                "example": {
                  "object": "graphic_folder",
                  "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                  "title": "Logos",
                  "panel": "pictures",
                  "fileIds": [
                    "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:05:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "updateGraphicFolder",
        "summary": "Update a graphic folder",
        "description": "Renames a folder or reorders its files. Folders Print.App provides cannot be changed.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GraphicFolderUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolder"
                },
                "example": {
                  "object": "graphic_folder",
                  "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                  "title": "Logos",
                  "panel": "pictures",
                  "fileIds": [
                    "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:05:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "deleteGraphicFolder",
        "summary": "Delete a graphic folder",
        "description": "Removes a folder from its panel. The files in it are kept.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/graphic-folders/{id}/files": {
      "post": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "addFileToFolder",
        "summary": "Add a file to a folder",
        "description": "Puts one of your files at the top of a folder.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FolderFile"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolder"
                },
                "example": {
                  "object": "graphic_folder",
                  "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                  "title": "Logos",
                  "panel": "pictures",
                  "fileIds": [
                    "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:05:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/graphic-folders/{id}/files/{fileId}": {
      "delete": {
        "tags": [
          "Graphic folders"
        ],
        "operationId": "removeFileFromFolder",
        "summary": "Remove a file from a folder",
        "description": "Takes a file out of a folder. The file itself is kept.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The folder id."
          },
          {
            "name": "fileId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The file id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GraphicFolder"
                },
                "example": {
                  "object": "graphic_folder",
                  "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
                  "title": "Logos",
                  "panel": "pictures",
                  "fileIds": [
                    "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:05:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/fonts": {
      "get": {
        "tags": [
          "Fonts"
        ],
        "operationId": "listFonts",
        "summary": "List fonts",
        "description": "Lists every font family your designs and customers can use, with its weights and styles.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FontList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "font",
                      "family": "playfair display",
                      "source": "google",
                      "variants": [
                        {
                          "weight": 400,
                          "style": "normal"
                        },
                        {
                          "weight": 400,
                          "style": "italic"
                        },
                        {
                          "weight": 700,
                          "style": "normal"
                        }
                      ]
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Fonts"
        ],
        "operationId": "createFont",
        "summary": "Add a font",
        "description": "Imports a Google font family by name (every weight and style), or uploads a TTF, OTF or WOFF font file from a public URL.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FontCreate"
              },
              "example": {
                "family": "Playfair Display"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Font"
                },
                "example": {
                  "object": "font",
                  "family": "playfair display",
                  "source": "google",
                  "variants": [
                    {
                      "weight": 400,
                      "style": "normal"
                    },
                    {
                      "weight": 400,
                      "style": "italic"
                    },
                    {
                      "weight": 700,
                      "style": "normal"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "413": {
            "description": "A body or a downloaded file is over its size limit.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "payload_too_large",
                  "message": "The file at url is larger than 50 MB.",
                  "param": "url",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/fonts/{family}": {
      "get": {
        "tags": [
          "Fonts"
        ],
        "operationId": "getFont",
        "summary": "Get a font",
        "description": "Returns one font family.",
        "parameters": [
          {
            "name": "family",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The font family, for example `Open Sans`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Font"
                },
                "example": {
                  "object": "font",
                  "family": "playfair display",
                  "source": "google",
                  "variants": [
                    {
                      "weight": 400,
                      "style": "normal"
                    },
                    {
                      "weight": 400,
                      "style": "italic"
                    },
                    {
                      "weight": 700,
                      "style": "normal"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Fonts"
        ],
        "operationId": "deleteFont",
        "summary": "Remove a font",
        "description": "Removes a font family (every weight and style) from your account. A built-in family is hidden instead.",
        "parameters": [
          {
            "name": "family",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The font family."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/palettes": {
      "get": {
        "tags": [
          "Palettes"
        ],
        "operationId": "listPalettes",
        "summary": "List palettes",
        "description": "Lists the colour palettes your editor offers, including the built-in ones.",
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaletteList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "palette",
                      "id": "folder:8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                      "title": "Brand",
                      "colors": [
                        {
                          "name": "Navy",
                          "type": "solid",
                          "hex": "#1f2a44",
                          "cmyk": "100,80,30,40",
                          "spot": null
                        }
                      ],
                      "builtIn": false,
                      "created": "2026-10-27T10:00:00Z",
                      "modified": "2026-10-27T10:00:00Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Palettes"
        ],
        "operationId": "createPalette",
        "summary": "Create a palette",
        "description": "Creates a palette of solid colours, each with an optional CMYK value and spot colour name for print.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaletteCreate"
              },
              "example": {
                "title": "Brand",
                "colors": [
                  {
                    "name": "Navy",
                    "hex": "#1f2a44",
                    "cmyk": "100,80,30,40"
                  },
                  {
                    "name": "Gold",
                    "hex": "#c9a227",
                    "spot": "PANTONE 7753 C"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Palette"
                },
                "example": {
                  "object": "palette",
                  "id": "folder:8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                  "title": "Brand",
                  "colors": [
                    {
                      "name": "Navy",
                      "type": "solid",
                      "hex": "#1f2a44",
                      "cmyk": "100,80,30,40",
                      "spot": null
                    }
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/palettes/{id}": {
      "get": {
        "tags": [
          "Palettes"
        ],
        "operationId": "getPalette",
        "summary": "Get a palette",
        "description": "Returns one palette.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The palette id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Palette"
                },
                "example": {
                  "object": "palette",
                  "id": "folder:8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                  "title": "Brand",
                  "colors": [
                    {
                      "name": "Navy",
                      "type": "solid",
                      "hex": "#1f2a44",
                      "cmyk": "100,80,30,40",
                      "spot": null
                    }
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Palettes"
        ],
        "operationId": "updatePalette",
        "summary": "Update a palette",
        "description": "Renames a palette or replaces its colours. Built-in palettes cannot be changed (409 `builtin_palette`); delete hides them.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The palette id."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PaletteUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Palette"
                },
                "example": {
                  "object": "palette",
                  "id": "folder:8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
                  "title": "Brand",
                  "colors": [
                    {
                      "name": "Navy",
                      "type": "solid",
                      "hex": "#1f2a44",
                      "cmyk": "100,80,30,40",
                      "spot": null
                    }
                  ],
                  "builtIn": false,
                  "created": "2026-10-27T10:00:00Z",
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "409": {
            "description": "The request conflicts with the current state; `code` says how (`folder_not_empty`, `builtin_folder`, `builtin_palette`, `editor_not_supported`, `design_changed`, `idempotency_key_reused`, `idempotency_in_progress`).",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "folder_not_empty",
                  "message": "The folder still holds designs. Remove them from it (or delete them) first.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Palettes"
        ],
        "operationId": "deletePalette",
        "summary": "Delete a palette",
        "description": "Deletes a palette. A built-in palette is hidden from your editor instead.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The palette id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "listProducts",
        "summary": "List products",
        "description": "Lists the store products that have designs assigned, in product id order.",
        "parameters": [
          {
            "required": false,
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Items per page."
          },
          {
            "required": false,
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "The `nextCursor` of the previous page. Keep the other parameters the same between pages."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "product",
                      "id": "8812001",
                      "title": "Business cards",
                      "designIds": [
                        "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
                      ],
                      "variants": [],
                      "modified": "2026-10-27T10:00:00Z"
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/products/{productId}": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "getProduct",
        "summary": "Get a product",
        "description": "Returns the designs assigned to one product and its variants.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The product's id in your store."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "object": "product",
                  "id": "8812001",
                  "title": "Business cards",
                  "designIds": [
                    "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
                  ],
                  "variants": [],
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Products"
        ],
        "operationId": "setProduct",
        "summary": "Assign designs to a product",
        "description": "Sets which designs open for a product, and optionally per variant. Replaces the product's assignment; settings made in the dashboard are kept.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The product's id in your store."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductSet"
              },
              "example": {
                "designIds": [
                  "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
                ],
                "variants": [
                  {
                    "id": "4401",
                    "designIds": [
                      "design_01J8ZB0C1D2E3F4G5H6J7K8M9N"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                },
                "example": {
                  "object": "product",
                  "id": "8812001",
                  "title": "Business cards",
                  "designIds": [
                    "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
                  ],
                  "variants": [],
                  "modified": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Products"
        ],
        "operationId": "deleteProduct",
        "summary": "Clear a product",
        "description": "Removes every design from a product, so it no longer opens the editor.",
        "parameters": [
          {
            "name": "productId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The product's id in your store."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/projects": {
      "get": {
        "tags": [
          "Projects"
        ],
        "operationId": "listProjects",
        "summary": "List projects",
        "description": "Lists your account's projects, most recently modified first.",
        "parameters": [
          {
            "required": false,
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            },
            "description": "Items per page."
          },
          {
            "required": false,
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "The `nextCursor` of the previous page. Keep the other parameters the same between pages."
          },
          {
            "required": false,
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "saved",
                "submitted"
              ]
            },
            "description": "Only projects with this status."
          },
          {
            "required": false,
            "name": "modifiedFrom",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only projects last saved at or after this time: ISO-8601 (`2026-10-01T00:00:00Z`) or epoch milliseconds."
          },
          {
            "required": false,
            "name": "modifiedTo",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Only projects last saved at or before this time: ISO-8601 or epoch milliseconds."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectList"
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "project",
                      "id": "project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                      "title": "Business Card",
                      "status": "submitted",
                      "product": {
                        "id": "sku-123",
                        "ref": "cart-line-7f3a"
                      },
                      "userId": "customer-1001",
                      "userData": {
                        "id": "customer-1001",
                        "name": "Jane Doe",
                        "email": "jane@example.com"
                      },
                      "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                      "created": "2026-10-17T09:12:03Z",
                      "modified": "2026-10-17T09:20:41Z",
                      "pages": [
                        {
                          "index": 0,
                          "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_a1.png&size=1000"
                        },
                        {
                          "index": 1,
                          "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b2.png&size=1000"
                        }
                      ],
                      "exports": {
                        "pdf": "https://pdf.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                        "png": "https://png.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                        "jpeg": "https://jpeg.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                        "tiff": "https://tiff.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b"
                      }
                    }
                  ],
                  "hasMore": false,
                  "nextCursor": null
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/projects/{id}": {
      "get": {
        "tags": [
          "Projects"
        ],
        "operationId": "getProject",
        "summary": "Get a project",
        "description": "Returns one of your account's projects. A project that belongs to another account answers 404, exactly like one that doesn't exist, so a 200 proves the project is yours.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `projectId` from the editor's `app:saved` event."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "object": "project",
                  "id": "project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                  "title": "Business Card",
                  "status": "submitted",
                  "product": {
                    "id": "sku-123",
                    "ref": "cart-line-7f3a"
                  },
                  "userId": "customer-1001",
                  "userData": {
                    "id": "customer-1001",
                    "name": "Jane Doe",
                    "email": "jane@example.com"
                  },
                  "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "created": "2026-10-17T09:12:03Z",
                  "modified": "2026-10-17T09:20:41Z",
                  "pages": [
                    {
                      "index": 0,
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_a1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b2.png&size=1000"
                    }
                  ],
                  "exports": {
                    "pdf": "https://pdf.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "png": "https://png.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "jpeg": "https://jpeg.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "tiff": "https://tiff.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Projects"
        ],
        "operationId": "updateProject",
        "summary": "Update a project",
        "description": "Changes a project's title or `userData` (your own customer or order details). `userData` is merged one level deep: send `null` for a key to remove it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `projectId`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProjectUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Project"
                },
                "example": {
                  "object": "project",
                  "id": "project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                  "title": "Business Card",
                  "status": "submitted",
                  "product": {
                    "id": "sku-123",
                    "ref": "cart-line-7f3a"
                  },
                  "userId": "customer-1001",
                  "userData": {
                    "id": "customer-1001",
                    "name": "Jane Doe",
                    "email": "jane@example.com"
                  },
                  "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "created": "2026-10-17T09:12:03Z",
                  "modified": "2026-10-17T09:20:41Z",
                  "pages": [
                    {
                      "index": 0,
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_a1.png&size=1000"
                    },
                    {
                      "index": 1,
                      "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b2.png&size=1000"
                    }
                  ],
                  "exports": {
                    "pdf": "https://pdf.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "png": "https://png.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "jpeg": "https://jpeg.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
                    "tiff": "https://tiff.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Projects"
        ],
        "operationId": "deleteProject",
        "summary": "Delete a project",
        "description": "Deletes a project. Its PDF and image exports stop working. It can be restored by support for 8 days.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The `projectId`."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/links": {
      "post": {
        "tags": [
          "Links"
        ],
        "operationId": "createLink",
        "summary": "Create an editor link",
        "description": "Creates a link that opens a design (for a customer to start from) or a project (to carry on with) in the Print.App editor at create.print.app, without a store.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkCreate"
              },
              "example": {
                "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                "userData": {
                  "email": "ada@example.com"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              },
              "idempotent-replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Link"
                },
                "example": {
                  "object": "link",
                  "id": "cid_Jx81kQ",
                  "url": "https://create.print.app/cid_Jx81kQ",
                  "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "projectId": null,
                  "userData": {
                    "email": "ada@example.com"
                  },
                  "expiresAt": "2026-11-26T10:00:00Z",
                  "created": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "400": {
            "description": "A parameter or body field is malformed: `param` names it and `details` lists every problem found.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "invalid_request",
                  "message": "width is required.",
                  "param": "width",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "415": {
            "description": "The body is not JSON.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unsupported_media_type",
                  "message": "Send the request body as JSON, with \"Content-Type: application/json\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    },
    "/v2/links/{id}": {
      "get": {
        "tags": [
          "Links"
        ],
        "operationId": "getLink",
        "summary": "Get an editor link",
        "description": "Returns a link, with the project a customer saved through it.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The link id (`cid_…`)."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Link"
                },
                "example": {
                  "object": "link",
                  "id": "cid_Jx81kQ",
                  "url": "https://create.print.app/cid_Jx81kQ",
                  "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "projectId": null,
                  "userData": {
                    "email": "ada@example.com"
                  },
                  "expiresAt": "2026-11-26T10:00:00Z",
                  "created": "2026-10-27T10:00:00Z"
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Links"
        ],
        "operationId": "deleteLink",
        "summary": "Expire an editor link",
        "description": "Stops a link from working. Projects saved through it are kept.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The link id."
          }
        ],
        "responses": {
          "200": {
            "description": "OK.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "design",
                  "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
                  "deleted": true
                }
              }
            }
          },
          "401": {
            "description": "Missing, unknown, revoked or expired secret key.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "unauthorized",
                  "message": "Missing or invalid secret key. Send it as \"Authorization: Bearer sk_…\".",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "403": {
            "description": "The account is suspended for an unpaid invoice.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "account_suspended",
                  "message": "This account is suspended. Settle the outstanding invoice in the Print.App dashboard.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "404": {
            "description": "Not found in your account. Another account's resources answer 404 too.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "not_found",
                  "message": "Not found.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          },
          "429": {
            "description": "Rate limited by the API gateway. Back off and retry. This response comes from the gateway, so its body is `{ \"message\": \"Too Many Requests\" }`, not the standard error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GatewayError"
                },
                "example": {
                  "message": "Too Many Requests"
                }
              }
            }
          },
          "500": {
            "description": "Something failed on our side. Retry; quote the requestId to support if it persists.",
            "headers": {
              "x-request-id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": true,
                  "code": "internal_error",
                  "message": "Something went wrong on our side. Retry the request; if it keeps failing, contact support with the requestId.",
                  "requestId": "FZn-uhymjoEEJow="
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "A secret key from Print.App admin → Domains → Secret keys, sent as `Authorization: Bearer sk_…`. Server-side only."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "description": "Makes a retry safe: a second request with the same key and the same body gets the first response back (for 24 hours) instead of creating the resource again. Use a new key, such as a UUID, for every new request."
      }
    },
    "headers": {
      "RequestId": {
        "description": "Identifies the request. Quote it when contacting support.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotentReplayed": {
        "description": "`true` when the response is the stored answer to an earlier request with the same Idempotency-Key.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "Account": {
        "title": "Account",
        "description": "The Print.App account (domain) a secret key belongs to.",
        "type": "object",
        "required": [
          "object",
          "id",
          "hostnames",
          "created"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "account"
          },
          "id": {
            "type": "string",
            "description": "Your Domain Key (`dom_…`), the public key you use in the browser."
          },
          "hostnames": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "The store hostnames registered for this account."
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "account",
            "id": "dom_01KA1WFS6BSCBQQV1H3EVTAXEA",
            "hostnames": [
              "shop.example.com"
            ],
            "created": "2026-03-02T10:15:00Z"
          }
        ]
      },
      "ContentItem": {
        "title": "ContentItem",
        "description": "One item on a page. Target it in `POST /v2/designs/{id}/ops` by `id`, or by `ref` when it has one.",
        "type": "object",
        "required": [
          "id",
          "type",
          "box",
          "lock"
        ],
        "properties": {
          "id": {
            "type": "string"
          },
          "ref": {
            "type": [
              "string",
              "null"
            ],
            "description": "The name it was added with."
          },
          "type": {
            "type": "string",
            "description": "`text`, `image`, `rect`, `ellipse`, `path`, `group`, `tiles`, or the module type (`qrcode`, `calendar`, …)."
          },
          "box": {
            "type": [
              "array",
              "null"
            ],
            "items": {
              "type": [
                "number",
                "null"
              ]
            },
            "minItems": 4,
            "maxItems": 4
          },
          "text": {
            "type": [
              "string",
              "null"
            ]
          },
          "font": {
            "type": [
              "string",
              "null"
            ]
          },
          "weight": {
            "type": [
              "number",
              "null"
            ]
          },
          "size": {
            "type": [
              "number",
              "null"
            ],
            "description": "Font size in points."
          },
          "drawnSize": {
            "type": [
              "number",
              "null"
            ],
            "description": "The size the text is drawn at, when a fitting frame shrank it."
          },
          "align": {
            "type": [
              "string",
              "null"
            ]
          },
          "color": {
            "type": [
              "string",
              "null"
            ],
            "description": "Text colour."
          },
          "fill": {
            "type": [
              "string",
              "null"
            ],
            "description": "Shape fill."
          },
          "asset": {
            "type": [
              "string",
              "null"
            ],
            "description": "The file or library graphic it shows."
          },
          "module": {
            "type": [
              "string",
              "null"
            ]
          },
          "tiles": {
            "type": [
              "number",
              "null"
            ],
            "description": "How many tiles a pattern has."
          },
          "field": {
            "type": "object",
            "required": [
              "title"
            ],
            "properties": {
              "title": {
                "type": [
                  "string",
                  "null"
                ]
              }
            },
            "description": "Customers edit it in the form."
          },
          "photoFrame": {
            "type": "boolean"
          },
          "background": {
            "type": "boolean"
          },
          "overflow": {
            "type": "boolean",
            "description": "Its text does not fit its box."
          },
          "lock": {
            "type": [
              "string",
              "null"
            ],
            "description": "`none`, `field`, `decor` or `hard`."
          }
        }
      },
      "Deleted": {
        "title": "Deleted",
        "description": "Confirms a deletion.",
        "type": "object",
        "required": [
          "object",
          "id",
          "deleted"
        ],
        "properties": {
          "object": {
            "type": "string",
            "description": "The kind of object deleted."
          },
          "id": {
            "type": "string"
          },
          "deleted": {
            "type": "boolean",
            "const": true
          }
        },
        "examples": [
          {
            "object": "design",
            "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "deleted": true
          }
        ]
      },
      "DesignContent": {
        "title": "DesignContent",
        "description": "What is on each page of a design. Boxes are `[x, y, width, height]` in `unit`, measured from the top-left of the trim (of the print area, on garment pages); text sizes are in points.",
        "type": "object",
        "required": [
          "object",
          "designId",
          "unit",
          "pages"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "design_content"
          },
          "designId": {
            "type": "string"
          },
          "unit": {
            "type": [
              "string",
              "null"
            ]
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "index",
                "id",
                "title",
                "width",
                "height",
                "bleed",
                "safeMargin",
                "items"
              ],
              "properties": {
                "index": {
                  "type": "integer",
                  "minimum": 0
                },
                "id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "width": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Trim width."
                },
                "height": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "Trim height."
                },
                "bleed": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "safeMargin": {
                  "type": [
                    "number",
                    "null"
                  ],
                  "description": "How far inside the trim the safe zone starts; null without one."
                },
                "safeArea": {
                  "type": "array",
                  "items": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "minItems": 4,
                  "maxItems": 4,
                  "description": "The safe zone as [x, y, width, height] from the top-left of the trim: keep text and key artwork inside it."
                },
                "printArea": {
                  "type": "boolean",
                  "description": "The page is a garment mockup: boxes are measured from its print area."
                },
                "panels": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "n",
                      "box"
                    ],
                    "properties": {
                      "n": {
                        "type": "integer"
                      },
                      "box": {
                        "type": [
                          "array",
                          "null"
                        ],
                        "items": {
                          "type": [
                            "number",
                            "null"
                          ]
                        }
                      }
                    }
                  },
                  "description": "The panels of a folded page."
                },
                "items": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ContentItem"
                  }
                }
              }
            }
          }
        },
        "examples": [
          {
            "object": "design_content",
            "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "unit": "mm",
            "pages": [
              {
                "index": 0,
                "id": "page_5b1e",
                "title": "Front",
                "width": 85,
                "height": 55,
                "bleed": 3,
                "safeMargin": 3,
                "items": [
                  {
                    "id": "itm_7f3a",
                    "ref": "band",
                    "type": "rect",
                    "box": [
                      0,
                      0,
                      85,
                      14
                    ],
                    "fill": "#1f2a44",
                    "lock": "decor"
                  },
                  {
                    "id": "itm_7f3b",
                    "ref": "name",
                    "type": "text",
                    "box": [
                      6,
                      22,
                      73,
                      10
                    ],
                    "text": "Ada Lovelace",
                    "font": "open sans",
                    "weight": 700,
                    "size": 14,
                    "align": "left",
                    "color": "#1f2a44",
                    "field": {
                      "title": "Name"
                    },
                    "lock": "field"
                  }
                ]
              }
            ]
          }
        ]
      },
      "DesignCreate": {
        "title": "DesignCreate",
        "description": "A new design with blank pages.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "width",
          "height"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The design's name. Default *New design*."
          },
          "unit": {
            "type": "string",
            "enum": [
              "in",
              "mm",
              "cm",
              "pt",
              "px",
              "ft"
            ],
            "default": "in",
            "description": "The unit for `width`, `height`, `bleed` and `safeMargin`, and the unit the design is measured in afterwards."
          },
          "width": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Trim width."
          },
          "height": {
            "type": "number",
            "exclusiveMinimum": 0,
            "description": "Trim height."
          },
          "pages": {
            "type": "integer",
            "minimum": 1,
            "maximum": 200,
            "default": 1,
            "description": "How many pages."
          },
          "pageTitles": {
            "type": "array",
            "maxItems": 200,
            "items": {
              "type": "string",
              "maxLength": 100
            },
            "description": "A title per page, for example `[\"Front\", \"Back\"]`. Default *Page 1*, *Page 2*, …"
          },
          "bleed": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Bleed on every edge, outside the trim."
          },
          "safeMargin": {
            "type": "number",
            "minimum": 0,
            "default": 0,
            "description": "Safe margin on every edge, inside the trim."
          },
          "folderId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The design folder to create it in. Default `root`, the top level."
          },
          "tags": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "description": "Labels for finding it again."
          }
        },
        "examples": [
          {
            "title": "Business card",
            "unit": "mm",
            "width": 85,
            "height": 55,
            "pages": 2,
            "pageTitles": [
              "Front",
              "Back"
            ],
            "bleed": 3,
            "safeMargin": 3
          }
        ]
      },
      "DesignDuplicate": {
        "title": "DesignDuplicate",
        "description": "Options for the copy.",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The copy's name. Default: the original's, with *(copy)*."
          },
          "folderId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder to put the copy in. Default `root`."
          }
        }
      },
      "DesignFolderCreate": {
        "title": "DesignFolderCreate",
        "description": "A new design folder.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder's name."
          },
          "parentId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder to create it in. Default `root`."
          }
        }
      },
      "DesignFolderList": {
        "title": "DesignFolderList",
        "description": "Design folders.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DesignFolder"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "DesignFolderUpdate": {
        "title": "DesignFolderUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder's name."
          },
          "parentId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Move the folder into this one (`root` for the top level)."
          }
        }
      },
      "DesignFolder": {
        "title": "DesignFolder",
        "description": "A folder of designs. The top level is the folder `root`.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "parentId",
          "created",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "design_folder"
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "parentId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The folder it sits in; `null` for `root`."
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "design_folder",
            "id": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11",
            "title": "Business cards",
            "parentId": "root",
            "created": "2026-09-02T14:05:11Z",
            "modified": "2026-10-11T08:40:27Z"
          }
        ]
      },
      "DesignList": {
        "title": "DesignList",
        "description": "A page of designs, in id order.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Design"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "DesignUpdate": {
        "title": "DesignUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The design's name."
          },
          "tags": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "description": "Labels for finding it again."
          }
        }
      },
      "Design": {
        "title": "Design",
        "description": "A design (template) your customers start from. Open it in the editor with `new PrintAppClient({ designId })`.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "unit",
          "pages",
          "tags",
          "created",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "design"
          },
          "id": {
            "type": "string",
            "description": "The `designId` to pass to `PrintAppClient`."
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "unit": {
            "type": [
              "string",
              "null"
            ],
            "description": "The unit the design is measured in: `mm`, `cm`, `in`, `pt`, `px` or `ft`."
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "index",
                "title",
                "previewUrl"
              ],
              "properties": {
                "index": {
                  "type": "integer",
                  "minimum": 0
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The page's name, when it has one (for example *Front*)."
                },
                "previewUrl": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "A preview image of the page."
                }
              }
            }
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "design",
            "id": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "title": "Business Card",
            "unit": "mm",
            "pages": [
              {
                "index": 0,
                "title": "Front",
                "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_f1.png&size=1000"
              },
              {
                "index": 1,
                "title": "Back",
                "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b1.png&size=1000"
              }
            ],
            "tags": [
              "cards"
            ],
            "created": "2026-09-02T14:05:11Z",
            "modified": "2026-10-11T08:40:27Z"
          }
        ]
      },
      "Error": {
        "title": "Error",
        "description": "Every error the API itself returns. Match on `code`; `message` is for people and may be reworded.",
        "type": "object",
        "required": [
          "error",
          "code",
          "message",
          "requestId"
        ],
        "properties": {
          "error": {
            "type": "boolean",
            "const": true
          },
          "code": {
            "type": "string",
            "enum": [
              "unauthorized",
              "account_suspended",
              "invalid_request",
              "not_found",
              "route_not_found",
              "idempotency_key_reused",
              "idempotency_in_progress",
              "folder_not_empty",
              "builtin_folder",
              "builtin_palette",
              "editor_not_supported",
              "design_changed",
              "payload_too_large",
              "unsupported_media_type",
              "ops_failed",
              "internal_error",
              "service_unavailable"
            ],
            "description": "`unauthorized` (401): missing, unknown, revoked or expired secret key. `account_suspended` (403): the account has an unpaid invoice. `invalid_request` (400): a parameter or body field is malformed — see `param` and `details`. `not_found` (404): no such resource in your account. `route_not_found` (404): no such endpoint. `idempotency_key_reused` (409): the Idempotency-Key was used for a different request. `idempotency_in_progress` (409): the first request with that key is still running. `folder_not_empty` (409): the folder still holds designs or folders. `builtin_folder`, `builtin_palette` (409): Print.App's own folders and palettes cannot be changed. `editor_not_supported` (409): page content can only be edited on accounts that use the new editor. `design_changed` (409): the design was saved elsewhere while the batch ran; read it again and retry. `payload_too_large` (413): a body or file over the limit. `unsupported_media_type` (415): send JSON. `ops_failed` (422): an operation in the batch failed, nothing was saved — see `details`. `internal_error` (500): retry; contact support with the `requestId` if it persists. `service_unavailable` (503): retry in a few seconds."
          },
          "message": {
            "type": "string"
          },
          "param": {
            "type": "string",
            "description": "The parameter or body field at fault, as a path (`pages[0].title`)."
          },
          "details": {
            "type": "array",
            "description": "Every problem found, when there was more than one (`invalid_request`), or each operation's result (`ops_failed`).",
            "items": {
              "type": "object"
            }
          },
          "requestId": {
            "type": "string",
            "description": "Also sent as the `x-request-id` header. Quote it when contacting support."
          }
        },
        "examples": [
          {
            "error": true,
            "code": "invalid_request",
            "message": "limit must be an integer from 1 to 100.",
            "param": "limit",
            "requestId": "FZn-uhymjoEEJow="
          }
        ]
      },
      "FileCreate": {
        "title": "FileCreate",
        "description": "A file to download from a public URL.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "A public http(s) URL of a PNG, JPEG, WebP, GIF, SVG, TIFF or PDF, up to 50 MB."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "A name for the file. Default: from the URL."
          },
          "folderId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "A graphic folder to put it in."
          },
          "tags": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "description": "Labels for finding it again."
          }
        },
        "examples": [
          {
            "url": "https://example.com/logo.png",
            "title": "Logo",
            "folderId": "folder:5f0c7a52-1e1b-4c55-9c3e-2a7d0f8e6b11"
          }
        ]
      },
      "FileList": {
        "title": "FileList",
        "description": "A page of files.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/File"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "FileUpdate": {
        "title": "FileUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The file's name."
          },
          "tags": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "minLength": 1,
              "maxLength": 50
            },
            "description": "Labels for finding it again."
          }
        }
      },
      "FileUploadCreate": {
        "title": "FileUploadCreate",
        "description": "The file you are about to upload.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "filename",
          "contentType"
        ],
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The file's name, with its extension."
          },
          "contentType": {
            "type": "string",
            "enum": [
              "image/png",
              "image/jpeg",
              "image/webp",
              "image/gif",
              "image/svg+xml",
              "image/tiff",
              "application/pdf"
            ],
            "description": "The file's media type."
          },
          "size": {
            "type": "integer",
            "minimum": 1,
            "maximum": 209715200,
            "description": "The file size in bytes, up to 200 MB. The upload is refused if the file is larger."
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "A name for the file. Default: the file name."
          }
        }
      },
      "FileUpload": {
        "title": "FileUpload",
        "description": "A presigned form for one direct upload.",
        "type": "object",
        "required": [
          "object",
          "fileId",
          "upload",
          "maxBytes",
          "expiresAt"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "file_upload"
          },
          "fileId": {
            "type": "string",
            "description": "The id the file will have once uploaded."
          },
          "upload": {
            "type": "object",
            "required": [
              "method",
              "url",
              "fields"
            ],
            "properties": {
              "method": {
                "type": "string",
                "const": "POST"
              },
              "url": {
                "type": "string"
              },
              "fields": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                },
                "description": "Send every field, then the file last as `file`."
              }
            }
          },
          "maxBytes": {
            "type": "integer"
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "File": {
        "title": "File",
        "description": "An image or graphic in your account.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "contentType",
          "size",
          "width",
          "height",
          "url",
          "previewUrl",
          "tags",
          "created",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "file"
          },
          "id": {
            "type": "string",
            "description": "Use it as `asset` in design operations."
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "contentType": {
            "type": [
              "string",
              "null"
            ]
          },
          "size": {
            "type": [
              "number",
              "null"
            ],
            "description": "Bytes."
          },
          "width": {
            "type": [
              "number",
              "null"
            ],
            "description": "Pixels, when known."
          },
          "height": {
            "type": [
              "number",
              "null"
            ],
            "description": "Pixels, when known."
          },
          "url": {
            "type": "string",
            "description": "The original file."
          },
          "previewUrl": {
            "type": "string",
            "description": "A small preview image."
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "file",
            "id": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
            "title": "Logo",
            "contentType": "image/png",
            "size": 48211,
            "width": 1200,
            "height": 800,
            "url": "https://d3f4dd8gq49w54.cloudfront.net/file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png",
            "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Ffile_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png&size=300",
            "tags": [],
            "created": "2026-10-27T10:00:00Z",
            "modified": "2026-10-27T10:00:00Z"
          }
        ]
      },
      "FolderDesign": {
        "title": "FolderDesign",
        "description": "A design to put in the folder.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "designId"
        ],
        "properties": {
          "designId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The `designId`."
          }
        }
      },
      "FolderFile": {
        "title": "FolderFile",
        "description": "A file to put in the folder.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "fileId"
        ],
        "properties": {
          "fileId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The file id."
          }
        }
      },
      "FontCreate": {
        "title": "FontCreate",
        "description": "A Google font family to import, or a font file to upload. Send one of `family` or `url`.",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "family": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "A Google Fonts family name, for example `Playfair Display`. Every weight and style is imported."
          },
          "url": {
            "type": "string",
            "format": "uri",
            "maxLength": 2048,
            "description": "A public URL of a TTF, OTF, WOFF or WOFF2 file, up to 20 MB. Its family, weight and style are read from the file."
          }
        },
        "oneOf": [
          {
            "required": [
              "family"
            ]
          },
          {
            "required": [
              "url"
            ]
          }
        ],
        "examples": [
          {
            "family": "Playfair Display"
          }
        ]
      },
      "FontList": {
        "title": "FontList",
        "description": "Font families, by name.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Font"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "Font": {
        "title": "Font",
        "description": "A font family.",
        "type": "object",
        "required": [
          "object",
          "family",
          "source",
          "variants"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "font"
          },
          "family": {
            "type": "string",
            "description": "The name to use in design operations (lower case)."
          },
          "source": {
            "type": "string",
            "enum": [
              "builtin",
              "google",
              "upload"
            ]
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "weight",
                "style"
              ],
              "properties": {
                "weight": {
                  "type": "number"
                },
                "style": {
                  "type": "string",
                  "enum": [
                    "normal",
                    "italic"
                  ]
                }
              }
            }
          }
        },
        "examples": [
          {
            "object": "font",
            "family": "playfair display",
            "source": "google",
            "variants": [
              {
                "weight": 400,
                "style": "normal"
              },
              {
                "weight": 400,
                "style": "italic"
              },
              {
                "weight": 700,
                "style": "normal"
              }
            ]
          }
        ]
      },
      "GraphicFolderCreate": {
        "title": "GraphicFolderCreate",
        "description": "A new graphic folder.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder's name."
          },
          "panel": {
            "type": "string",
            "enum": [
              "pictures",
              "backgrounds",
              "textures",
              "frames"
            ],
            "default": "pictures",
            "description": "The editor panel that shows it."
          }
        }
      },
      "GraphicFolderList": {
        "title": "GraphicFolderList",
        "description": "Graphic folders, panel by panel.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GraphicFolder"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "GraphicFolderUpdate": {
        "title": "GraphicFolderUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The folder's name."
          },
          "fileIds": {
            "type": "array",
            "maxItems": 5000,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "description": "The folder's files in their new order: exactly the ids it holds now."
          }
        }
      },
      "GraphicFolder": {
        "title": "GraphicFolder",
        "description": "A folder of graphics in one of the editor's panels.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "panel",
          "fileIds",
          "builtIn",
          "created",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "graphic_folder"
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "panel": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pictures",
              "backgrounds",
              "textures",
              "frames",
              null
            ]
          },
          "fileIds": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Its files, in the order the editor shows them."
          },
          "builtIn": {
            "type": "boolean",
            "description": "Provided by Print.App: listed, but cannot be changed."
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "graphic_folder",
            "id": "folder:19d51ae0-0bbd-43c9-b3d1-8aedc4e112b3",
            "title": "Logos",
            "panel": "pictures",
            "fileIds": [
              "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
            ],
            "builtIn": false,
            "created": "2026-10-27T10:00:00Z",
            "modified": "2026-10-27T10:05:00Z"
          }
        ]
      },
      "LinkCreate": {
        "title": "LinkCreate",
        "description": "What the link opens. Send one of `designId` or `projectId`.",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "designId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "A design to start from."
          },
          "projectId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "A project to carry on with."
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the link stops working. Default: 30 days from now. At most a year."
          },
          "userData": {
            "type": "object",
            "description": "Your own details (customer, order), saved onto projects made through the link."
          }
        },
        "oneOf": [
          {
            "required": [
              "designId"
            ]
          },
          {
            "required": [
              "projectId"
            ]
          }
        ],
        "examples": [
          {
            "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "userData": {
              "email": "ada@example.com"
            }
          }
        ]
      },
      "Link": {
        "title": "Link",
        "description": "An editor link at create.print.app.",
        "type": "object",
        "required": [
          "object",
          "id",
          "url",
          "designId",
          "projectId",
          "userData",
          "expiresAt",
          "created"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "link"
          },
          "id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "description": "Send this to your customer."
          },
          "designId": {
            "type": [
              "string",
              "null"
            ]
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The project it opens, or the one a customer saved through it."
          },
          "userData": {
            "type": [
              "object",
              "null"
            ]
          },
          "expiresAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "link",
            "id": "cid_Jx81kQ",
            "url": "https://create.print.app/cid_Jx81kQ",
            "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "projectId": null,
            "userData": {
              "email": "ada@example.com"
            },
            "expiresAt": "2026-11-26T10:00:00Z",
            "created": "2026-10-27T10:00:00Z"
          }
        ]
      },
      "OpResult": {
        "title": "OpResult",
        "description": "One operation's result. Also the items of an error's `details` for `invalid_request` and `ops_failed` on `POST /v2/designs/{id}/ops`.",
        "type": "object",
        "required": [
          "index",
          "op",
          "ok"
        ],
        "properties": {
          "index": {
            "type": [
              "integer",
              "null"
            ],
            "description": "The operation's position in `ops`; null for a problem with the batch itself."
          },
          "op": {
            "type": [
              "string",
              "null"
            ]
          },
          "ok": {
            "type": "boolean"
          },
          "id": {
            "type": "string",
            "description": "The id of the item it added or changed."
          },
          "pageId": {
            "type": "string",
            "description": "The id of the page it added."
          },
          "ref": {
            "type": [
              "string",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "path": {
            "type": [
              "string",
              "null"
            ],
            "description": "The part of the operation at fault."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "OpsBatch": {
        "title": "OpsBatch",
        "description": "A batch of design operations, run in order as one change: either every operation succeeds and the design is saved, or nothing is. Each operation is checked against its own schema (the DesignOp schemas) before anything runs.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "ops"
        ],
        "properties": {
          "units": {
            "type": "string",
            "enum": [
              "mm",
              "cm",
              "in",
              "pt",
              "px"
            ],
            "description": "The unit of every box and length in the batch. Default: the design's unit (mm for designs measured in ft). Text sizes are always in points."
          },
          "page": {
            "oneOf": [
              {
                "type": "integer",
                "minimum": 1,
                "maximum": 500
              },
              {
                "type": "string",
                "minLength": 1,
                "maxLength": 40
              }
            ],
            "description": "The page item operations go on: a page number from 1, or a page's ref. An operation's own `page` wins. Default 1."
          },
          "ops": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/DesignOpTextAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpFrameAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpGraphicAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpShapeAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpPatternAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpBorderAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpModuleAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpPageAdd"
                },
                {
                  "$ref": "#/components/schemas/DesignOpPageSet"
                },
                {
                  "$ref": "#/components/schemas/DesignOpDesignSet"
                },
                {
                  "$ref": "#/components/schemas/DesignOpItemUpdate"
                },
                {
                  "$ref": "#/components/schemas/DesignOpItemRemove"
                },
                {
                  "$ref": "#/components/schemas/DesignOpAlign"
                }
              ],
              "discriminator": {
                "propertyName": "op"
              }
            },
            "description": "The operations, run in order. Items added in the batch can be targeted by later operations through their `ref`."
          },
          "dryRun": {
            "type": "boolean",
            "default": false,
            "description": "Run the batch and report every operation's result and the resulting content, without saving anything."
          }
        },
        "examples": [
          {
            "units": "mm",
            "ops": [
              {
                "op": "shape.add",
                "ref": "band",
                "kind": "rect",
                "box": [
                  0,
                  0,
                  85,
                  14
                ],
                "fill": "#1f2a44"
              },
              {
                "op": "text.add",
                "ref": "name",
                "box": [
                  6,
                  22,
                  73,
                  10
                ],
                "content": "Ada Lovelace",
                "font": "open sans",
                "size": 14,
                "weight": 700,
                "align": "left",
                "color": "#1f2a44",
                "field": {
                  "title": "Name",
                  "maxTextCount": 30
                }
              },
              {
                "op": "graphic.add",
                "ref": "logo",
                "box": [
                  62,
                  3,
                  18,
                  8
                ],
                "asset": "file_01JB2W3X4Y5Z6A7B8C9D0E1F2G.png"
              }
            ]
          }
        ]
      },
      "OpsResult": {
        "title": "OpsResult",
        "description": "The outcome of a batch that ran: every operation's result, the design as saved (unchanged on a dry run), and its content now.",
        "type": "object",
        "required": [
          "object",
          "dryRun",
          "results",
          "design",
          "content"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "ops_result"
          },
          "dryRun": {
            "type": "boolean"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OpResult"
            }
          },
          "design": {
            "$ref": "#/components/schemas/Design"
          },
          "content": {
            "$ref": "#/components/schemas/DesignContent"
          }
        }
      },
      "PageUpdate": {
        "title": "PageUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "maxLength": 100,
            "description": "The page's name."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "Move the page to this index."
          }
        }
      },
      "PagesCreate": {
        "title": "PagesCreate",
        "description": "Blank pages to add.",
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "count": {
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 1,
            "description": "How many pages to add."
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "description": "The index the first new page takes. Default: after the last page."
          },
          "titles": {
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "string",
              "maxLength": 100
            },
            "description": "A title per new page."
          }
        }
      },
      "PaletteCreate": {
        "title": "PaletteCreate",
        "description": "A new palette.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "title",
          "colors"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The palette's name."
          },
          "colors": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "hex"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "maxLength": 100,
                  "description": "The colour's name, shown in the editor."
                },
                "hex": {
                  "type": "string",
                  "format": "color",
                  "description": "The screen colour, `#rrggbb`."
                },
                "cmyk": {
                  "type": "string",
                  "pattern": "^\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}$",
                  "description": "The print colour as `c,m,y,k` percentages, for example `0,16,100,0`."
                },
                "spot": {
                  "type": "string",
                  "maxLength": 100,
                  "description": "A spot colour name for print, for example `PANTONE 186 C`."
                }
              }
            },
            "description": "The colours, in order."
          }
        },
        "examples": [
          {
            "title": "Brand",
            "colors": [
              {
                "name": "Navy",
                "hex": "#1f2a44",
                "cmyk": "100,80,30,40"
              },
              {
                "name": "Gold",
                "hex": "#c9a227",
                "spot": "PANTONE 7753 C"
              }
            ]
          }
        ]
      },
      "PaletteList": {
        "title": "PaletteList",
        "description": "Palettes.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Palette"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "PaletteUpdate": {
        "title": "PaletteUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The palette's name."
          },
          "colors": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "hex"
              ],
              "properties": {
                "name": {
                  "type": "string",
                  "maxLength": 100,
                  "description": "The colour's name, shown in the editor."
                },
                "hex": {
                  "type": "string",
                  "format": "color",
                  "description": "The screen colour, `#rrggbb`."
                },
                "cmyk": {
                  "type": "string",
                  "pattern": "^\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}$",
                  "description": "The print colour as `c,m,y,k` percentages, for example `0,16,100,0`."
                },
                "spot": {
                  "type": "string",
                  "maxLength": 100,
                  "description": "A spot colour name for print, for example `PANTONE 186 C`."
                }
              }
            },
            "description": "Replaces every colour."
          }
        }
      },
      "Palette": {
        "title": "Palette",
        "description": "A colour palette.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "colors",
          "builtIn",
          "created",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "palette"
          },
          "id": {
            "type": "string"
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "colors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "name",
                "type",
                "hex",
                "cmyk",
                "spot"
              ],
              "properties": {
                "name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "type": {
                  "type": "string",
                  "enum": [
                    "solid",
                    "foil",
                    "gradient",
                    "texture"
                  ]
                },
                "hex": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "`#rrggbb` for solid colours."
                },
                "cmyk": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "spot": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            }
          },
          "builtIn": {
            "type": "boolean",
            "description": "Provided by Print.App: it cannot be changed, only hidden by deleting it."
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "palette",
            "id": "folder:8a1d2c3b-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
            "title": "Brand",
            "colors": [
              {
                "name": "Navy",
                "type": "solid",
                "hex": "#1f2a44",
                "cmyk": "100,80,30,40",
                "spot": null
              }
            ],
            "builtIn": false,
            "created": "2026-10-27T10:00:00Z",
            "modified": "2026-10-27T10:00:00Z"
          }
        ]
      },
      "ProductList": {
        "title": "ProductList",
        "description": "A page of products, in id order.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        }
      },
      "ProductSet": {
        "title": "ProductSet",
        "description": "The designs a product opens.",
        "type": "object",
        "additionalProperties": false,
        "required": [
          "designIds"
        ],
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The product's name, shown in the dashboard. Default: the current one, or the product id."
          },
          "designIds": {
            "type": "array",
            "maxItems": 50,
            "uniqueItems": true,
            "items": {
              "type": "string"
            },
            "description": "The designs the product opens, in order. `[]` leaves only the variants' designs."
          },
          "variants": {
            "type": "array",
            "maxItems": 500,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "id",
                "designIds"
              ],
              "properties": {
                "id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "description": "The variant's id in your store."
                },
                "title": {
                  "type": "string",
                  "maxLength": 200
                },
                "designIds": {
                  "type": "array",
                  "maxItems": 50,
                  "uniqueItems": true,
                  "items": {
                    "type": "string"
                  },
                  "description": "The designs this variant opens instead of the product's."
                }
              }
            },
            "description": "Per-variant designs. Variants you leave out open the product's designs."
          }
        },
        "examples": [
          {
            "designIds": [
              "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
            ],
            "variants": [
              {
                "id": "4401",
                "designIds": [
                  "design_01J8ZB0C1D2E3F4G5H6J7K8M9N"
                ]
              }
            ]
          }
        ]
      },
      "Product": {
        "title": "Product",
        "description": "The designs one store product opens.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "designIds",
          "variants",
          "modified"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "product"
          },
          "id": {
            "type": "string",
            "description": "The product's id in your store."
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "designIds": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variants": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "id",
                "title",
                "designIds"
              ],
              "properties": {
                "id": {
                  "type": "string"
                },
                "title": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "designIds": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            },
            "description": "Variants with their own designs."
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "examples": [
          {
            "object": "product",
            "id": "8812001",
            "title": "Business cards",
            "designIds": [
              "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1"
            ],
            "variants": [],
            "modified": "2026-10-27T10:00:00Z"
          }
        ]
      },
      "ProjectList": {
        "title": "ProjectList",
        "description": "A page of projects, most recently modified first.",
        "type": "object",
        "required": [
          "object",
          "data",
          "hasMore",
          "nextCursor"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "list"
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page may follow. A following page can come back empty when a `status` filter excludes the remaining projects."
          },
          "nextCursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as `cursor` to fetch the next page, with the same filters. `null` on the last page."
          }
        }
      },
      "ProjectUpdate": {
        "title": "ProjectUpdate",
        "description": "The fields to change.",
        "type": "object",
        "additionalProperties": false,
        "minProperties": 1,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "The project's name."
          },
          "userData": {
            "type": "object",
            "description": "Merged into the project's `userData`, one level deep. A key set to `null` is removed."
          }
        }
      },
      "Project": {
        "title": "Project",
        "description": "A customer's saved design.",
        "type": "object",
        "required": [
          "object",
          "id",
          "title",
          "status",
          "product",
          "userId",
          "userData",
          "designId",
          "created",
          "modified",
          "pages",
          "exports"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "project"
          },
          "id": {
            "type": "string",
            "description": "The `projectId` from the editor's `app:saved` event."
          },
          "title": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "saved",
              "submitted"
            ],
            "description": "`submitted`: the customer finished the design (the editor's submit). `saved`: saved for later. `draft`: autosaved, not yet saved by the customer."
          },
          "product": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Exactly the `product` object your page passed to `PrintAppClient` when the project was created — for example `{ id, ref }`. Use it to check the project was made for the product being ordered. It passes through the customer's browser, so treat it as the customer's claim about the page, not as proof."
          },
          "userId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The `userId` your page passed to `PrintAppClient`, if any."
          },
          "userData": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": true,
            "description": "Customer details attached to the project by a store plugin or your page: `id`, `name`, `email`, `phone`, `info`.",
            "properties": {
              "id": {},
              "name": {
                "type": "string"
              },
              "firstName": {
                "type": "string"
              },
              "lastName": {
                "type": "string"
              },
              "email": {
                "type": "string"
              },
              "phone": {
                "type": "string"
              },
              "info": {
                "type": "string"
              }
            }
          },
          "designId": {
            "type": [
              "string",
              "null"
            ],
            "description": "The design (template) the project was made from."
          },
          "created": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "modified": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Last save."
          },
          "pages": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "index",
                "previewUrl"
              ],
              "properties": {
                "index": {
                  "type": "integer",
                  "minimum": 0
                },
                "previewUrl": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "A preview image of the page."
                }
              }
            }
          },
          "exports": {
            "type": "object",
            "required": [
              "pdf",
              "png",
              "jpeg",
              "tiff"
            ],
            "description": "Print files, rendered on request from the project's current state.",
            "properties": {
              "pdf": {
                "type": "string"
              },
              "png": {
                "type": "string"
              },
              "jpeg": {
                "type": "string"
              },
              "tiff": {
                "type": "string"
              }
            }
          }
        },
        "examples": [
          {
            "object": "project",
            "id": "project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
            "title": "Business Card",
            "status": "submitted",
            "product": {
              "id": "sku-123",
              "ref": "cart-line-7f3a"
            },
            "userId": "customer-1001",
            "userData": {
              "id": "customer-1001",
              "name": "Jane Doe",
              "email": "jane@example.com"
            },
            "designId": "design_01J8Z9K2M3N4P5Q6R7S8T9V0W1",
            "created": "2026-10-17T09:12:03Z",
            "modified": "2026-10-17T09:20:41Z",
            "pages": [
              {
                "index": 0,
                "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_a1.png&size=1000"
              },
              {
                "index": 1,
                "previewUrl": "https://d1p81tn8mwpox2.cloudfront.net/?k=s3%3A%2F%2Fapp-print-cdn%2Fcontent_b2.png&size=1000"
              }
            ],
            "exports": {
              "pdf": "https://pdf.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
              "png": "https://png.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
              "jpeg": "https://jpeg.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b",
              "tiff": "https://tiff.print.app/project_2b6f1c9e-8d0a-4c3e-9f57-0c1d2e3f4a5b"
            }
          }
        ]
      },
      "DesignOpPartRef": {
        "type": "string",
        "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$",
        "description": "A short name you choose; later ops (and later batches) can target the item by it."
      },
      "DesignOpPartTarget": {
        "type": "string",
        "minLength": 1,
        "maxLength": 100,
        "description": "An item ref or item id."
      },
      "DesignOpPartPage": {
        "oneOf": [
          {
            "type": "integer",
            "minimum": 1,
            "maximum": 500
          },
          {
            "$ref": "#/components/schemas/DesignOpPartRef"
          }
        ]
      },
      "DesignOpPartColor": {
        "type": "string",
        "pattern": "^(#[0-9A-Fa-f]{6}|#[0-9A-Fa-f]{3}|none|transparent)$",
        "description": "#rrggbb, #rgb, none or transparent."
      },
      "DesignOpPartSolidColor": {
        "type": "string",
        "pattern": "^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$"
      },
      "DesignOpPartLength": {
        "type": "number",
        "minimum": 0,
        "maximum": 100000
      },
      "DesignOpPartCoord": {
        "type": "number",
        "minimum": -100000,
        "maximum": 100000
      },
      "DesignOpPartBox": {
        "type": "array",
        "minItems": 4,
        "maxItems": 4,
        "items": {
          "$ref": "#/components/schemas/DesignOpPartCoord"
        },
        "description": "[x, y, width, height] from the trim top-left (the print window's on garment pages)."
      },
      "DesignOpPartArea": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/DesignOpPartBox"
          },
          {
            "type": "string",
            "pattern": "^(bleed|trim|safe|panel:[1-9][0-9]?)$"
          }
        ]
      },
      "DesignOpPartPoint": {
        "type": "array",
        "minItems": 2,
        "maxItems": 2,
        "items": {
          "$ref": "#/components/schemas/DesignOpPartCoord"
        }
      },
      "DesignOpPartAsset": {
        "type": "string",
        "pattern": "^[A-Za-z0-9_.:-]{1,200}$",
        "description": "One of your file ids (file_…) or a print.app library graphic id (c_…). An SVG file stays vector in print."
      },
      "DesignOpPartSvg": {
        "type": "string",
        "minLength": 10,
        "maxLength": 12000,
        "description": "SVG markup, inline. Through the API, upload SVGs as files instead (POST /v2/files or /v2/files/uploads) and place them with `asset`: the firewall in front of api.print.app refuses request bodies that carry markup, with an HTML 403."
      },
      "DesignOpPartSvgPath": {
        "type": "string",
        "minLength": 3,
        "maxLength": 20000,
        "description": "SVG path data drawn in a 0..1 box, stretched to the box."
      },
      "DesignOpPartFont": {
        "type": "string",
        "minLength": 1,
        "maxLength": 100,
        "description": "A font family name from the account's fonts (GET /v2/fonts)."
      },
      "DesignOpPartLock": {
        "type": "string",
        "enum": [
          "decor",
          "field",
          "hard",
          "none"
        ]
      },
      "DesignOpPartStroke": {
        "type": "object",
        "required": [
          "color",
          "width"
        ],
        "additionalProperties": false,
        "properties": {
          "color": {
            "$ref": "#/components/schemas/DesignOpPartColor"
          },
          "width": {
            "type": "number",
            "minimum": 0,
            "maximum": 1000
          }
        }
      },
      "DesignOpPartField": {
        "type": "object",
        "required": [
          "title"
        ],
        "additionalProperties": false,
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "maxTextCount": {
            "type": "integer",
            "minimum": 1,
            "maximum": 10000
          },
          "hint": {
            "type": "string",
            "maxLength": 300
          },
          "required": {
            "type": "boolean"
          }
        }
      },
      "DesignOpPartTextFrame": {
        "oneOf": [
          {
            "type": "string",
            "enum": [
              "wrap",
              "hug"
            ]
          },
          {
            "type": "object",
            "required": [
              "fit"
            ],
            "additionalProperties": false,
            "properties": {
              "fit": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "minSize": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 1000
                  }
                }
              }
            }
          }
        ]
      },
      "DesignOpPartOpacity": {
        "type": "number",
        "exclusiveMinimum": 0,
        "maximum": 1
      },
      "DesignOpPartDegrees": {
        "type": "number",
        "minimum": -360,
        "maximum": 360
      },
      "DesignOpPartFolds": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "v": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartLength"
            }
          },
          "h": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartLength"
            }
          }
        }
      },
      "DesignOpPartBackground": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/DesignOpPartColor"
          },
          {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "color": {
                "$ref": "#/components/schemas/DesignOpPartColor"
              },
              "asset": {
                "$ref": "#/components/schemas/DesignOpPartAsset"
              },
              "fit": {
                "type": "string",
                "enum": [
                  "cover",
                  "contain",
                  "stretch"
                ]
              }
            },
            "oneOf": [
              {
                "required": [
                  "color"
                ]
              },
              {
                "required": [
                  "asset"
                ]
              }
            ]
          }
        ]
      },
      "DesignOpTextAdd": {
        "title": "text.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "box",
          "font",
          "size",
          "align"
        ],
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "content"
            ]
          },
          {
            "required": [
              "template"
            ]
          }
        ],
        "properties": {
          "op": {
            "const": "text.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartBox"
          },
          "content": {
            "type": "string",
            "maxLength": 5000
          },
          "template": {
            "type": "string",
            "minLength": 3,
            "maxLength": 5000,
            "description": "Smart tokens: \"{Phone | type: tel, default: +1 555 0100}\"; each token is a form field."
          },
          "font": {
            "$ref": "#/components/schemas/DesignOpPartFont"
          },
          "size": {
            "type": "number",
            "minimum": 1,
            "maximum": 2000,
            "description": "pt"
          },
          "weight": {
            "type": "integer",
            "minimum": 100,
            "maximum": 900
          },
          "style": {
            "type": "string",
            "enum": [
              "normal",
              "italic"
            ]
          },
          "color": {
            "$ref": "#/components/schemas/DesignOpPartSolidColor"
          },
          "leading": {
            "type": "number",
            "minimum": 0.5,
            "maximum": 5,
            "description": "Line spacing as a multiple of size."
          },
          "tracking": {
            "type": "number",
            "minimum": -500,
            "maximum": 2000,
            "description": "Letter spacing, 1/1000 em."
          },
          "align": {
            "type": "string",
            "enum": [
              "left",
              "center",
              "right"
            ]
          },
          "anchor": {
            "type": "string",
            "enum": [
              "top",
              "center",
              "bottom"
            ]
          },
          "frame": {
            "$ref": "#/components/schemas/DesignOpPartTextFrame"
          },
          "field": {
            "$ref": "#/components/schemas/DesignOpPartField"
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          }
        }
      },
      "DesignOpFrameAdd": {
        "title": "frame.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "box"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "frame.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartBox"
          },
          "mask": {
            "type": "string",
            "enum": [
              "rect",
              "ellipse",
              "star",
              "heart",
              "arch",
              "path"
            ]
          },
          "radius": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "points": {
            "type": "integer",
            "minimum": 3,
            "maximum": 50
          },
          "path": {
            "$ref": "#/components/schemas/DesignOpPartSvgPath"
          },
          "fit": {
            "type": "string",
            "enum": [
              "cover",
              "contain"
            ]
          },
          "border": {
            "$ref": "#/components/schemas/DesignOpPartStroke"
          },
          "asset": {
            "$ref": "#/components/schemas/DesignOpPartAsset"
          },
          "svg": {
            "$ref": "#/components/schemas/DesignOpPartSvg"
          },
          "field": {
            "type": "object",
            "required": [
              "title"
            ],
            "additionalProperties": false,
            "properties": {
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 100
              },
              "hint": {
                "type": "string",
                "maxLength": 300
              }
            }
          },
          "shuffle": {
            "const": false
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          }
        }
      },
      "DesignOpGraphicAdd": {
        "title": "graphic.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "box"
        ],
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "asset"
            ]
          },
          {
            "required": [
              "svg"
            ]
          }
        ],
        "properties": {
          "op": {
            "const": "graphic.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartBox"
          },
          "asset": {
            "$ref": "#/components/schemas/DesignOpPartAsset"
          },
          "svg": {
            "$ref": "#/components/schemas/DesignOpPartSvg"
          },
          "fit": {
            "type": "string",
            "enum": [
              "contain",
              "cover",
              "stretch"
            ]
          },
          "opacity": {
            "$ref": "#/components/schemas/DesignOpPartOpacity"
          },
          "rotate": {
            "$ref": "#/components/schemas/DesignOpPartDegrees"
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          }
        }
      },
      "DesignOpShapeAdd": {
        "title": "shape.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "kind"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "shape.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "kind": {
            "type": "string",
            "enum": [
              "rect",
              "ellipse",
              "line",
              "polygon",
              "star",
              "heart",
              "path"
            ]
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartBox"
          },
          "from": {
            "$ref": "#/components/schemas/DesignOpPartPoint"
          },
          "to": {
            "$ref": "#/components/schemas/DesignOpPartPoint"
          },
          "cornerRadius": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "sides": {
            "type": "integer",
            "minimum": 3,
            "maximum": 64
          },
          "points": {
            "type": "integer",
            "minimum": 3,
            "maximum": 64
          },
          "path": {
            "$ref": "#/components/schemas/DesignOpPartSvgPath"
          },
          "fill": {
            "$ref": "#/components/schemas/DesignOpPartColor"
          },
          "stroke": {
            "$ref": "#/components/schemas/DesignOpPartStroke"
          },
          "opacity": {
            "$ref": "#/components/schemas/DesignOpPartOpacity"
          },
          "rotate": {
            "$ref": "#/components/schemas/DesignOpPartDegrees"
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          }
        }
      },
      "DesignOpPatternAdd": {
        "title": "pattern.add",
        "type": "object",
        "required": [
          "op",
          "ref"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "pattern.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartArea"
          },
          "motifs": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "items": {
              "type": "string",
              "enum": [
                "dot",
                "sparkle",
                "star",
                "snowflake",
                "plus",
                "diamond",
                "heart",
                "tree",
                "stripes"
              ]
            }
          },
          "assets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartAsset"
            }
          },
          "colors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 6,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartSolidColor"
            }
          },
          "size": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          },
          "spacing": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          },
          "layout": {
            "type": "string",
            "enum": [
              "half-drop",
              "grid"
            ]
          },
          "angle": {
            "$ref": "#/components/schemas/DesignOpPartDegrees"
          },
          "rotate": {
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartDegrees"
            }
          },
          "clear": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartBox"
            }
          },
          "opacity": {
            "$ref": "#/components/schemas/DesignOpPartOpacity"
          }
        }
      },
      "DesignOpBorderAdd": {
        "title": "border.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "style"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "border.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartArea"
          },
          "style": {
            "type": "string",
            "enum": [
              "solid",
              "line",
              "double",
              "dots",
              "candy"
            ]
          },
          "width": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          },
          "inset": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "colors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartSolidColor"
            }
          },
          "size": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          }
        }
      },
      "DesignOpModuleAdd": {
        "title": "module.add",
        "type": "object",
        "required": [
          "op",
          "ref",
          "type",
          "params"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "module.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartArea"
          },
          "type": {
            "type": "string",
            "enum": [
              "qrcode",
              "calendar",
              "curved-text",
              "stamp-grid",
              "pattern-fill"
            ]
          },
          "params": {
            "type": "object",
            "maxProperties": 40,
            "description": "Per type, as playbook/ops.md module.add (colours hex, fonts family names, sizes pt, lengths in the batch units, motifs as asset ids)."
          },
          "field": {
            "$ref": "#/components/schemas/DesignOpPartField"
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          }
        }
      },
      "DesignOpPageAdd": {
        "title": "page.add",
        "type": "object",
        "required": [
          "op",
          "ref"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "page.add"
          },
          "ref": {
            "$ref": "#/components/schemas/DesignOpPartRef"
          },
          "position": {
            "type": "integer",
            "minimum": 1,
            "maximum": 500,
            "description": "1-based index to insert at (default: the end). The new page copies the first page's size, bleed and margin."
          },
          "title": {
            "type": "string",
            "maxLength": 100
          }
        }
      },
      "DesignOpPageSet": {
        "title": "page.set",
        "type": "object",
        "required": [
          "op",
          "page"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "page.set"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "title": {
            "type": "string",
            "maxLength": 100
          },
          "folds": {
            "$ref": "#/components/schemas/DesignOpPartFolds"
          },
          "background": {
            "$ref": "#/components/schemas/DesignOpPartBackground"
          },
          "underlay": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "object",
                "required": [
                  "asset"
                ],
                "additionalProperties": false,
                "properties": {
                  "asset": {
                    "$ref": "#/components/schemas/DesignOpPartAsset"
                  },
                  "tint": {
                    "$ref": "#/components/schemas/DesignOpPartSolidColor"
                  }
                }
              }
            ]
          },
          "window": {
            "$ref": "#/components/schemas/DesignOpPartBox"
          }
        }
      },
      "DesignOpDesignSet": {
        "title": "design.set",
        "type": "object",
        "required": [
          "op"
        ],
        "additionalProperties": false,
        "minProperties": 2,
        "properties": {
          "op": {
            "const": "design.set"
          },
          "freedom": {
            "type": "string",
            "enum": [
              "templates",
              "mix",
              "free"
            ]
          },
          "settings": {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "dpiCheck": {
                "type": "boolean"
              },
              "dpi": {
                "type": "integer",
                "minimum": 72,
                "maximum": 1200
              },
              "renderCutLines": {
                "type": "boolean"
              }
            }
          },
          "modules": {
            "type": "object",
            "additionalProperties": false,
            "minProperties": 1,
            "properties": {
              "pageselector": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "title": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "maxPageCount": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 500
                  },
                  "enablePageSwap": {
                    "type": "boolean"
                  }
                }
              },
              "calendar": {
                "type": "object",
                "maxProperties": 30
              },
              "stickers": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "margin": {
                    "$ref": "#/components/schemas/DesignOpPartLength"
                  },
                  "cutlineWidth": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "autoRemoveBackground": {
                    "type": "boolean"
                  },
                  "outerEdgeOnly": {
                    "type": "boolean"
                  },
                  "showPanelToCustomers": {
                    "type": "boolean"
                  }
                }
              },
              "pattern": {
                "type": "object",
                "required": [
                  "instance"
                ],
                "maxProperties": 10,
                "properties": {
                  "instance": {
                    "$ref": "#/components/schemas/DesignOpPartRef"
                  }
                }
              },
              "photoshuffle": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "promptOnLaunch": {
                    "type": "boolean"
                  },
                  "autoFill": {
                    "type": "boolean"
                  },
                  "allowShuffle": {
                    "type": "boolean"
                  },
                  "minPhotos": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 500
                  },
                  "maxPhotos": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 500
                  }
                }
              },
              "mailmerge": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "numbers",
                      "list"
                    ]
                  },
                  "start": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "linkQuantity": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      },
      "DesignOpItemUpdate": {
        "title": "item.update",
        "type": "object",
        "required": [
          "op",
          "target"
        ],
        "additionalProperties": false,
        "minProperties": 3,
        "description": "Changes an item. Items added earlier in the same batch take any property of the op that added them. Items already on the saved design take: box, content, font, size, weight, style, color, leading, tracking, align, anchor, fill, stroke, opacity, rotate, lock, field, asset, svg, cornerRadius.",
        "properties": {
          "op": {
            "const": "item.update"
          },
          "target": {
            "$ref": "#/components/schemas/DesignOpPartTarget"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          },
          "box": {
            "$ref": "#/components/schemas/DesignOpPartArea"
          },
          "content": {
            "type": "string",
            "maxLength": 5000
          },
          "template": {
            "type": "string",
            "minLength": 3,
            "maxLength": 5000
          },
          "font": {
            "$ref": "#/components/schemas/DesignOpPartFont"
          },
          "size": {
            "type": "number",
            "minimum": 1,
            "maximum": 2000
          },
          "weight": {
            "type": "integer",
            "minimum": 100,
            "maximum": 900
          },
          "style": {
            "type": "string",
            "enum": [
              "normal",
              "italic"
            ]
          },
          "color": {
            "$ref": "#/components/schemas/DesignOpPartSolidColor"
          },
          "leading": {
            "type": "number",
            "minimum": 0.5,
            "maximum": 5
          },
          "tracking": {
            "type": "number",
            "minimum": -500,
            "maximum": 2000
          },
          "align": {
            "type": "string",
            "enum": [
              "left",
              "center",
              "right"
            ]
          },
          "anchor": {
            "type": "string",
            "enum": [
              "top",
              "center",
              "bottom"
            ]
          },
          "frame": {
            "$ref": "#/components/schemas/DesignOpPartTextFrame"
          },
          "field": {
            "type": "object"
          },
          "lock": {
            "$ref": "#/components/schemas/DesignOpPartLock"
          },
          "mask": {
            "type": "string",
            "enum": [
              "rect",
              "ellipse",
              "star",
              "heart",
              "arch",
              "path"
            ]
          },
          "radius": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "points": {
            "type": "integer",
            "minimum": 3,
            "maximum": 64
          },
          "sides": {
            "type": "integer",
            "minimum": 3,
            "maximum": 64
          },
          "path": {
            "$ref": "#/components/schemas/DesignOpPartSvgPath"
          },
          "fit": {
            "type": "string",
            "enum": [
              "contain",
              "cover",
              "stretch"
            ]
          },
          "border": {
            "$ref": "#/components/schemas/DesignOpPartStroke"
          },
          "asset": {
            "$ref": "#/components/schemas/DesignOpPartAsset"
          },
          "svg": {
            "$ref": "#/components/schemas/DesignOpPartSvg"
          },
          "shuffle": {
            "const": false
          },
          "kind": {
            "type": "string",
            "enum": [
              "rect",
              "ellipse",
              "line",
              "polygon",
              "star",
              "heart",
              "path"
            ]
          },
          "from": {
            "$ref": "#/components/schemas/DesignOpPartPoint"
          },
          "to": {
            "$ref": "#/components/schemas/DesignOpPartPoint"
          },
          "cornerRadius": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "fill": {
            "$ref": "#/components/schemas/DesignOpPartColor"
          },
          "stroke": {
            "$ref": "#/components/schemas/DesignOpPartStroke"
          },
          "opacity": {
            "$ref": "#/components/schemas/DesignOpPartOpacity"
          },
          "rotate": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/DesignOpPartDegrees"
              },
              {
                "type": "array",
                "minItems": 1,
                "maxItems": 12,
                "items": {
                  "$ref": "#/components/schemas/DesignOpPartDegrees"
                }
              }
            ]
          },
          "motifs": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "items": {
              "type": "string"
            }
          },
          "assets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 4,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartAsset"
            }
          },
          "colors": {
            "type": "array",
            "minItems": 1,
            "maxItems": 6,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartSolidColor"
            }
          },
          "spacing": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          },
          "layout": {
            "type": "string",
            "enum": [
              "half-drop",
              "grid"
            ]
          },
          "angle": {
            "$ref": "#/components/schemas/DesignOpPartDegrees"
          },
          "clear": {
            "type": "array",
            "maxItems": 30,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartBox"
            }
          },
          "width": {
            "type": "number",
            "exclusiveMinimum": 0,
            "maximum": 100000
          },
          "inset": {
            "$ref": "#/components/schemas/DesignOpPartLength"
          },
          "params": {
            "type": "object",
            "maxProperties": 40
          }
        }
      },
      "DesignOpItemRemove": {
        "title": "item.remove",
        "type": "object",
        "required": [
          "op",
          "target"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "item.remove"
          },
          "target": {
            "$ref": "#/components/schemas/DesignOpPartTarget"
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          }
        }
      },
      "DesignOpAlign": {
        "title": "align",
        "type": "object",
        "required": [
          "op",
          "targets",
          "edge"
        ],
        "additionalProperties": false,
        "properties": {
          "op": {
            "const": "align"
          },
          "targets": {
            "type": "array",
            "minItems": 1,
            "maxItems": 50,
            "items": {
              "$ref": "#/components/schemas/DesignOpPartTarget"
            }
          },
          "edge": {
            "type": "string",
            "enum": [
              "left",
              "right",
              "top",
              "bottom",
              "centerX",
              "centerY"
            ]
          },
          "to": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "safe, page, panel or a ref (default: the first target)."
          },
          "page": {
            "$ref": "#/components/schemas/DesignOpPartPage"
          }
        }
      },
      "GatewayError": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "description": "Returned by the API gateway itself (429)."
      }
    }
  }
}
