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

# Submit Message Feedback

> Submit user feedback (thumbs up/down and optional text) for a message. Supports both Auth0 JWT and device-based authentication for guest users.

Submit user feedback (like/dislike rating and optional text comments) for a specific message. This endpoint supports both registered users (Auth0 JWT) and guest users (device-based authentication), making it accessible during free trial flows.

## Authentication Methods

Unlike other conversation endpoints, this route accepts **two authentication methods**:

1. **Auth0 JWT** (Registered users)
   * Header: `Authorization: Bearer <token>`
   * Standard authenticated flow

2. **Device-based** (Guest users)
   * Headers: `x-device-id`, `x-user-id`, `x-platform`
   * Same authentication as `/api/v1/ai/chat`
   * Enables feedback during trial/guest sessions

## Use Cases

* **Thumbs up/down** on AI responses
* **Report inaccuracies** with text feedback
* **Track user satisfaction** for model improvements
* **A/B testing** different prompts or models

## Request Body

| Field      | Type      | Required | Description                              |
| ---------- | --------- | -------- | ---------------------------------------- |
| `rating`   | `1 \| -1` | ✅ Yes    | `1` for like (👍), `-1` for dislike (👎) |
| `feedback` | `string`  | ❌ No     | Optional text feedback (max 1000 chars)  |

## Response

Returns the updated feedback data with a timestamp.

```json theme={null}
{
  "success": true,
  "data": {
    "messageId": "507f1f77bcf86cd799439011",
    "rating": 1,
    "feedback": "Very helpful explanation!",
    "updatedAt": "2025-12-10T08:35:00.000Z"
  },
  "meta": {
    "timestamp": "2025-12-10T08:35:00.000Z",
    "requestId": "req_abc123"
  }
}
```

## Examples

<CodeGroup>
  ```bash Registered User (JWT) theme={null}
  curl -X POST \
    'https://api.handauncle.com/api/v1/user/messages/507f1f77bcf86cd799439011/feedback' \
    -H 'Authorization: Bearer YOUR_JWT_TOKEN' \
    -H 'Content-Type: application/json' \
    -d '{
      "rating": 1,
      "feedback": "Great response!"
    }'
  ```

  ```bash Guest User (Device Headers) theme={null}
  curl -X POST \
    'https://api.handauncle.com/api/v1/user/messages/507f1f77bcf86cd799439011/feedback' \
    -H 'x-device-id: unique-device-id-12345' \
    -H 'x-user-id: 507f1f77bcf86cd799439012' \
    -H 'x-platform: android' \
    -H 'Content-Type: application/json' \
    -d '{
      "rating": -1,
      "feedback": "Not accurate"
    }'
  ```

  ```typescript TypeScript SDK theme={null}
  async function submitFeedback(
    messageId: string, 
    rating: 1 | -1, 
    feedback?: string
  ) {
    const response = await fetch(
      `/api/v1/user/messages/${messageId}/feedback`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${token}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ rating, feedback }),
      }
    );
    
    return await response.json();
  }

  // Like a message
  await submitFeedback('507f1f77bcf86cd799439011', 1);

  // Dislike with feedback
  await submitFeedback('507f1f77bcf86cd799439011', -1, 'Incorrect calculation');
  ```

  ```python Python theme={null}
  import requests

  def submit_message_feedback(
      message_id: str,
      rating: int,  # 1 or -1
      feedback: str = None,
      token: str = None,
      device_id: str = None,
      user_id: str = None,
      platform: str = "web"
  ):
      url = f"https://api.handauncle.com/api/v1/user/messages/{message_id}/feedback"
      
      # Choose authentication method
      if token:
          headers = {"Authorization": f"Bearer {token}"}
      elif device_id:
          headers = {
              "x-device-id": device_id,
              "x-user-id": user_id,
              "x-platform": platform
          }
      else:
          raise ValueError("Provide either token or device_id")
      
      headers["Content-Type"] = "application/json"
      
      payload = {"rating": rating}
      if feedback:
          payload["feedback"] = feedback
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Registered user
  submit_message_feedback("507f1f77bcf86cd799439011", 1, "Helpful!", token="...")

  # Guest user
  submit_message_feedback(
      "507f1f77bcf86cd799439011", 
      -1, 
      "Wrong answer",
      device_id="device-123",
      user_id="user-456"
  )
  ```
</CodeGroup>

## Error Responses

### 400 Bad Request - Invalid Rating

```json theme={null}
{
  "success": false,
  "error": {
    "message": "rating: Rating must be 1 (like) or -1 (dislike)",
    "code": "VALIDATION_ERROR"
  }
}
```

