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

# Import comments

> Import external review comments, replies, and action responses onto the latest version. Returns per-item results in request order. Send externalCommentId on every item for safe sequential retries; concurrent duplicate requests may race. Location anchors must already be collapsed: send the centre point of a region, and the start timestamp of a time range. Omit location entirely for an unanchored (sidebar) thread. Newly imported comments may not appear in GET immediately — allow a short delay before using GET to resolve parentCommentId.



## OpenAPI

````yaml /openapi/integration-api.json post /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 (Unkey API key) and the
    `X-External-User-ID` header.

    `X-External-User-Email` is optional.


    ## 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  /v1/links/{uploadId}  (poll every few seconds)

    →  200 { status: "completed", finalUploadId }

    ```

    Use the resulting uploadId (or `finalUploadId` for Figma) with `fileFormat:
    "image"`

    when creating a promotion. 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)

    ```


    ### 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, issue count, and any metadata you provided.


    ### 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 and public Figma links as image 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:
    post:
      tags:
        - Evaluation
      summary: Import comments
      description: >-
        Import external review comments, replies, and action responses onto the
        latest version. Returns per-item results in request order. Send
        externalCommentId on every item for safe sequential retries; concurrent
        duplicate requests may race. Location anchors must already be collapsed:
        send the centre point of a region, and the start timestamp of a time
        range. Omit location entirely for an unanchored (sidebar) thread. Newly
        imported comments may not appear in GET immediately — allow a short
        delay before using GET to resolve parentCommentId.
      operationId: postComments
      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: External user identifier from the calling system
        - name: X-External-User-Email
          in: header
          required: false
          schema:
            type: string
            format: email
          description: External user email from the calling system
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PostCommentsRequest'
      responses:
        '200':
          description: Import results (partial success)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PostCommentsResponse'
        '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'
        '409':
          description: Version is not the current latest version
          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:
    PostCommentsRequest:
      type: object
      properties:
        comments:
          type: array
          items:
            $ref: '#/components/schemas/PostCommentItem'
          minItems: 1
          maxItems: 100
      required:
        - comments
    PostCommentsResponse:
      type: object
      properties:
        results:
          type: array
          items:
            $ref: '#/components/schemas/PostCommentItemResult'
        summary:
          type: object
          properties:
            created:
              type: integer
            skipped:
              type: integer
            rejected:
              type: integer
          required:
            - created
            - 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
    PostCommentItem:
      type: object
      properties:
        externalCommentId:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[\x20-\x7E]+$
          description: >-
            Optional caller id used for in-batch threading and sequential retry
            dedup. Must be unique within the version across all integrations, so
            prefix it with something that identifies your system.
        author:
          $ref: '#/components/schemas/PostCommentAuthor'
        content:
          type: string
          minLength: 1
          maxLength: 20000
          description: >-
            Comment text. Required for roots, ordinary replies, and
            action:reply. Optional for canned action responses.
        createdAt:
          type: string
          format: date-time
        uploadId:
          type: string
          format: uuid
          description: Required on roots when the version has multiple uploads
        location:
          $ref: '#/components/schemas/PostCommentLocation'
        parentCommentId:
          type: string
          description: Reply to an existing Adclear comment id
        parentExternalCommentId:
          type: string
          minLength: 1
          maxLength: 128
          pattern: ^[\x20-\x7E]+$
          description: Reply to a root imported in this or a prior request
        action:
          type: string
          enum:
            - agree_to_action
            - agree_will_action
            - dismiss
            - dispute
            - relevant_not_required
            - reply
          description: When present, item is an action response on an AI thread
      required:
        - author
    PostCommentItemResult:
      type: object
      properties:
        index:
          type: integer
        externalCommentId:
          type:
            - string
            - 'null'
        status:
          type: string
          enum:
            - created
            - skipped
            - rejected
        threadId:
          type: string
        commentId:
          type: string
        reason:
          type: string
          enum:
            - already_imported
        error:
          type: object
          properties:
            code:
              type: string
              enum:
                - AUTHOR_UNAVAILABLE
                - PARENT_NOT_FOUND
                - UPLOAD_NOT_FOUND
                - LOCATION_INVALID
                - ACTION_TARGET_INVALID
                - DEDUP_CAPACITY_EXCEEDED
                - 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
    PostCommentLocation:
      oneOf:
        - $ref: '#/components/schemas/PostCommentImageLocation'
        - $ref: '#/components/schemas/PostCommentPdfLocation'
        - $ref: '#/components/schemas/PostCommentTimecodeLocation'
        - $ref: '#/components/schemas/PostCommentTextLocation'
      discriminator:
        propertyName: type
        mapping:
          image:
            $ref: '#/components/schemas/PostCommentImageLocation'
          pdf:
            $ref: '#/components/schemas/PostCommentPdfLocation'
          timecode:
            $ref: '#/components/schemas/PostCommentTimecodeLocation'
          text:
            $ref: '#/components/schemas/PostCommentTextLocation'
      description: Anchor for root comments only (already-collapsed point/time/text)
    PostCommentImageLocation:
      type: object
      properties:
        type:
          type: string
          enum:
            - image
        xRatio:
          type: number
          minimum: 0
          maximum: 1
        yRatio:
          type: number
          minimum: 0
          maximum: 1
      required:
        - type
        - xRatio
        - yRatio
    PostCommentPdfLocation:
      type: object
      properties:
        type:
          type: string
          enum:
            - pdf
        pageNumber:
          type: integer
          minimum: 1
        xRatio:
          type: number
          minimum: 0
          maximum: 1
        yRatio:
          type: number
          minimum: 0
          maximum: 1
      required:
        - type
        - pageNumber
        - xRatio
        - yRatio
    PostCommentTimecodeLocation:
      type: object
      properties:
        type:
          type: string
          enum:
            - timecode
        timeSeconds:
          type: number
          minimum: 0
          description: Single timestamp in seconds. Collapse a time range to its start.
      required:
        - type
        - timeSeconds
    PostCommentTextLocation:
      type: object
      properties:
        type:
          type: string
          enum:
            - text
        textToFind:
          type: string
          minLength: 1
          maxLength: 5000
      required:
        - type
        - textToFind
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      description: Unkey API key passed as Bearer token

````