---
title: "Create a feedback widget"
method: POST
path: "/feedback-widgets"
tags: ["Feedback Widgets"]
---

# Create a feedback widget

`POST /feedback-widgets`

## Request

- Base URL: `https://api.produktly.com/api/v1`
- URL: `https://api.produktly.com/api/v1/feedback-widgets`
- Auth: HTTP bearer

Creates the widget as a draft. Pass active: true to publish immediately — the widget must have at least one option and targeting set, otherwise it stays a draft and the response note explains why. Supply options directly or use optionsPreset for a built-in set. The response includes a dashboardUrl for reviewing the widget in the builder.

## Request body

- object
  - `name` string, required
  - `options` object[]: The answer options users pick from
    - `name` string, required: Shown under the emoji and submitted as optionName
    - `emoji` string
    - `type` string: Submitted as the response type. Defaults to a slug of name
  - `optionsPreset` integer: Use a built-in option set instead of listing options: 1 issue/idea/other, 2 three emojis, 3 five emojis, 4 four emojis, 5 feelings, 6 issue/idea/happy/angry/other
  - `settings` object
    - `question` string: Default "We would love to hear your feedback"
    - `showBeacon` boolean: Default true. When false, open with Produktly.openFeedback()
    - `collapsedText` string: Beacon label. Default "Feedback"
    - `beaconLocation` 'mid-right' | 'mid-left' | 'bottom-right' | 'bottom-left' | 'right-bottom' | 'left-bottom' | 'top-right' | 'top-left' | 'right-top' | 'left-top': Default "mid-right"
    - `collectEmail` boolean: Default false
    - `emailOptional` boolean
    - `shouldValidateEmail` boolean: Default true
    - `allowScreenshots` boolean
    - `autoCaptureScreenshot` boolean
    - `requireScreenshot` boolean: Only enforced when allowScreenshots is on and autoCaptureScreenshot is off
    - `themeColor` string
    - `textColor` string
    - `emailLabelText` string
    - `emailOptionalLabelText` string
    - `messageLabelText` string
    - `submitBtnText` string
    - `submitAnotherBtnText` string
    - `feedbackSuccessText` string
    - `feedbackErrorText` string
    - `emailMissingErrorText` string
    - `emailInvalidErrorText` string
    - `messageMissingErrorText` string
    - `screenshotLabelText` string
    - `screenshotMissingErrorText` string
    - `slackWebhookUrl` string: Write-only. Never returned by read endpoints
    - `discordWebhookUrl` string: Write-only
    - `zapierWebhookUrl` string: Write-only
    - `customWebhookUrl` string: Write-only
    - `notificationEmails` string: Comma-separated. Write-only
  - `targeting` union
    - object
      - `showOnAllPages` true, required
    - object
      - `rules` object[], required
        - `type` union, required
          - 'url' | 'current_time' | 'time_of_day' | 'day_of_week' | 'location' | 'language' | 'produktly_user_created_at' | 'device_type' | 'screen_width' | 'screen_height' | 'produktly_user_visit_count' | 'produktly_user_days_active'
          - string
          - string
        - `comparisonOperator` 'equals' | 'not_equal' | 'contains' | 'no_contains' | 'starts_with' | 'ends_with' | 'one_of' | 'not_one_of' | 'greater' | 'greater_eq' | 'less' | 'less_eq' | 'exists' | 'not_exists' | 'time_ago' | 'within_last' | 'between', required
        - `value` union
          - string
          - number
          - union[]
            - union
              - …
          - object
            - `value` integer, required
            - `unit` 'minutes' | 'hours' | 'days' | 'weeks' | 'months' | 'years', required
      - `logicalOperator` 'AND' | 'OR' | 'and' | 'or': How multiple rules combine. Default "AND".
    - object
      - `userSegmentIds` integer[], required
  - `themeId` integer
  - `folderId` integer
  - `active` boolean: Publish immediately. Needs at least one option and targeting

## Response `201`

Created feedback widget

- FeedbackWidgetDetail
  - `id` integer, required
  - `name` string, required
  - `active` boolean, required
  - `createdAt` string, date-time, required
  - `updatedAt` string, date-time, required
  - `folderId` integer, nullable, required
  - `themeId` integer, nullable, required
  - `settings` object, required
  - `rules` object[], required
  - `ruleLogicalOperator` string, nullable, required
  - `options` object[], required
  - `dashboardUrl` string, required
  - `note` string

## Other responses

- `400`: Validation error
- `401`: Unauthorized
- `403`: Plan limit reached
- `429`: Rate limit exceeded

---

[API](https://skmtc.dev/produktly/apis/produktly-api.md) · [All operations](https://skmtc.dev/produktly/apis/produktly-api/llms.txt) · [OpenAPI document](https://skmtc.dev/produktly/apis/produktly-api/revisions/fd942a97a7d1?raw)
