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

# Save feedback

> Requires a connection owned by a current workspace owner/admin with ai:use and conversations:read.
Feedback belongs to that human and is also visible in the app. Only the exact connection that created the result can access it through this API; other connections and private app results are excluded.
Read the current revision and targetVersion before saving or withdrawing. Identical lost-response retries are safe with the same body; stale changes return 409. No Idempotency-Key is needed.
Personal visibility is the default. Explicit workspace visibility shares the answer and correction for workspace review. Withdrawal retains revision history and removes the active feedback.
This records feedback using the existing feedback system; it does not guarantee a future answer, publish guidance, invoke a model, or consume AI generation credits.




## OpenAPI

````yaml PUT /ai/feedback/{kind}/{targetId}
openapi: 3.1.0
info:
  title: Protodesk API
  version: 0.1.0
  description: >
    The Protodesk Platform API: sync your customers in, attach your own business
    objects (orders, bookings, listings) to conversations, post and read
    messages across channels, and receive every workspace event via signed
    webhooks or a resumable SSE stream.


    Authenticate every request with a workspace-scoped API key: `Authorization:
    Bearer pk_...`. Operations that support retry protection document an
    `Idempotency-Key` header. Reuse it only with an identical request. List
    pagination is described on each endpoint.


    Task-oriented guides: [docs.protodesk.io](https://docs.protodesk.io).
servers:
  - url: https://api.protodesk.io/v1
    description: Production
  - url: http://localhost:8080/v1
    description: Local development
security: []
tags:
  - name: Evelin
    description: >-
      Human-owned AI connections using the existing Evelin runtime. Generation
      never sends a customer message.
  - name: Customers
    description: People or companies contacting a workspace across channels.
  - name: Conversations
    description: Customer conversations attached to channels and external business objects.
  - name: Messages
    description: Customer, agent, AI, system, and internal messages inside conversations.
  - name: Attachments
    description: Scoped file transfer for messages.
  - name: Channel identities
    description: >-
      The same customer across WhatsApp, email, chat, and more — linked
      identities per channel.
  - name: Statuses & priorities
    description: The workspace's conversation statuses and priority levels.
  - name: Assignments
    description: >-
      Who a conversation has been assigned to, over time. Assign via POST
      /conversations/{conversationId}/assign.
  - name: Webhooks
    description: Webhook subscriptions for receiving workspace events.
  - name: Realtime
    description: Server-sent event stream of workspace events.
  - name: API Keys
    description: Create, list, and revoke workspace API keys.
  - name: Account
    description: The workspace and scopes behind your API key.
  - name: System
    description: Service metadata and health endpoints.
paths:
  /ai/feedback/{kind}/{targetId}:
    parameters:
      - name: kind
        in: path
        required: true
        description: >-
          Use reply_draft for suggested replies and follow-ups; artifact for
          rewrites, translations, and draft reviews.
        schema:
          type: string
          enum:
            - reply_draft
            - artifact
      - name: targetId
        in: path
        required: true
        description: >-
          The artifactId from a completed result created by this exact API key
          or OAuth connection.
        schema:
          type: string
    put:
      tags:
        - Evelin
      summary: Save feedback on an Evelin result
      description: >
        Requires a connection owned by a current workspace owner/admin with
        ai:use and conversations:read.

        Feedback belongs to that human and is also visible in the app. Only the
        exact connection that created the result can access it through this API;
        other connections and private app results are excluded.

        Read the current revision and targetVersion before saving or
        withdrawing. Identical lost-response retries are safe with the same
        body; stale changes return 409. No Idempotency-Key is needed.

        Personal visibility is the default. Explicit workspace visibility shares
        the answer and correction for workspace review. Withdrawal retains
        revision history and removes the active feedback.

        This records feedback using the existing feedback system; it does not
        guarantee a future answer, publish guidance, or start a new Evelin
        generation run.
      operationId: save_evelin_feedback
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/EvelinFeedbackRequest'
            example:
              expectedRevision: 0
              targetVersion: '0000000000000000000000000000000000000000000000000000000000000000'
              signal: helpful
              reason: useful
              visibility: personal
      responses:
        '200':
          description: Current feedback state, including revision after withdrawal.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                properties:
                  data:
                    $ref: '#/components/schemas/EvelinFeedbackState'
        default:
          $ref: '#/components/responses/Error'
      security:
        - ApiKeyAuth: []
components:
  schemas:
    EvelinFeedbackRequest:
      type: object
      additionalProperties: false
      required:
        - expectedRevision
        - targetVersion
        - signal
      properties:
        expectedRevision:
          type: integer
          minimum: 0
        targetVersion:
          type: string
          minLength: 64
          maxLength: 64
        signal:
          type: string
          enum:
            - helpful
            - needs_improvement
        reason:
          type: string
          enum:
            - ''
            - incorrect_information
            - missing_details
            - wrong_tone
            - repeated_question
            - other
            - accurate
            - clear
            - useful
            - good_tone
        correction:
          type: string
          maxLength: 1000
        visibility:
          type: string
          enum:
            - personal
            - workspace
          default: personal
          description: Workspace shares the answer and correction with workspace reviewers.
    EvelinFeedbackState:
      type: object
      required:
        - revision
        - visibility
        - targetVersion
        - feedback
      properties:
        revision:
          type: integer
          minimum: 0
        visibility:
          type: string
          enum:
            - personal
            - workspace
        targetVersion:
          type: string
        feedback:
          type:
            - object
            - 'null'
          properties:
            revision:
              type: integer
            targetVersion:
              type: string
            signal:
              type: string
              enum:
                - helpful
                - needs_improvement
            reason:
              type: string
            correction:
              type: string
            sharedWithReviewers:
              type: boolean
            updatedAt:
              type: string
              format: date-time
        review:
          type: object
          description: >-
            Reporter-safe review outcome; no reviewer identity or internal
            notes.
          properties:
            feedbackRevision:
              type: integer
            status:
              type: string
            decision:
              type: string
            reviewedAt:
              type: string
              format: date-time
    ErrorEnvelope:
      type: object
      required:
        - error
      properties:
        error:
          $ref: '#/components/schemas/Error'
    Error:
      type: object
      required:
        - code
        - message
        - requestId
      properties:
        code:
          type: string
          example: route.not_found
        message:
          type: string
          example: Not found
        requestId:
          type: string
          example: req_x6q5vl75f5d53m7oet2k4r5w6a
  responses:
    Error:
      description: >-
        Error response. All /v1 responses carry RateLimit-Limit,
        RateLimit-Remaining, and RateLimit-Reset headers. A 429
        (rate_limit.exceeded) additionally carries Retry-After. Request bodies
        exceeding the route-class limit (1KB reads, 64KB writes) return 413
        (request.body_too_large).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/RequestId'
        RateLimit-Limit:
          $ref: '#/components/headers/RateLimitLimit'
        RateLimit-Remaining:
          $ref: '#/components/headers/RateLimitRemaining'
        RateLimit-Reset:
          $ref: '#/components/headers/RateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorEnvelope'
  headers:
    RequestId:
      description: Request id for tracing this request in logs and support.
      schema:
        type: string
        example: req_x6q5vl75f5d53m7oet2k4r5w6a
    RateLimitLimit:
      description: >-
        Request budget for the route class (read or write) applied to this
        request.
      schema:
        type: integer
        example: 40
    RateLimitRemaining:
      description: Requests remaining in the current budget after this request.
      schema:
        type: integer
        example: 39
    RateLimitReset:
      description: Seconds until the budget refills to its full limit.
      schema:
        type: integer
        example: 1
    RetryAfter:
      description: Seconds to wait before retrying, sent with 429 responses.
      schema:
        type: integer
        example: 1
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: Protodesk API key
      description: >
        Use a workspace API key in the Authorization header: Bearer pk_....
        Older pk_live_ and pk_test_ keys remain valid; their prefixes do not
        isolate data or select a separate environment.

````

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