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

# Update comments

> Update existing comments on a version — edit the body (content), change the action response, or both. Identify each comment by its Adclear commentId or your own externalCommentId. Fields you omit are left unchanged. Returns per-item results in request order. Action changes must target a reply on an Adclear AI thread and require author. A newly imported reply may take a short moment to become resolvable by externalCommentId — use commentId to update it immediately.



## OpenAPI

````yaml /openapi/integration-api.json patch /v1/promotions/{promotionId}/versions/{versionId}/comments
openapi: 3.1.0
info:
  title: Adclear Public API
  version: 1.0.0
  description: >
    REST API for managing promotions, versions, evaluations, and reference data.


    ## Authentication

    All requests require a Bearer token (your API key) and the
    `X-External-User-ID` header,

    identifying the acting user in your system. The value is recorded against
    every audited

    action the request performs; requests without it are rejected with 400.


    `X-External-User-Email` is only meaningful on keys with act-on-behalf
    enabled, where it

    is resolved to the matching Adclear user and becomes mandatory on writes. On
    ordinary

    keys it is ignored.


    ## Quick Start


    ### 1. Upload files

    Use the **File API** at `files.adclear.ai`
    ([docs](https://files.adclear.ai/v1/docs)):

    ```

    POST https://files.adclear.ai/v1/uploads  →  { uploadId, uploadUrl }

    PUT  {uploadUrl}  (binary file)

    ```


    ### 1b. Or submit a link

    Generic URLs are captured synchronously as a full-page screenshot (up to 2
    minutes —

    set a generous client timeout). Limited to 10 requests per minute per API
    key.

    ```

    POST /v1/links  { url }  →  201 { uploadId, fileFormat: "image" }

    ```

    Figma links import asynchronously. The file must be shared with "anyone with
    the link",

    and a frame must be identified via the node-id in the URL ("copy link to
    frame" in Figma),

    the `figmaFrameId` field, or discovery via `POST /v1/links/figma/frames`:

    ```

    POST /v1/links  { url: "https://www.figma.com/design/KEY/Name?node-id=1-23"
    }

    →  202 { uploadId, statusUrl }

    GET  {statusUrl}  (poll every few seconds)

    →  200 { status: "completed", finalUploadId }

    ```

    Google Drive and Google Docs links import asynchronously too, and must also
    be shared

    with "anyone with the link" (the API has no connected Google account, so
    private files

    are unreachable). Native Docs, Sheets and Slides are converted to PDF:

    ```

    POST /v1/links  { url: "https://docs.google.com/document/d/KEY/edit" }

    →  202 { uploadId, fileFormat: "pdf", source: "gdrive", statusUrl }

    GET  {statusUrl}  (poll every few seconds)

    →  200 { status: "completed", finalUploadId }

    ```

    Always poll `statusUrl` exactly as returned — it carries the source the poll
    needs.

    Use the resulting uploadId (or `finalUploadId`) when creating a promotion,
    with the

    `fileFormat` from the capture response rather than a fixed value:
    screenshots and Figma

    frames are always `image`, but a Drive file can be any supported format.
    Very large

    Figma frames (over ~6 megapixels) cannot be imported via the API yet.


    ### 2. Create a promotion

    ```

    POST /v1/promotions  { uploadIds, fileFormat, promotionName, ... }

    →  201 { promotionId, versionId }

    →  409 if uploads not yet ready (retry after a short delay)

    ```


    #### Field limits

    The free-text `details` field ("Additional details" in the UI) accepts up to

    **1,500 characters** on every path — single promotions, each entry of a

    `variations[]` set, and new versions (`POST /v1/promotions/{id}/versions`).

    Over-length values are rejected with a `400 VALIDATION_ERROR` whose

    `error.details[]` identifies the offending field (e.g. `details` or

    `variations.2.details`) and the permitted length — no binary-searching
    required.


    ### 3. Trigger evaluation

    ```

    POST /v1/promotions/{id}/versions/{id}/evaluate

    →  202 { evaluationId, status: "processing" }

    ```


    ### 4. Receive results via webhook

    An `evaluation-completed` webhook is sent to your configured endpoint

    with the evaluation status, issues, and any metadata you provided.
    Comment-backed

    issues normally include a `commentId`; replayed deliveries may omit it. Send
    it as

    `parentCommentId` when posting a reply.

    If that reply briefly returns `PARENT_NOT_FOUND`, retry because comment
    indexing is asynchronous.


    ### 5. Submit revisions (if needed)

    Upload new files, then create a new version on the same promotion:

    ```

    POST /v1/promotions/{id}/versions  { uploadIds, fileFormat, ... }

    →  201 { versionId, version: 2 }

    ```


    ---
servers:
  - url: https://public-api.adclear.ai
    description: Production
  - url: https://public-api-staging.adclear.ai
    description: Staging
security:
  - BearerAuth: []
tags:
  - name: Promotions
    description: Promotion and version management
  - name: Links
    description: >-
      Submit URLs, public Figma frames and public Google Drive files as uploads
      for promotions
  - name: Evaluation
    description: AI evaluation triggers and results
  - name: Reference Data
    description: Read-only lookups for products, channels, jurisdictions, target markets
externalDocs:
  description: File uploads are handled by the File Proxy API (files.adclear.ai)
  url: https://files.adclear.ai/v1/docs
paths:
  /v1/promotions/{promotionId}/versions/{versionId}/comments:
    patch:
      tags:
        - Evaluation
      summary: Update comments
      description: >-
        Update existing comments on a version — edit the body (content), change
        the action response, or both. Identify each comment by its Adclear
        commentId or your own externalCommentId. Fields you omit are left
        unchanged. Returns per-item results in request order. Action changes
        must target a reply on an Adclear AI thread and require author. A newly
        imported reply may take a short moment to become resolvable by
        externalCommentId — use commentId to update it immediately.
      operationId: patchComments
      parameters:
        - schema:
            type: string
            format: uuid
            description: Promotion ID
          required: true
          name: promotionId
          in: path
        - schema:
            type: string
            format: uuid
            description: Version ID
          required: true
          name: versionId
          in: path
        - name: X-External-User-ID
          in: header
          required: true
          schema:
            type: string
          description: >-
            Identifier of the acting user in the calling system (e.g. a
            Workfront user id). Recorded against every audited action this
            request performs.
        - name: X-External-User-Email
          in: header
          required: false
          schema:
            type: string
            format: email
          description: >-
            Acting user email. Only meaningful on keys with act-on-behalf
            enabled, where it is resolved to the matching Adclear user and is
            mandatory on writes. Ignored on ordinary keys.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PatchCommentsRequest'
      responses:
        '200':
          description: Update results (partial success)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PatchCommentsResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Unauthorized — missing or invalid API key
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Promotion or version not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limited
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: >-
            Author identity could not be resolved because an upstream service
            was unavailable. Nothing was written; the request is safe to retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - BearerAuth: []
components:
  schemas:
    PatchCommentsRequest:
      type: object
      properties:
        comments:
          type: array
          items:
            $ref: '#/components/schemas/PatchCommentItem'
          minItems: 1
          maxItems: 100
      required:
        - comments
    PatchCommentsResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/PatchCommentItemResult'
        summary:
          type: object
          properties:
            updated:
              type: integer
            skipped:
              type: integer
            rejected:
              type: integer
          required:
            - updated
            - skipped
            - rejected
        correlationId:
          type: string
          format: uuid
          description: Correlation ID for request tracing. Include in support requests.
      required:
        - results
        - summary
        - correlationId
    ErrorResponse:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - VALIDATION_ERROR
                - INVALID_REQUEST
                - UNAUTHORIZED
                - FORBIDDEN
                - NOT_FOUND
                - CONFLICT
                - PAYLOAD_TOO_LARGE
                - RATE_LIMITED
                - INTERNAL_ERROR
                - UPSTREAM_ERROR
            message:
              type: string
            details:
              type: array
              items:
                oneOf:
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - field_error
                      field:
                        type: string
                      message:
                        type: string
                    required:
                      - type
                      - field
                      - message
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - constraint_violation
                      constraint:
                        type: string
                      limit:
                        type: number
                      actual:
                        type: number
                    required:
                      - type
                      - constraint
                      - limit
                      - actual
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - retry_info
                      retryAfterSeconds:
                        type: number
                    required:
                      - type
                      - retryAfterSeconds
                  - type: object
                    properties:
                      type:
                        type: string
                        enum:
                          - upload_not_ready
                      uploadId:
                        type: string
                        format: uuid
                    required:
                      - type
                      - uploadId
          required:
            - code
            - message
        correlationId:
          type: string
          format: uuid
      required:
        - error
        - correlationId
    PatchCommentItem:
      type: object
      properties:
        commentId:
          type: string
          minLength: 1
          description: >-
            Adclear comment id to update (as returned by import or GET).
            Resolves any comment — root or reply.
        externalCommentId:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[\x20-\x7E]+$
          description: >-
            Your own id for the comment to update. Resolves a root immediately
            after import; a reply becomes resolvable by it after a short sync
            delay. Send commentId to update a reply straight away. When both are
            given, commentId wins.
        author:
          allOf:
            - $ref: '#/components/schemas/PostCommentAuthor'
            - description: >-
                Identity making the change. Required only when action is present
                — it sets who took the decision. A body-only edit keeps the
                original author.
        content:
          type: string
          minLength: 1
          maxLength: 20000
          description: >-
            New comment text. Replaces the body. With action, it is appended to
            the canned decision text; on its own it replaces the whole body.
        action:
          type: string
          enum:
            - agree_to_action
            - agree_will_action
            - dismiss
            - dispute
            - relevant_not_required
            - reply
          description: >-
            Set or change the action response. The target must be a reply on an
            Adclear AI thread. Omit to leave the action unchanged.
    PatchCommentItemResult:
      type: object
      properties:
        index:
          type: integer
        commentId:
          type: string
        externalCommentId:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - updated
            - skipped
            - rejected
        threadId:
          type: string
        reason:
          type: string
          enum:
            - not_modified
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - COMMENT_NOT_FOUND
                - COMMENT_AMBIGUOUS
                - ACTION_TARGET_INVALID
                - AUTHOR_UNAVAILABLE
                - INVALID_ITEM
                - WRITE_FAILED
            message:
              type: string
          required:
            - code
            - message
      required:
        - index
        - externalCommentId
        - status
    PostCommentAuthor:
      type: object
      properties:
        email:
          type: string
          format: email
          description: >-
            Primary email of the comment author (required for identity
            resolution)
        displayName:
          type: string
          maxLength: 256
          description: Trace metadata only — not persisted
        sourceUserId:
          type: string
          maxLength: 256
          description: Trace metadata only — not persisted
        sourceRole:
          type: string
          maxLength: 64
          description: Trace metadata only — never used for authorization
      required:
        - email
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: API key passed as Bearer token

````