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

# Edit page content

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

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



## OpenAPI

````yaml openapi.json POST /v2/designs/{id}/ops
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/designs/{id}/ops:
    post:
      tags:
        - Designs
      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.


        Place 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.
      operationId: applyOps
      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=
components:
  schemas:
    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'
    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=
    GatewayError:
      type: object
      properties:
        message:
          type: string
      description: Returned by the API gateway itself (429).
    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'
    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
    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'
    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
    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.
    DesignOpPartPage:
      oneOf:
        - type: integer
          minimum: 1
          maximum: 500
        - $ref: '#/components/schemas/DesignOpPartRef'
    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).
    DesignOpPartFont:
      type: string
      minLength: 1
      maxLength: 100
      description: A font family name from the account's fonts (GET /v2/fonts).
    DesignOpPartSolidColor:
      type: string
      pattern: ^#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})$
    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
    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
    DesignOpPartLock:
      type: string
      enum:
        - decor
        - field
        - hard
        - none
    DesignOpPartLength:
      type: number
      minimum: 0
      maximum: 100000
    DesignOpPartSvgPath:
      type: string
      minLength: 3
      maxLength: 20000
      description: SVG path data drawn in a 0..1 box, stretched to the box.
    DesignOpPartStroke:
      type: object
      required:
        - color
        - width
      additionalProperties: false
      properties:
        color:
          $ref: '#/components/schemas/DesignOpPartColor'
        width:
          type: number
          minimum: 0
          maximum: 1000
    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.
    DesignOpPartOpacity:
      type: number
      exclusiveMinimum: 0
      maximum: 1
    DesignOpPartDegrees:
      type: number
      minimum: -360
      maximum: 360
    DesignOpPartPoint:
      type: array
      minItems: 2
      maxItems: 2
      items:
        $ref: '#/components/schemas/DesignOpPartCoord'
    DesignOpPartColor:
      type: string
      pattern: ^(#[0-9A-Fa-f]{6}|#[0-9A-Fa-f]{3}|none|transparent)$
      description: '#rrggbb, #rgb, none or transparent.'
    DesignOpPartArea:
      oneOf:
        - $ref: '#/components/schemas/DesignOpPartBox'
        - type: string
          pattern: ^(bleed|trim|safe|panel:[1-9][0-9]?)$
    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
    DesignOpPartTarget:
      type: string
      minLength: 1
      maxLength: 100
      description: An item ref or item id.
    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`.'
    DesignOpPartCoord:
      type: number
      minimum: -100000
      maximum: 100000
  headers:
    RequestId:
      description: Identifies the request. Quote it when contacting support.
      schema:
        type: string
  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.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.