V3 Feedback Records

Create a feedback record

Changed on

Stores one feedback record in the dataset named by tenant_id in the body. The gateway reads tenant_id from the JSON body to authorize the call — a body that is not JSON, or has no tenant_id, answers 400 before anything is stored.

Requires an API key with write permission (or higher) on a workspace the dataset is assigned to. Creating is allowed on shared datasets (it is ordinary workspace work, like a CSV import); only changing and deleting existing records is restricted to unshared ones.

Ingestion is idempotent per (tenant_id, submission_id, field_id): a second record with the same triple answers 409 rather than creating a duplicate. Send exactly one value_* member, matching field_type. A text record is enriched asynchronously — sentiment, emotions and the translation members appear on the record once enrichment completes, and it becomes searchable once embedded.

post/api/v3/feedbackRecords

Request

  • Base URL
    https://app.formbricks.com
  • URL
    https://app.formbricks.com/api/v3/feedbackRecords
  • Auth
    API key in header x-api-key

Request body

tenant_idstring cuid2 required

The feedback dataset to write into (the dataset id). The gateway authorizes the request against this dataset, so it must be one the API key's workspace is assigned to.

source_typestring required

Type of feedback source, e.g. survey, review, feedback_form.

source_idstring nullable

Reference to the survey / form / ticket the record came from.

source_namestring nullable

Human-readable name of the source.

submission_idstring required

Identifier of the logical submission this record belongs to. Groups multi-field submissions and makes ingestion idempotent: records are unique per (tenant_id, submission_id, field_id) and a duplicate answers 409. If a record has no logical submission, reuse field_id.

field_idstring required

Identifier of the question / field.

field_labelstring nullable

The question text.

field_group_idstring

Stable identifier grouping related fields (ranking, matrix and grid questions).

field_group_labelstring nullable

Human-readable question text for the group.

field_type'text' | 'categorical' | 'nps' | 'csat' | 'ces' | 'rating' | 'number' | 'boolean' | 'date' required

The type of a feedback field, which determines which value_* member carries the answer: text → value_text (the only enrichable type), categorical → value_text + value_id, nps / csat / ces / rating / number → value_number, boolean → value_boolean, date → value_date.

languagestring

ISO language code the feedback was given in.

user_idstring

End-user identifier (e.g. an anonymous id or an email hash). Set it on anything you may later have to erase: DELETE /api/v3/feedbackRecords matches on user_id.

collected_atstring date-time

When the feedback was given. Defaults to now. Must be between 1970-01-01 and 2080-12-31.

value_textstring nullable

Text answer. The only member that feeds sentiment, emotion, translation and embedding enrichment.

value_idstring nullable

Stable id of the selected option in the source system (e.g. a survey choice id or matrix column id), stored alongside value_text. Opaque, not validated. Omit for free-text, "other" and non-choice answers.

value_numbernumber double

Numeric answer (ratings, NPS scores, numbers). Must be between -1e15 and +1e15.

value_booleanboolean

Yes / no answer.

value_datestring date-time

Date answer. Must be between 1970-01-01 and 2080-12-31.

metadataobject nullable

Arbitrary context for this record, stored as JSON: the dimensions you want to slice a dashboard by, such as channel, device, country, campaign, plan or tags. Values may be strings, numbers, booleans, null, or nested objects and arrays. Use stable snake_case keys — a key is what a dashboard groups by. Numbers keep full precision in storage. Metadata is not sent to the enrichment providers, but it is included in the feedback_record.created / feedback_record.updated webhook payloads.

Response

Feedback record created

idstring uuid required

UUIDv7 primary key.

tenant_idstring cuid2 required

The feedback dataset this record belongs to (the dataset id, as shown by the MCP list_feedback_datasets tool).

collected_atstring date-time required

When the feedback was given.

created_atstring date-time required

When the record was stored. Diverges from collected_at on a historical re-import.

updated_atstring date-time required

When the record was last changed.

source_typestring required

Type of feedback source, e.g. survey, review, feedback_form.

source_idstring

Reference to the survey / form / ticket the record came from.

source_namestring

Human-readable name of the source.

submission_idstring required

Identifier of the logical submission this record belongs to (e.g. a response id). Records are unique per (tenant_id, submission_id, field_id).

field_idstring required

Identifier of the question / field.

field_labelstring

The question text.

field_group_idstring

Stable identifier grouping related fields (ranking, matrix and grid questions).

field_group_labelstring

Human-readable question text for the group.

field_type'text' | 'categorical' | 'nps' | 'csat' | 'ces' | 'rating' | 'number' | 'boolean' | 'date' required

The type of a feedback field, which determines which value_* member carries the answer: text → value_text (the only enrichable type), categorical → value_text + value_id, nps / csat / ces / rating / number → value_number, boolean → value_boolean, date → value_date.

languagestring

ISO language code the feedback was given in.

user_idstring

End-user identifier (e.g. an anonymous id or an email hash).

value_textstring

Text answer.

value_idstring

Stable id of the selected option in the source system (e.g. a survey choice id), stored alongside value_text so choice answers keep their identity across label edits and languages. Opaque. Absent for free-text and non-choice answers.

value_numbernumber double

Numeric answer (ratings, NPS scores, numbers).

value_booleanboolean

Yes / no answer.

value_datestring date-time

Date answer.

sentiment'very_negative' | 'negative' | 'neutral' | 'positive' | 'very_positive' | 'mixed'

Sentiment polarity label inferred from value_text by the sentiment enrichment: five ordinal levels plus a distinct mixed. Server-generated and read-only.

sentiment_scorenumber double

Signed sentiment polarity from -1.0 (very negative) to 1.0 (very positive). Read-only; absent until the record is enriched.

emotionsFeedbackRecordEmotion[]

Emotions inferred from value_text; multi-label from a fixed set. Read-only, and never an empty array — the column is either absent or has at least one label. Absent covers two different states: not yet classified, and classified with no emotion detected. Do not read absence as "not enriched yet"; has_emotions=false selects both, and the enrichment-status endpoint is what distinguishes them.

value_text_translatedstring

value_text translated into the dataset's configured target language. Read-only; absent until the record is enriched.

translation_lang_keystring

BCP-47 locale that value_text_translated was produced in. Read-only; absent until the record is enriched.

Changes