Create a new feedback record
const url = 'http://localhost:8080/v1/feedback-records';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"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","language":"en"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url http://localhost:8080/v1/feedback-records \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "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", "language": "en" }'Creates a new feedback record data point
Authorizations
Section titled “Authorizations”Request Bodyrequired
Section titled “Request Bodyrequired”object
When the feedback was collected (defaults to now). Must be between 1970-01-01 and 2080-12-31.
Identifier for the question/field. NULL bytes not allowed.
The actual question text
Stable identifier grouping related fields (for ranking, matrix, grid questions). NULL bytes not allowed.
Human-readable question text for the group
Field type: text (enrichable), categorical, nps, csat, ces, rating, number, boolean, date
ISO language code. NULL bytes not allowed.
Arbitrary context for this record, stored as JSON and returned with equivalent values (key order and number formatting are normalized): the dimensions you want to slice a dashboard by, such as channel, device, browser, OS, country, referrer, campaign, plan or tags. Values may be strings, numbers, booleans, null, or nested objects and arrays.
Use snake_case keys and keep them stable across records, since a key is what a dashboard groups by: customer_tier, not a mix of customerTier and tier. Numbers keep full precision in storage (unlike value_number, which is a float64), so a large integer id round-trips exactly through this API — though a JavaScript client will still lose precision above 2^53 when it parses the response.
Nothing here is redacted. Metadata is not sent to the LLM or embedding enrichment providers, unlike value_text — but it is included in the feedback_record.created and feedback_record.updated webhook payloads, so it reaches whatever URL a tenant has configured. Erasure covers metadata, with one precondition worth knowing: DELETE /v1/feedback-records matches on user_id and hard-deletes the whole row, metadata included — so a record written without a user_id cannot be reached that way. Set user_id on anything you may later have to erase.
Three kinds of content are rejected with 400, because none of them can be stored: invalid UTF-8; NULL bytes or unpaired UTF-16 surrogates, in keys or values; and numbers outside the storable numeric range.
Reference to survey/form/ticket ID
Human-readable name
Type of feedback source (e.g., survey, review, feedback_form). NULL bytes not allowed.
Identifier for the logical submission this record belongs to (tenant-scoped). Required. Enables grouping multi-field submissions and idempotent ingestion. Unique per (tenant_id, submission_id, field_id). If a record has no logical submission, use e.g. field_id.
Tenant/organization identifier for multi-tenancy. Required. U+FFFD is not allowed (it stands in for invalid UTF-8 or an unpaired surrogate).
User ID (e.g., anonymous ID or email hash)
For yes/no questions
For date responses. Must be between 1970-01-01 and 2080-12-31.
For ratings, NPS scores, numeric responses. Must be between -1e15 and +1e15.
For open-ended text responses. Omit or null if not applicable. NULL bytes not allowed when present.
Stable id of the selected option in the source system (e.g. a survey choice id or matrix column id), stored alongside value_text so selected-choice answers keep a durable identity across label edits and languages. Opaque to Hub (not validated). Null for free-text/“other” answers, non-choice fields, and sources without option ids. NULL bytes not allowed when present.
Examples
Rating feedback
{ "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", "language": "en"}Text feedback
{ "source_type": "survey", "field_id": "q2", "field_type": "text", "field_label": "What can we improve?", "value_text": "Great service! Keep it up.", "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", "language": "en"}NPS score
{ "source_type": "survey", "field_id": "nps", "field_type": "nps", "field_label": "How likely are you to recommend us?", "value_number": 8, "source_id": "survey-123", "source_name": "NPS Survey", "user_id": "user-abc-123", "tenant_id": "org-123", "submission_id": "550e8400-e29b-41d4-a716-446655440000", "language": "en"}Boolean feedback
{ "source_type": "survey", "field_id": "q3", "field_type": "boolean", "field_label": "Would you use our service again?", "value_boolean": true, "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", "language": "en"}Ranking question item
{ "source_type": "survey", "field_id": "feature_priority__reports", "field_type": "number", "field_label": "Reports", "field_group_id": "feature_priority", "field_group_label": "Rank these features by importance", "value_number": 1, "source_id": "survey-123", "source_name": "Feature Priority Survey", "user_id": "user-abc-123", "tenant_id": "org-123", "submission_id": "550e8400-e29b-41d4-a716-446655440000", "metadata": { "question_type": "ranking", "total_items": 3 }}Matrix rating item
{ "source_type": "survey", "field_id": "feature_satisfaction__ease_of_use", "field_type": "rating", "field_label": "Ease of Use", "field_group_id": "feature_satisfaction", "field_group_label": "Rate your satisfaction with each feature", "value_number": 4, "source_id": "survey-123", "source_name": "Feature Satisfaction Survey", "user_id": "user-abc-123", "tenant_id": "org-123", "submission_id": "550e8400-e29b-41d4-a716-446655440000", "metadata": { "question_type": "matrix" }}Responses
Section titled “Responses”Created
object
When the feedback was collected
When this record was created
Identifier for the question/field
The actual question text
Stable identifier grouping related fields (for ranking, matrix, grid questions)
Human-readable question text for the group
Type of field
UUIDv7 primary key
ISO language code. NULL bytes not allowed.
Arbitrary context stored with this record, returned with equivalent values (key order is normalized, and so are number exponents — 1e2 reads back as 100). Omitted when the record has no metadata; a record explicitly stored with a JSON null returns null.
An object is the supported shape and the only one the request schemas accept. The wider union is for reading: the column stores whatever JSON was written, so a record created before that convention can return an array or a scalar, and an object-only response schema would make a generated client reject it.
Sentiment polarity inferred from value_text (sentiment enrichment). Read-only; absent until the record is enriched.
Signed sentiment polarity from -1.0 (very negative) to 1.0 (very positive) (sentiment enrichment). Read-only; absent until the record is enriched.
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.
Reference to survey/form/ticket ID
Human-readable name
Type of feedback source
Identifier for the logical submission this record belongs to (required).
Tenant/organization identifier. NULL bytes not allowed.
BCP-47 target locale that value_text_translated was produced in (language enrichment). Read-only; absent until the record is enriched.
When this record was last updated
User ID (e.g., anonymous ID or email hash)
Boolean response
Date response
Numeric response
Text response. NULL bytes not allowed.
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_text translated into the tenant’s configured target language (language enrichment). Read-only; absent until the record is enriched.
Examples
Created feedback record
{ "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", "language": "en"}Bad Request (e.g. validation 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.
Examples
Invalid field_type enum
{ "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": "field_type", "reason": "has invalid value \"textt\"; must be one of: text, categorical, nps, csat, ces, rating, number, boolean, date" } ]}Conflict. Either a duplicate tenant_id/submission_id/field_id (code conflict, terminal),
or a tenant data purge is in progress for this tenant (code tenant_write_conflict,
retryable – retry after the purge completes).
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"}Request body exceeds the maximum allowed size.
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"}