> ## Documentation Index
> Fetch the complete documentation index at: https://docs.moda.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Voyager Save Onboarding Survey

> Save Voyager's onboarding answers into the user's new-user survey.

Merged, not replaced: the body's responses overwrite the same question ids and every other
stored response stays. An existing survey keeps its version and completion (Voyager's
questions are additional to the web survey's); with none yet, the body is the survey. The
same ``personal_onboarding.*_recorded`` events as the web app's survey fire, with
``writer: "voyager"``.



## OpenAPI

````yaml /openapi/moda-public-api.yaml put /voyager/me/onboarding-survey
openapi: 3.1.0
info:
  title: Moda Public API
  description: >
    Programmatic access to Moda's canvas design platform. Create designs, export
    assets, manage brand kits, and run AI design tasks.


    ## Versioning


    Pin response shapes with a calendar-dated `Moda-Version` header (e.g.
    `2026-05-01`). **The pin is global** — it applies to every endpoint in the
    request, not just the one you adopted it for, so raising it to use a new
    endpoint also moves your other responses to that version's shapes.


    ### Migrating `2026-04-12` → `2026-05-01`


    - **Tasks** move from the flat `JobResponse` (`job_id`, `canvas_url`,
    `can_export`) to the canonical `Task` envelope. The export artifact is now
    under `result.export` as `{url, format, page_count}`; update any code that
    read the export URL from the old top-level fields.

    - **Multi-page PNG/JPEG exports are delivered as a single `.zip`** of
    per-page files (`page-1.png`, …), so `result.export.format` is `zip`. For
    one bundled document instead, request `format=pdf` or `pptx`; for a single
    image, pass `page_number`.
  version: 1.0.0
  x-moda-api-version: '2026-05-01'
servers:
  - url: https://api.moda.app/v1
    description: Production
security: []
tags:
  - name: canvases
    description: List, search, read, export, and share canvases
  - name: tasks
    description: Start and monitor AI design tasks
  - name: organizations
    description: List organizations and teams
  - name: credits
    description: Check credit balance and usage
  - name: brand-kits
    description: Manage brand kits
  - name: remix
    description: Duplicate and edit canvases
  - name: share-links
    description: Resolve share URLs to canvas identifiers
  - name: uploads
    description: Upload files for use as attachments
  - name: voices
    description: >-
      Managed voices: capabilities, the voice catalog, favorites and
      pronunciation dictionaries
  - name: usage
    description: Aggregate API usage stats for the caller's team
  - name: feedback
    description: Submit product feedback from Voyager
  - name: voyager
    description: 'Voyager desktop sign-in: OAuth config, device registration and revocation'
  - name: embed
    description: Signed iframe embed sessions
  - name: web
    description: 'Metered web research: search and page reading'
  - name: websites
    description: >-
      Create, update, publish, screenshot, and manage hosted multi-page static
      sites
  - name: drive
    description: >-
      Organize the workspace: folders, the folder tree, and item
      move/rename/visibility/delete for folders, canvases, and files
paths:
  /voyager/me/onboarding-survey:
    put:
      tags:
        - voyager
      summary: Voyager Save Onboarding Survey
      description: >-
        Save Voyager's onboarding answers into the user's new-user survey.


        Merged, not replaced: the body's responses overwrite the same question
        ids and every other

        stored response stays. An existing survey keeps its version and
        completion (Voyager's

        questions are additional to the web survey's); with none yet, the body
        is the survey. The

        same ``personal_onboarding.*_recorded`` events as the web app's survey
        fire, with

        ``writer: "voyager"``.
      operationId: voyagerSaveOnboardingSurvey
      parameters:
        - $ref: '#/components/parameters/ModaVersion'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OnboardingSurvey'
        required: true
      responses:
        '200':
          description: Successful Response
          content:
            application/json:
              schema:
                additionalProperties:
                  type: boolean
                type: object
                title: Response Voyagersaveonboardingsurvey
        '401':
          description: Authentication required.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '402':
          description: Insufficient credits for a metered operation.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: Permission denied for this scope.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: Resource not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '409':
          description: Conflict (idempotency / resource state).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '422':
          description: Request validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: Internal error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - API Key: []
components:
  parameters:
    ModaVersion:
      name: Moda-Version
      in: header
      required: false
      description: >-
        Calendar-dated API version pin. New integrations should pin `2026-05-01`
        to opt into the newest response shapes. For back-compat the server also
        accepts requests with no header and resolves them to the current default
        (today: `2026-04-12`); that default advances on each [sunset
        date](/api-reference/versioning). Any unsupported value returns 400
        `unsupported_version`.
      example: '2026-05-01'
      schema:
        type: string
        enum:
          - '2026-04-12'
          - '2026-05-01'
        default: '2026-05-01'
        example: '2026-05-01'
  schemas:
    OnboardingSurvey:
      properties:
        version:
          type: string
          maxLength: 64
          minLength: 1
          title: Version
        responses:
          additionalProperties:
            $ref: '#/components/schemas/OnboardingSurveyResponse'
          type: object
          maxProperties: 20
          title: Responses
        completed_at:
          anyOf:
            - type: string
              format: date-time
            - type: 'null'
          title: Completed At
      type: object
      required:
        - version
      title: OnboardingSurvey
      description: Versioned responses for the new-user survey.
    ErrorEnvelope:
      properties:
        type:
          $ref: '#/components/schemas/ErrorType'
        code:
          type: string
          title: Code
          description: >-
            Stable machine string keyed to doc_url. Never changes once
            published.
        message:
          type: string
          title: Message
          description: >-
            Human-readable message, for developers. Not localized, not
            user-facing.
        doc_url:
          type: string
          title: Doc Url
          description: Permalink to the docs page for this code.
        request_id:
          anyOf:
            - type: string
            - type: 'null'
          title: Request Id
          description: Correlator for logs/Sentry/audit.
        causes:
          anyOf:
            - items:
                $ref: '#/components/schemas/ErrorEnvelope'
              type: array
            - type: 'null'
          title: Causes
          description: Aggregated upstream failures (e.g. per-page export errors).
        details:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Details
          description: >-
            Code-specific detail payload (e.g. validation field list). Callers
            should pass ``None`` rather than ``{}`` to omit the key from the
            response.
        retry_after_ms:
          anyOf:
            - type: integer
            - type: 'null'
          title: Retry After Ms
          description: Hint for rate-limited or transient errors.
        retryable:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Retryable
          description: >-
            Explicit retryability for this code, from the error-code registry:
            ``false`` means retrying the same request cannot succeed (fix the
            input / resource first); ``true`` means the condition is transient
            and a retry (with backoff / after the blocker clears) can succeed.
            For a code whose retryability is context-dependent (the registry
            declares none), the raising site sets it per response when it knows
            the cause (e.g. ``source_url_unreachable``: a timeout is retryable,
            a 404 is not) and omits it otherwise — do not derive it from
            ``type`` or the HTTP status when this field is present.
      type: object
      required:
        - type
        - code
        - message
        - doc_url
      title: ErrorEnvelope
      description: >-
        Canonical error payload, nested under the top-level ``{"error": ...}``
        key.
    OnboardingSurveyResponse:
      properties:
        answer_ids:
          items:
            type: string
          type: array
          maxItems: 20
          title: Answer Ids
        display_order:
          items:
            type: string
          type: array
          maxItems: 20
          title: Display Order
        other_text:
          anyOf:
            - type: string
              maxLength: 500
            - type: 'null'
          title: Other Text
        skipped:
          type: boolean
          title: Skipped
          default: false
        completed_at:
          type: string
          format: date-time
          title: Completed At
      type: object
      required:
        - completed_at
      title: OnboardingSurveyResponse
      description: >-
        One persisted answer in the new-user survey.


        Question and option ids are intentionally data rather than schema fields
        so the

        survey can add or reorder questions without changing the API contract.
        The

        bounds keep this generic envelope from becoming an unbounded JSONB write
        path.
    ErrorType:
      type: string
      enum:
        - invalid_request
        - authentication
        - permission
        - not_found
        - conflict
        - rate_limited
        - idempotency_conflict
        - unprocessable
        - upstream_error
        - internal_error
      title: ErrorType
      description: Closed set of high-level categories SDKs branch on.
  securitySchemes:
    API Key:
      type: http
      description: API key from Settings > Developer > REST API
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.