Skip to content
Support

List feedback records with filters

GET/v1/feedback-records

Lists feedback records for a required tenant_id with optional additional filters and pagination

Query ParametersExpand Collapse
tenant_id: string

Tenant ID (required for isolation). NULL bytes not allowed.

minLength1
maxLength255
created_since: optional string

Filter by created_at >= created_since (ISO 8601, inclusive). created_at is when Hub stored the record; collected_at (see since) is when the feedback was given. They diverge on a historical re-import, so this is the parameter for "what did this import bring in". Must be between 1970-01-01 and 2080-12-31.

formatdate-time
created_until: optional string

Filter by created_at <= created_until (ISO 8601, inclusive). See created_since for how created_at differs from collected_at. Must be between 1970-01-01 and 2080-12-31.

formatdate-time
cursor: optional string

Omit for the first page. For the next page, use the exact value from the previous response's next_cursor. Opaque (base64-encoded); keyset pagination.

A cursor is a position within one specific ordering. Presenting it with a different sort or order returns 400 — restart pagination without a cursor instead. A cursor issued before sort control existed records no ordering; it is treated as a position in the default collected_at/desc listing and is accepted only there.

emotions: optional array of "joy" or "anger" or "sadness" or 3 more

Filter by emotion label. Repeat the parameter to match ANY of the listed emotions: a record tagged {joy} and a record tagged {joy, anger} both match ?emotions=joy&emotions=anger. There is no "must carry all of them" form. An empty value is ignored rather than rejected, so ?emotions= is the same as omitting the filter.

Accepts one of the following:
"joy"
"anger"
"sadness"
"fear"
"surprise"
"disgust"
field_group_id: optional array of string

Filter by field group ID (for ranking/matrix questions). Repeat the parameter to match any of several groups; the values are OR-ed. NULL bytes not allowed.

field_id: optional array of string

Filter by field ID — every answer to one question. Repeat the parameter to match any of several fields; the values are OR-ed. NULL bytes not allowed.

field_type: optional array of "text" or "categorical" or "nps" or 6 more

Filter by field type. Repeat the parameter to match any of several types; the values are OR-ed. An empty value is ignored rather than rejected, so ?field_type= is the same as omitting the filter.

Accepts one of the following:
"text"
"categorical"
"nps"
"csat"
"ces"
"rating"
"number"
"boolean"
"date"
has_emotions: optional boolean

Filter on whether the record carries emotion labels: true selects records where emotions IS NOT NULL, false selects those where it IS NULL. Note that false covers both "not yet classified" and "classified, no emotion detected" — the two are indistinguishable here. Omit for no constraint.

has_sentiment: optional boolean

Filter on whether sentiment enrichment has produced a label: true selects records where sentiment IS NOT NULL, false selects those where it IS NULL. Omit for no constraint.

has_translation: optional boolean

Filter on whether the record has been translated: true selects records where translation_lang_key IS NOT NULL, false selects those where it IS NULL. Omit for no constraint.

language: optional array of string

Filter by the language the feedback was given in. Repeat the parameter to match any of several languages; the values are OR-ed. NULL bytes not allowed.

limit: optional number

Number of results to return (max 1000)

formatint64
minimum1
maximum1000
order: optional "asc" or "desc"

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

Accepts one of the following:
"asc"
"desc"
sentiment: optional array of "very_negative" or "negative" or "neutral" or 3 more

Filter by sentiment label. Repeat the parameter to match any of several labels (?sentiment=negative&sentiment=very_negative); the values are OR-ed. An empty value is ignored rather than rejected, so ?sentiment= is the same as omitting the filter. Records that have not been enriched carry no sentiment and are therefore never matched — use has_sentiment=false to find them.

Accepts one of the following:
"very_negative"
"negative"
"neutral"
"positive"
"very_positive"
"mixed"
sentiment_score_max: optional number

Filter by sentiment_score <= sentiment_score_max (inclusive). Records that have not been enriched are excluded.

formatdouble
minimum-1
maximum1
sentiment_score_min: optional number

