V3 Responses

Create a response

Changed on

Records a survey response. Requires read-write access to the workspace, which is resolved from surveyId rather than supplied by the caller.

This performs a real submission. It runs the full response pipeline — webhooks, integrations, follow-ups, quota evaluation, and Hub ingestion once the response is finished — and it consumes one metered monthly response. That is the same power a v1/v2 management create has today, and the same power an API key with write access already carries; it is called out because an agent holding that key can create genuine submissions. Use POST /api/v3/responses/validate to check a payload without any of that happening.

createdAt cannot be supplied. Bulk historical loading is therefore not what this endpoint is for — see ResponseListItem.createdAt for why, and use v2 while a dedicated import path is outstanding.

post/api/v3/responses

Request

  • Base URL
    https://app.formbricks.com
  • URL
    https://app.formbricks.com/api/v3/responses
  • Auth
    • API key in cookie next-auth.session-token
    • or API key in header x-api-key
    • or HTTP bearer

Request body

surveyIdstring cuid2 required

The survey to record the response against. Immutable after creation.

finishedboolean required

Whether this response is complete. Creating with finished: true fires the finish side of the pipeline immediately, including Hub ingestion.

dataResponseDataMapInput required

The same map on the way in, with the cardinality bounds a v3 write enforces.

At most 500 keys, and at most 1000 entries in a multi-select array or matrix object. Both sit far above any real survey — a response holds one entry per element, a multi-select answer one per choice — and exist because every later reader pays per entry: the serializer's per-answer mapping, export columns, and the positional probe the "Other" response filter emits. Exceeding either is a 400 from the request schema, not a 422.

Deliberately separate from ResponseDataMap, which the read returns. These bounds are v3-only — the v1 and v2 write paths store the same map without them — so a stored response may exceed them, and the read schema must not claim otherwise.

embeddedDataResponseEmbeddedDataInput

Embedded Data values to write, keyed by field name.

This is the write counterpart of embeddedData[] on the read, and it is keyed the way an author names a field rather than the way storage addresses it. A hidden field is stored under its name but a variable is stored under its cuid, and that split is an implementation detail of the storage layout — the server resolves a name to its storage key through the survey's Embedded Data links, so a caller never sees a cuid and never has to know which kind it is writing.

Which kinds are writable:

  • ingested (hidden fields) — accepted, through the same ingest contract the SDK uses: the name must be declared on the survey, the value is coerced to the field's declared type, a locked field ignores the write, and the whole payload is bounded. A name the survey does not declare is a 422 rather than a silent drop — knowing whether a name is declared means loading the survey, and these operations route every failure that needs stored state to 422.

  • computed (variables) — accepted, because a management caller correcting a response needs to, and v1 and v2 both allow it today.

  • reserved — refused. Auto-captured context describes the submission environment, and a caller-supplied value would be fiction. The three exceptions are source, url and action, which ResponseMetaInput accepts for exactly the replay case.

Values follow their field's declared type. A field the payload omits is left as it is; this is a merge over named fields, not a replacement of the collection.

null clears a field. Omission and null therefore mean different things — leave it alone versus remove its value — which is the only reading that makes a merge-shaped map able to express deletion at all. A cleared field is then absent from embeddedData[] on the next read, exactly as one that was never written, and a field whose definition carries a defaultValue falls back to that default rather than disappearing.

An ambiguous name is refused. The read says key is unique per kind rather than across the collection, because a survey predating the reserved-name guard can hold a variable and a hidden field under one name. This map has no kind, so on such a survey a name cannot say which field it means — and guessing would write the caller's value into the wrong one. A name that matches more than one declared field is a 422 naming it, for the same reason as an undeclared one; rename one side on the survey to clear it. The set is finite, frozen and tracked, and nothing new can enter it.

Reserved names collide differently and are not ambiguous: reserved is not writable at all, so a name that matches both a declared field and a catalog entry resolves to the declared one.

At most 500 names. Every name that matches no declared field becomes its own invalid_params entry naming it, so without a cap a large body answers with a 422 several times its own size. Far above any real survey; a v3-only bound, as on data.

ttcResponseTtcMap

Per-element time-to-complete, keyed by element id, in milliseconds. Accepted on create so that a caller replaying a real submission can carry its timing; reads report the same information as durationSeconds in seconds, on each answer and summed at the top level.

This is client-reported telemetry, not a measurement the server can vouch for, so each value is clamped into [0, 86400000] (24 hours per element) rather than rejected — a noisy timing value should never cost you the response. Any finite value is therefore accepted, and none is declared out of range.

The number of entries is capped at 500, matching data: a response holds one timing per element, so anything beyond that is not telemetry the server can use. A map with more entries is rejected — maxProperties below is enforced during request validation, so the whole write fails rather than the excess being trimmed or stored.

Do not send a _total key. The server owns that bucket: it drops any _total you supply and writes its own when the response is finished, by summing the element entries. Sending one therefore changes nothing rather than skewing the stored total, and durationSeconds on the read is computed from the element entries regardless.

An omitted map is not the same as an empty one. Omitting ttc stores no timings at all and the response reports no durationSeconds; sending {} on a finished response stores a _total of zero, which reads as "completed instantly".

tagsstring[]

Tag ids to apply, so a tagged response can be created in one call rather than a create followed by a patch. Tags must already exist in the same workspace — create them via POST /api/v3/tags. Applied in the same transaction as the response.

endingIdstring nullable

The ending card the respondent reached. Must exist in the survey definition.

languagestring nullable

Survey language code to stamp on the response. Must be a language the survey has enabled. Omit for single-language surveys.

contactIdstring cuid2

Contact to attribute the response to. Create-only — a response cannot later be re-linked to a different contact. Must be a contact in the same workspace.

displayIdstring cuid2

Display (survey impression) this response answers. Create-only. Each display can back at most one response.

singleUseIdstring

Single-use link id, for surveys configured with single-use links. Create-only, and unique per survey. Bounded because the value is indexed with surveyId: an empty string would slip past the uniqueness pre-check and still be stored, and an oversize one overflows the index entry.

Response

Response created successfully

Changes

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new chart_in_use enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new dashboards_plan_required enum value to the response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new limit_exceeded enum value to the // response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new creatives_not_entitled enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status

    • warning

      added the new survey_has_linked_creatives enum value to the response property for the response status