Forms & Profiles
The forms system drives any structured input the platform needs to render: account creation, account settings, profiles, surveys, and product reviews. A form is a server-defined list of fields with validators and render conditions, which the client renders and then posts back as a FormSubmissionInput.
Because forms are configured server-side, the same client code can render any form by identifier — you don’t need bespoke UI per form. Availability is gated by FORM_INFO; additional form types are unlocked by PROFILES, SURVEYS and REVIEWS.
Fetching a form
Section titled “Fetching a form”Every form has an identifier and a list of fields. Each field carries its type, the validators that apply, a required flag, and any renderConditions that hide it until other answers are given.
query GetForm { form(input: { identifier: "subscription-cancellation" }) { identifier type displayStyle isMultiSubmission canSubmit fields { name label translation { value } type required confirmable disabled defaultValue validators { name argument } answerOptions { optionKey translation { value } } renderConditions { referenceFieldName relationship value } } }}displayStyle tells the client whether to render every field on a single page or step through one question at a time.
Listing forms
Section titled “Listing forms”forms returns multiple forms by type. profiles is the same query restricted to profile forms; this is what powers the profile-list view in the account section.
query AccountProfiles { profiles(input: { type: MAIN_PROFILE }) { identifier type canSubmit isMultiSubmission submissions { id complete submissionTitle submissionSubtitle } }}Convenience queries for common fields
Section titled “Convenience queries for common fields”For sign-up and login flows the API exposes the canonical email, password and referral-code field definitions directly, so the client doesn’t have to fetch a whole form to render them. The matching accountCreationForm and accountSettingsForm queries return the full forms.
query SignupFields { accountCreationForm { identifier fields { name type required validators { name argument } } } emailField { name validators { name argument } } passwordField { name validators { name argument } } referralCodeField { name validators { name argument } }}Reading a submission
Section titled “Reading a submission”Existing submissions are reachable from the form. Use this to pre-populate a form for editing.
query FormSubmission { form(input: { identifier: "main-profile" }) { submission(submissionId: "sub_123") { id complete editable answers { question { name type } values locked } } }}Submitting a profile
Section titled “Submitting a profile”Pass the form identifier and an answers array keyed by questionName. For new submissions leave submissionId null; for edits pass the existing id.
mutation SubmitProfile { submitProfile( input: { identifier: "main-profile" answers: [ { questionName: "fitness_goal", values: ["LOSE_WEIGHT"] } { questionName: "preferred_flavours", values: ["CHOCOLATE", "VANILLA"] } ] } ) { status fieldErrors { fieldName validators requiredButNotProvided invalidOption } outcome { outcomeType outcomeValue } }}The status enum covers the full set of outcomes (SUBMITTED, SUBMITTED_INCOMPLETE, EDITED_NOW_COMPLETE, LOGIN_REQUIRED, ALREADY_SUBMITTED, ERROR_SUBMITTING, etc.). fieldErrors is populated when validation fails so the client can highlight the offending fields. For profiles that produce a recommendation, outcome carries the URL to send the customer to next.
Deleting a profile submission
Section titled “Deleting a profile submission”mutation DeleteProfileSubmission { deleteProfileSubmission(submissionId: "sub_123")}Submitting a survey
Section titled “Submitting a survey”Surveys use the same input shape but go through their own mutation and require authentication. The otherText field on FormAnswerInput is for answers where the survey offers an “other” free-text option alongside the predefined choices.
mutation SubmitSurvey { submitSurvey( input: { identifier: "post-purchase-survey-42" answers: [ { questionName: "satisfaction", values: ["4"] } { questionName: "improvement_area" values: ["OTHER"] otherText: "Faster delivery" } ] } ) { status fieldErrors { fieldName validators } }}