Filter by sentiment_score >= sentiment_score_min (inclusive). The score is continuous where the label is bucketed, so this is the parameter for "the most negative feedback". Records that have not been enriched are excluded.

formatdouble
minimum-1
maximum1
since: optional string

Filter by collected_at >= since (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.

formatdate-time
sort: optional "collected_at" or "created_at"

Column to order by. Defaults to collected_at. Only columns that are non-null and immutable after insert are offered: a mutable sort key would let a row move across the cursor between pages and be silently skipped.

Accepts one of the following:
"collected_at"
"created_at"
source_id: optional array of string

Filter by source ID. Repeat the parameter to match any of several sources; the values are OR-ed. NULL bytes not allowed.

source_name: optional array of string

Filter by source display name — the human-readable label stored alongside source_id. Prefer source_id where the records carry one: a name can be edited or translated, while the id is stable. Repeat the parameter to match any of several names; the values are OR-ed. NULL bytes not allowed.

source_type: optional array of string

Filter by source type. Repeat the parameter to match any of several source types; the values are OR-ed. NULL bytes not allowed.

submission_id: optional array of string

Filter by submission ID to group records belonging to one logical submission. Repeat the parameter to match any of several submissions; the values are OR-ed, and a single occurrence behaves exactly as it always has. Comma-separated values are NOT split. NULL bytes not allowed.

until: optional string

Filter by collected_at <= until (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.

formatdate-time
user_id: optional array of string

Filter by end-user identifier — everything one person submitted. Repeat the parameter to match any of several users; the values are OR-ed. NULL bytes not allowed.

value_date_max: optional string

Filter by value_date <= value_date_max (ISO 8601, inclusive). Records whose value_date is NULL are excluded.

formatdate-time
value_date_min: optional string

Filter by value_date >= value_date_min (ISO 8601, inclusive) — bounds the answer to a date question, not when the feedback was collected. Records whose value_date is NULL are excluded.

formatdate-time
value_id: optional array of string

Filter by the source system's stable option id (e.g. all records for one survey choice). Repeat the parameter to match any of several options; the values are OR-ed. NULL bytes not allowed.

value_number_max: optional number

Filter by value_number <= value_number_max (inclusive). Paired with value_number_min it selects a band: 9..10 is the NPS promoters, 0..6 the detractors. Records whose value_number is NULL are excluded. Supplying a max below the min is a 400, not an empty result.

formatdouble
value_number_min: optional number

Filter by value_number >= value_number_min (inclusive) — e.g. NPS promoters with value_number_min=9. Records whose value_number is NULL (every non-numeric answer) are excluded, so this is never a no-op filter.

formatdouble
ReturnsExpand Collapse
data: array of FeedbackRecordData { id, collected_at, created_at, 24 more }

List of feedback records

id: string

UUIDv7 primary key

formatuuid
collected_at: string

When the feedback was collected

formatdate-time
created_at: string

When this record was created

formatdate-time
field_id: string

Identifier for the question/field

field_type: "text" or "categorical" or "nps" or 6 more

Type of field

Accepts one of the following:
"text"
"categorical"
"nps"
"csat"
"ces"
"rating"
"number"
"boolean"
"date"
source_type: string

Type of feedback source

submission_id: string

Identifier for the logical submission this record belongs to (required).

tenant_id: string

Tenant/organization identifier. NULL bytes not allowed.

updated_at: string

When this record was last updated

formatdate-time
emotions: optional array of "joy" or "anger" or "sadness" or 3 more

Emotions inferred from value_text (emotion enrichment); multi-label from a fixed set. Read-only; absent until the record is enriched, and never an empty array.

Accepts one of the following:
"joy"
"anger"
"sadness"
"fear"
"surprise"
"disgust"
field_group_id: optional string

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

field_group_label: optional string

Human-readable question text for the group

field_label: optional string

The actual question text

language: optional string

ISO language code. NULL bytes not allowed.

metadata: optional map[unknown]

Additional context

sentiment: optional "very_negative" or "negative" or "neutral" or 3 more

Sentiment polarity inferred from value_text (sentiment enrichment). Read-only; absent until the record is enriched.

Accepts one of the following:
"very_negative"
"negative"
"neutral"
"positive"
"very_positive"
"mixed"
sentiment_score: optional number

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

formatdouble
minimum-1
maximum1
source_id: optional string

Reference to survey/form/ticket ID

source_name: optional string

Human-readable name

translation_lang_key: optional string

BCP-47 target locale that value_text_translated was produced in (language enrichment). Read-only; absent until the record is enriched.

maxLength35
user_id: optional string

User ID (e.g., anonymous ID or email hash)

value_boolean: optional boolean

Boolean response

value_date: optional string

Date response

formatdate-time
value_id: optional string

Stable id of the selected option in the source system (e.g. a survey choice id), stored alongside value_text for durable option identity. Opaque to Hub. Absent for free-text/non-choice answers. NULL bytes not allowed.

value_number: optional number

Numeric response

formatdouble
value_text: optional string

Text response. NULL bytes not allowed.

value_text_translated: optional string

value_text translated into the tenant's configured target language (language enrichment). Read-only; absent until the record is enriched.

limit: number

Limit used in query

formatint64
next_cursor: optional string

Opaque cursor for the next page (keyset paging). Present only when there may be more results. Use as the cursor query param for the next page.

List feedback records with filters

curl http://localhost:8080/v1/feedback-records \
    -H "Authorization: Bearer $HUB_API_KEY"
{
  "data": [
    {
      "id": "018e1234-5678-9abc-def0-123456789abc",
      "collected_at": "2024-01-15T10:30:00Z",
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z",
      "source_type": "survey",
      "field_id": "q1",
      "field_type": "rating",
      "field_label": "How satisfied are you?",
      "value_number": 9,
      "source_id": "survey-123",
      "source_name": "Q1 NPS Survey",
      "user_id": "user-abc-123",
      "tenant_id": "org-123",
      "submission_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  ],
  "limit": 100
}
{
  "type": "https://hub.formbricks.com/problems/validation",
  "title": "Validation Failed",
  "status": 400,
  "code": "validation",
  "detail": "One or more request parameters are invalid",
  "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
  "invalid_params": [
    {
      "name": "sentiment_score_min",
      "reason": "must be less than or equal to sentiment_score_max"
    }
  ]
}
{
  "type": "https://hub.formbricks.com/problems/validation",
  "title": "Validation Error",
  "status": 400,
  "code": "validation",
  "detail": "One or more request parameters are invalid",
  "instance": "/v1/feedback-records",
  "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
  "invalid_params": [
    {
      "name": "tenant_id",
      "reason": "is required"
    }
  ]
}
Returns Examples
{
  "data": [
    {
      "id": "018e1234-5678-9abc-def0-123456789abc",
      "collected_at": "2024-01-15T10:30:00Z",
      "created_at": "2024-01-15T10:30:00Z",
      "updated_at": "2024-01-15T10:30:00Z",
      "source_type": "survey",
      "field_id": "q1",
      "field_type": "rating",
      "field_label": "How satisfied are you?",
      "value_number": 9,
      "source_id": "survey-123",
      "source_name": "Q1 NPS Survey",
      "user_id": "user-abc-123",
      "tenant_id": "org-123",
      "submission_id": "550e8400-e29b-41d4-a716-446655440000"
    }
  ],
  "limit": 100
}
{
  "type": "https://hub.formbricks.com/problems/validation",
  "title": "Validation Failed",
  "status": 400,
  "code": "validation",
  "detail": "One or more request parameters are invalid",
  "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
  "invalid_params": [
    {
      "name": "sentiment_score_min",
      "reason": "must be less than or equal to sentiment_score_max"
    }
  ]
}
{
  "type": "https://hub.formbricks.com/problems/validation",
  "title": "Validation Error",
  "status": 400,
  "code": "validation",
  "detail": "One or more request parameters are invalid",
  "instance": "/v1/feedback-records",
  "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b",
  "invalid_params": [
    {
      "name": "tenant_id",
      "reason": "is required"
    }
  ]
}