### 401 Unauthorized - Missing Authentication

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Missing authentication. Provide either Authorization header or x-device-id header.",
    "code": "UNAUTHORIZED"
  }
}
```

### 403 Forbidden - Wrong User

```json theme={null}
{
  "success": false,
  "error": {
    "message": "You do not have access to this message",
    "code": "FORBIDDEN"
  }
}
```

### 404 Not Found - Message Doesn't Exist

```json theme={null}
{
  "success": false,
  "error": {
    "message": "Message not found",
    "code": "NOT_FOUND"
  }
}
```

## Validation Rules

* `rating` must be exactly `1` or `-1` (no other values accepted)
* `feedback` is optional but limited to 1000 characters
* `messageId` must be a valid 24-character MongoDB ObjectId
* User must own the conversation containing the message

## Notes

* **Idempotent**: Submitting feedback multiple times overwrites previous feedback
* **Guest support**: Same authentication pattern as chat API for seamless trial experience
* **Privacy**: Only the message owner can submit feedback
* **Analytics**: Feedback data can be used to improve AI model performance
* **No removal**: Once submitted, feedback can only be updated (not deleted)

## Related Endpoints

* [List Messages](./messages) - Get messages to display feedback UI
* [Chat](../ai/chat) - Create messages that can receive feedback
* [Get Conversation](./details) - View conversation metadata


## OpenAPI

````yaml POST /api/v1/user/messages/{messageId}/feedback
openapi: 3.1.0
info:
  title: Handa Uncle API
  version: 1.0.0
  description: Public specification for the Handa Uncle web and mobile APIs.
  contact:
    name: Handa Uncle Engineering
    email: hello@handauncle.com
servers:
  - url: https://handauncle-backend-prod-205012263523.asia-south1.run.app
    description: Prod API base (Cloud Run)
  - url: https://api.handauncle.com
    description: Production
  - url: https://staging-api.handauncle.com
    description: Staging
  - url: http://localhost:8080
    description: Local development
security: []
tags:
  - name: Mobile App
    description: Endpoints used by the native Handa Uncle app.
  - name: Platform
    description: Cross-service operational endpoints.
  - name: Auth
    description: Authentication endpoints handled by the backend adapter.
  - name: AI
    description: LLM chat endpoints supporting streaming and device-auth guests.
  - name: OTP
    description: Phone OTP lifecycle powered by Exotel.
  - name: Webhooks
    description: Server-to-server hooks invoked by Auth0.
  - name: Conversations
    description: Authenticated user conversation management.
  - name: Chat Share
    description: Create, manage, and consume shared conversations.
  - name: Files
    description: Upload, list, and delete user files.
  - name: Prompt management
    description: Admin and public APIs for managing masked pre-prompts.
  - name: User Profile
    description: Profile card collection and user data for personalized AI responses.
  - name: Visual Embeds
    description: Manage visual embed images that attach to AI chat responses.
  - name: Second Opinion
    description: Admin and public APIs for Second Opinion suggestion cards.
  - name: Profile Cards
    description: >-
      APIs for managing profile card questions used in onboarding and
      personalization.
paths:
  /api/v1/user/messages/{messageId}/feedback:
    post:
      tags:
        - Conversations
      summary: Submit message feedback (like/dislike)
      description: >-
        Submit user feedback (thumbs up/down and optional text) for a message.
        Supports both Auth0 JWT and device-based authentication for guest users.
      operationId: submitMessageFeedback
      parameters:
        - name: messageId
          in: path
          required: true
          description: MongoDB ObjectId of the message to rate
          schema:
            type: string
            pattern: ^[a-f0-9]{24}$
            example: 507f1f77bcf86cd799439011
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - rating
              properties:
                rating:
                  type: integer
                  enum:
                    - 1
                    - -1
                  description: 1 for like (👍), -1 for dislike (👎)
                  example: 1
                feedback:
                  type: string
                  maxLength: 1000
                  description: Optional text feedback explaining the rating
                  example: Very helpful and accurate response!
      responses:
        '200':
          description: Feedback submitted successfully.
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                  - meta
                properties:
                  success:
                    type: boolean
                    enum:
                      - true
                  data:
                    type: object
                    required:
                      - messageId
                      - rating
                      - feedback
                      - updatedAt
                    properties:
                      messageId:
                        type: string
                        example: 507f1f77bcf86cd799439011
                      rating:
                        type: integer
                        enum:
                          - 1
                          - -1
                        example: 1
                      feedback:
                        type: string
                        nullable: true
                        example: Very helpful and accurate response!
                      updatedAt:
                        type: string
                        format: date-time
                        example: '2025-12-10T08:35:00.000Z'
                  meta:
                    type: object
                    required:
                      - timestamp
                    properties:
                      timestamp:
                        type: string
                        format: date-time
                      requestId:
                        type: string
        '400':
          $ref: '#/components/responses/ValidationError'
        '401':
          $ref: '#/components/responses/UnauthorizedError'
        '403':
          $ref: '#/components/responses/ForbiddenError'
        '404':
          $ref: '#/components/responses/NotFoundError'
        '500':
          $ref: '#/components/responses/InternalError'
      security:
        - bearerAuth: []
        - deviceAuth: []
components:
  responses:
    ValidationError:
      description: The request payload or headers were invalid.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    UnauthorizedError:
      description: Authentication failed or is missing.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    ForbiddenError:
      description: Caller is not allowed to access this resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NotFoundError:
      description: Requested resource was not found.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Unexpected server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
  schemas:
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
        error:
          $ref: '#/components/schemas/ErrorObject'
        meta:
          $ref: '#/components/schemas/ResponseMeta'
      required:
        - success
        - error
        - meta
    ErrorObject:
      type: object
      properties:
        message:
          type: string
          description: Human-readable error message describing the issue.
          example: Please enter a valid 10-digit phone number (e.g., 9876543210)
        code:
          type: string
          description: Error code for programmatic handling.
          example: VALIDATION_ERROR
        details:
          type: array
          description: >-
            Array of field-specific validation errors (for VALIDATION_ERROR
            responses).
          items:
            type: object
            properties:
              field:
                type: string
                description: Field name that failed validation.
                example: phone
              message:
                type: string
                description: Specific validation error message for this field.
                example: Please enter a valid 10-digit phone number (e.g., 9876543210)
            required:
              - field
              - message
      required:
        - message
    ResponseMeta:
      type: object
      properties:
        timestamp:
          type: string
          format: date-time
        requestId:
          type: string
          description: Server generated correlation identifier.
      required:
        - timestamp
        - requestId
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: Auth0 access token for registered users.
    deviceAuth:
      type: apiKey
      in: header
      name: x-device-id
      description: >-
        Device-based authentication for guest users. Requires x-device-id,
        x-user-id (optional), and x-platform headers.

````