V3 Feedback Records

List feedback records

Changed on

Lists the feedback records of one dataset, newest first, with optional filters and keyset pagination. Served by the API gateway, which authorizes the call against tenant_id and forwards it to the feedback store — see the introduction for how the two layers answer.

Requires an API key with read permission (or higher) on a workspace the dataset is assigned to. The organization must hold the Unify Feedback entitlement.

Multi-value filters are OR-ed within a parameter and AND-ed across parameters. Repeat the parameter to pass several values (?field_type=text&field_type=rating); comma-separated values are not split. Filters on enrichment members (sentiment, emotions, sentiment_score_*) never match records that have not been enriched — use has_sentiment=false / has_emotions=false to find those.

Incremental extraction. To keep a copy of a dataset in sync, filter on updated_since and page with sort=updated_at&order=asc, bounded by updated_until: every page is then one index range, and a record that changes while you page normally comes back later in the run. Start each run with a limit=1 request and read its Date header: that value is this run's updated_until and, minus a few minutes, the next run's updated_since — both bounds from the same value, or records between them are never read. Do not use the newest updated_at received instead: it skips a write that was still committing when you read past its timestamp. Upsert by id and let the most recent fetch win. Deleted records leave nothing for updated_since to match, so reconcile deletions separately: periodically list every record id with no updated_since, and remove the local records that were not returned and were created before that listing's start (its first response's Date header) minus the overlap. Run one sync at a time.

get/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

Query parameters

tenant_idstring cuid2 required

The feedback dataset to operate on (the dataset id, as shown by the MCP list_feedback_datasets tool). Required by the gateway on this operation: a missing or malformed value answers 400 before the request reaches the feedback store, and a dataset the API key's workspace is not assigned to answers 403. The two POST operations take the same value in the request body instead, and the single-record operations derive it from the record.

submission_idstring[]

Records belonging to any of these logical submissions (e.g. response ids).

source_typestring[]

Records from any of these source types, e.g. survey, review.

source_idstring[]

Records from any of these sources (e.g. survey ids).

source_namestring[]

Records whose source display name is any of these. Prefer source_id where records carry one: a name can be edited or translated, the id is stable.

field_idstring[]

Every answer to any of these questions.

field_group_idstring[]

Records in any of these field groups (ranking / matrix questions).

field_typeFeedbackRecordFieldType[]

Records of any of these field types. An empty value is ignored, so ?field_type= equals omitting the filter.

value_idstring[]

Records whose selected option id is any of these (e.g. every pick of one survey choice).

user_idstring[]

Everything any of these end users submitted.

languagestring[]

Records given in any of these languages (ISO codes).

sincestring date-time

collected_at >= since (ISO 8601, inclusive). Must be between 1970-01-01 and 2080-12-31.

untilstring date-time

collected_at <= until (ISO 8601, inclusive).

created_sincestring date-time

created_at >= created_since (ISO 8601, inclusive). created_at is when the record was stored; collected_at (see since) is when the feedback was given. They diverge on a historical re-import, so this is the filter for "what did this import bring in".

created_untilstring date-time

created_at <= created_until (ISO 8601, inclusive).

updated_sincestring date-time

updated_at >= updated_since (ISO 8601, inclusive). updated_at is stamped when a record is created, corrected, or enriched (translation, sentiment, emotions), so this selects records created or changed since a point — the filter for incremental extraction. Deleted records are never returned; see "Incremental extraction" above for choosing the next value and for detecting deletions.

updated_untilstring date-time

updated_at <= updated_until (ISO 8601, inclusive).

value_number_minnumber double

value_number >= value_number_min (inclusive), e.g. NPS promoters with value_number_min=9. Records without a numeric answer are excluded. A max below the min answers 400.

value_number_maxnumber double

value_number <= value_number_max (inclusive). Paired with the min it selects a band: 9..10 promoters, 0..6 detractors.

value_date_minstring date-time

value_date >= value_date_min (inclusive) — bounds the answer to a date question, not when the feedback was collected.

value_date_maxstring date-time

value_date <= value_date_max (inclusive).

sentimentFeedbackRecordSentiment[]

Records carrying any of these sentiment labels. An empty value is ignored.

emotionsFeedbackRecordEmotion[]

Records tagged with any of these emotions: a record tagged {joy} and one tagged {joy, anger} both match ?emotions=joy&emotions=anger. There is no "all of them" form.

sentiment_score_minnumber double

sentiment_score >= sentiment_score_min (inclusive). The score is continuous where the label is bucketed, so this is the filter for "the most negative feedback".

sentiment_score_maxnumber double

sentiment_score <= sentiment_score_max (inclusive).

has_sentimentboolean

true selects enriched records (a sentiment label is present), false the not-yet-enriched ones. Omit for no constraint.

has_emotionsboolean

true selects records carrying emotion labels, false those without. Note false covers both "not yet classified" and "classified, no emotion detected".

has_translationboolean

true selects translated records, false untranslated ones. Omit for no constraint.

sort'collected_at' | 'created_at' | 'updated_at'

Column to order by. collected_at and created_at never change. updated_at does, so it is accepted only with order=asc: a record that changes while you page then normally moves ahead of the cursor and is returned again (upsert it by id). Descending, or with no order (which defaults to desc), it answers 400. Even ascending, a write that started before the cursor's position and commits after it is missed by that run and picked up by the next, whose updated_since is the previous run's start minus an overlap. Use sort=updated_at&order=asc with updated_since and updated_until for incremental extraction.

order'asc' | 'desc'

Sort direction. Rows tied on the sort column are ordered by id ascending.

limitinteger

Page size. Out-of-range and non-numeric values are rejected — -5 and 1001 answer 400 — with one exception: limit=0 is indistinguishable from omitting the parameter, so it is accepted and the default of 100 applies. Send no limit rather than 0 if you are computing it. The search operations behave differently again: they clamp instead of rejecting.

cursorstring

Opaque keyset cursor returned as next_cursor by the previous page. Omit on the first request. A cursor is a position within one specific ordering: presenting it with a different sort or order answers 400 — restart without a cursor instead.

Response

Feedback records retrieved successfully

limitinteger required

The page size that was applied.

next_cursorstring

Opaque keyset cursor for the next page. Present only when there may be more results; absent on the last page. Pass it back unchanged as cursor, with the same sort and order.

Changes

    • info

      added the new optional query request parameter updated_since

    • info

      added the new optional query request parameter updated_until

    • info

      added the new enum value updated_at to the query request parameter sort

    • info

      added the optional property // to the response with the status