Count feedback records
const url = 'http://localhost:8080/v1/feedback-records/count?tenant_id=org-123&submission_id=550e8400-e29b-41d4-a716-446655440000&source_type=survey&source_type=review&source_id=survey-123&field_id=q1&field_group_id=feature_priority&field_type=text&field_type=rating&value_id=opt_very_satisfied&user_id=user-abc-123&source_name=After%20match%20survey&language=en&language=ar&since=2024-01-01T00%3A00%3A00Z&until=2024-12-31T23%3A59%3A59Z&created_since=2026-01-01T00%3A00%3A00Z&created_until=2026-12-31T00%3A00%3A00Z&updated_since=2026-01-01T00%3A00%3A00Z&updated_until=2026-12-31T00%3A00%3A00Z&value_number_min=9&value_number_max=10&value_date_min=2026-01-01T00%3A00%3A00Z&value_date_max=2026-12-31T00%3A00%3A00Z&sentiment=negative&sentiment=very_negative&emotions=anger&emotions=fear&sentiment_score_min=-0.5&sentiment_score_max=0.5&has_sentiment=true&has_emotions=true&has_translation=false';const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request GET \ --url 'http://localhost:8080/v1/feedback-records/count?tenant_id=org-123&submission_id=550e8400-e29b-41d4-a716-446655440000&source_type=survey&source_type=review&source_id=survey-123&field_id=q1&field_group_id=feature_priority&field_type=text&field_type=rating&value_id=opt_very_satisfied&user_id=user-abc-123&source_name=After%20match%20survey&language=en&language=ar&since=2024-01-01T00%3A00%3A00Z&until=2024-12-31T23%3A59%3A59Z&created_since=2026-01-01T00%3A00%3A00Z&created_until=2026-12-31T00%3A00%3A00Z&updated_since=2026-01-01T00%3A00%3A00Z&updated_until=2026-12-31T00%3A00%3A00Z&value_number_min=9&value_number_max=10&value_date_min=2026-01-01T00%3A00%3A00Z&value_date_max=2026-12-31T00%3A00%3A00Z&sentiment=negative&sentiment=very_negative&emotions=anger&emotions=fear&sentiment_score_min=-0.5&sentiment_score_max=0.5&has_sentiment=true&has_emotions=true&has_translation=false' \ --header 'Authorization: Bearer <token>'Returns the total number of feedback records matching the given filters. Supports the same query parameters as the list endpoint.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Query Parameters
Section titled “Query Parameters”Tenant ID (required for isolation). NULL bytes not allowed.
Example
org-123Tenant ID (required for isolation). NULL bytes not allowed.
Example
[ "550e8400-e29b-41d4-a716-446655440000"]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.
Example
[ "survey", "review"]Filter by source type. Repeat the parameter to match any of several source types; the values are OR-ed. NULL bytes not allowed.
Example
[ "survey-123"]Filter by source ID. Repeat the parameter to match any of several sources; the values are OR-ed. NULL bytes not allowed.
Example
[ "q1"]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.
Example
[ "feature_priority"]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.
Example
[ "text", "rating"]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.
Example
[ "opt_very_satisfied"]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.
Example
[ "user-abc-123"]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.
Example
[ "After match survey"]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.
Example
[ "en", "ar"]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.
Filter by collected_at >= since (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.
Example
2024-01-01T00:00:00ZFilter by collected_at >= since (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.
Filter by collected_at <= until (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.
Example
2024-12-31T23:59:59ZFilter by collected_at <= until (ISO 8601 format). Must be between 1970-01-01 and 2080-12-31.
Example
2026-01-01T00:00:00ZFilter 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.
Example
2026-12-31T00:00:00ZFilter 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.
Example
2026-01-01T00:00:00ZFilter by updated_at >= updated_since (ISO 8601, inclusive). updated_at is stamped on every write to a record — create, update, and every enrichment result (translation, sentiment, emotions) — so this selects records created OR changed since a point: the parameter for incremental extraction. Pair it with sort=updated_at&order=asc. For the next run, use the time the previous run started (its first response’s Date header) minus an overlap, not the largest updated_at received. The overlap must outlast the longest write to a record; Hub does not bound that, so a few minutes is a default rather than a guarantee. Permanently deleted records are never returned: periodically list every record, upsert what it returns (which also repairs any change a slow write slipped past the overlap), and remove only local records that were not returned and were created before that listing started (its first response’s Date header) minus the overlap. See “Incremental extraction” in the filtering and sorting guide.
Example
2026-12-31T00:00:00ZFilter by updated_at <= updated_until (ISO 8601, inclusive). See updated_since for what updates updated_at.
Example
9Filter 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.
Example
10Filter 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.
Example
2026-01-01T00:00:00ZFilter 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.
Example
2026-12-31T00:00:00ZFilter by value_date <= value_date_max (ISO 8601, inclusive). Records whose value_date is NULL are excluded.
Example
[ "negative", "very_negative"]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.
Example
[ "anger", "fear"]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.
Example
-0.5Filter 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.
Example
0.5Filter by sentiment_score <= sentiment_score_max (inclusive). Records that have not been enriched are excluded.
Example
trueFilter 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.
Example
trueFilter 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.
Example
falseFilter 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.
Responses
Section titled “Responses”OK
object
Number of feedback records matching the filters
Example
{ "count": 42}Bad Request. Returned for an unknown enum value (sentiment, emotions, field_type), an inverted range whose _min/_since exceeds its _max/_until, or a missing or blank tenant_id.
RFC 9457 problem details (application/problem+json). Branch on the stable code member rather than on title or type.
object
Stable, machine-readable error code; the primary value to branch on. service_unavailable indicates a feature or dependency is temporarily unavailable and the request may be retried later. tenant_write_conflict indicates the write conflicted with an in-progress tenant data purge (or vice versa) and may be retried later unchanged. All other codes are terminal until the request itself is changed.
A human-readable explanation specific to this occurrence of the problem.
Optional structured context for this problem, e.g. resource_type on a 404.
object
A URI reference (typically the request path) identifying the specific occurrence of the problem.
Field-level validation failures (RFC 9457 “invalid_params” extension). Present on validation errors.
A single invalid request parameter (RFC 9457 “invalid_params” extension member).
object
Dotted path to the offending request field, e.g. ‘field_type’ or ‘items[0].field_type’.
Human- and agent-readable explanation of why the value is invalid, naming allowed values or constraints where applicable so the request can be corrected without guessing.
Identifier for this request, also returned in the X-Request-ID response header; include it when reporting a problem.
HTTP status code
A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
A URI reference identifying the problem type.
Examples
A range filter supplied backwards
{ "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" } ]}Unauthorized (missing or invalid API key)
RFC 9457 problem details (application/problem+json). Branch on the stable code member rather than on title or type.
object
Stable, machine-readable error code; the primary value to branch on. service_unavailable indicates a feature or dependency is temporarily unavailable and the request may be retried later. tenant_write_conflict indicates the write conflicted with an in-progress tenant data purge (or vice versa) and may be retried later unchanged. All other codes are terminal until the request itself is changed.
A human-readable explanation specific to this occurrence of the problem.
Optional structured context for this problem, e.g. resource_type on a 404.
object
A URI reference (typically the request path) identifying the specific occurrence of the problem.
Field-level validation failures (RFC 9457 “invalid_params” extension). Present on validation errors.
A single invalid request parameter (RFC 9457 “invalid_params” extension member).
object
Dotted path to the offending request field, e.g. ‘field_type’ or ‘items[0].field_type’.
Human- and agent-readable explanation of why the value is invalid, naming allowed values or constraints where applicable so the request can be corrected without guessing.
Identifier for this request, also returned in the X-Request-ID response header; include it when reporting a problem.
HTTP status code
A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
A URI reference identifying the problem type.
Example
{ "code": "validation", "detail": "One or more request parameters are invalid", "instance": "/v1/feedback-records", "invalid_params": [ { "name": "field_type", "reason": "must be one of: text, categorical, nps, csat, ces, rating, number, boolean, date" } ], "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b", "status": 400, "title": "Bad Request", "type": "https://hub.formbricks.com/problems/bad-request"}default
Section titled “default”Error
RFC 9457 problem details (application/problem+json). Branch on the stable code member rather than on title or type.
object
Stable, machine-readable error code; the primary value to branch on. service_unavailable indicates a feature or dependency is temporarily unavailable and the request may be retried later. tenant_write_conflict indicates the write conflicted with an in-progress tenant data purge (or vice versa) and may be retried later unchanged. All other codes are terminal until the request itself is changed.
A human-readable explanation specific to this occurrence of the problem.
Optional structured context for this problem, e.g. resource_type on a 404.
object
A URI reference (typically the request path) identifying the specific occurrence of the problem.
Field-level validation failures (RFC 9457 “invalid_params” extension). Present on validation errors.
A single invalid request parameter (RFC 9457 “invalid_params” extension member).
object
Dotted path to the offending request field, e.g. ‘field_type’ or ‘items[0].field_type’.
Human- and agent-readable explanation of why the value is invalid, naming allowed values or constraints where applicable so the request can be corrected without guessing.
Identifier for this request, also returned in the X-Request-ID response header; include it when reporting a problem.
HTTP status code
A short, human-readable summary of the problem type. This value should not change between occurrences of the error.
A URI reference identifying the problem type.
Example
{ "code": "validation", "detail": "One or more request parameters are invalid", "instance": "/v1/feedback-records", "invalid_params": [ { "name": "field_type", "reason": "must be one of: text, categorical, nps, csat, ces, rating, number, boolean, date" } ], "request_id": "0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b", "status": 400, "title": "Bad Request", "type": "https://hub.formbricks.com/problems/bad-request"}