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

# List surveys

> List the workspace's surveys, newest first. There are no filters. Requires a secret server key (`gt_live_`). Publishable keys (`gt_pub_`) return `403`.

**Scope:** `read:surveys`



## OpenAPI

````yaml /openapi.json get /surveys
openapi: 3.1.0
info:
  title: GainTrace API
  version: 1.0.0
  description: >-
    The GainTrace REST API (v1). Read your customer data and push product-usage
    events, metric events, and signals into GainTrace.


    All endpoints are authenticated with a Bearer API key and scoped to a single
    workspace.


    Each API key can send 60 requests a minute. A `429` response includes a
    `Retry-After` header with the seconds to wait.
servers:
  - url: https://app.gaintrace.com/api/v1
    description: Production
security:
  - bearerAuth: []
tags:
  - name: Companies
    description: Read and manage canonical company records.
  - name: Signals
    description: Read, create, and manage buyer / risk signals.
  - name: Ingest
    description: Push product-usage and metric events into GainTrace.
  - name: Contacts
    description: >-
      The original path for People. It shares its handlers with /people, and
      also offers delete-by-key.
  - name: Webhooks
    description: Subscribe to workspace events with signed, retried delivery.
  - name: People
    description: Read and manage People. One Person can belong to many Companies.
  - name: NPS responses
    description: Import NPS scores from another survey tool and read your NPS history.
  - name: Surveys
    description: >-
      Create and launch surveys, request invitations, record responses and mint
      in-app sessions.
  - name: Survey responses
    description: Read the responses collected by your surveys.
  - name: Survey segments
    description: Save groups of Companies and People that surveys can target.
  - name: Survey imports
    description: Pull responses from the survey tools your workspace has connected.
paths:
  /surveys:
    get:
      tags:
        - Surveys
      summary: List surveys
      description: >-
        List the workspace's surveys, newest first. There are no filters.
        Requires a secret server key (`gt_live_`). Publishable keys (`gt_pub_`)
        return `403`.


        **Scope:** `read:surveys`
      operationId: listSurveys
      parameters:
        - $ref: '#/components/parameters/limit'
        - $ref: '#/components/parameters/offset'
      responses:
        '200':
          description: A page of surveys.
          content:
            application/json:
              schema:
                type: object
                required:
                  - data
                  - meta
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Survey'
                  meta:
                    $ref: '#/components/schemas/Meta'
              example:
                data:
                  - id: 7b6f2c1e-4d3a-4b5c-9e8f-1a2b3c4d5e6f
                    name: Relationship NPS
                    measure: nps
                    status: draft
                    questions:
                      - text: How likely are you to recommend us to a colleague?
                        type: rating
                        required: true
                      - text: What is the main reason for your score?
                        type: text
                        required: false
                    settings:
                      thankYouTitle: Thank you
                      reminders:
                        afterDays: 3
                        max: 1
                    cooldownDays: 90
                    createdAt: '2026-10-14T09:00:00.000Z'
                    updatedAt: '2026-10-14T09:00:00.000Z'
                meta:
                  limit: 50
                  offset: 0
                  count: 1
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalServerError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
        '504':
          $ref: '#/components/responses/GatewayTimeout'
components:
  parameters:
    limit:
      name: limit
      in: query
      description: Max rows to return. Default 50, max 100.
      schema:
        type: integer
        default: 50
        maximum: 100
        minimum: 1
    offset:
      name: offset
      in: query
      description: Rows to skip (pagination).
      schema:
        type: integer
        default: 0
        minimum: 0
  schemas:
    Survey:
      type: object
      required:
        - id
        - name
        - measure
        - status
        - questions
        - settings
        - cooldownDays
        - createdAt
        - updatedAt
      properties:
        id:
          type: string
          format: uuid
        name:
          type: string
        measure:
          $ref: '#/components/schemas/SurveyMeasure'
        status:
          type: string
          enum:
            - draft
            - active
            - closed
        questions:
          type: array
          items:
            $ref: '#/components/schemas/SurveyQuestion'
        settings:
          $ref: '#/components/schemas/SurveySettings'
        cooldownDays:
          type: integer
        createdAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
    Meta:
      type: object
      properties:
        limit:
          type: integer
        offset:
          type: integer
        count:
          type: integer
          description: Number of rows in this page.
    SurveyMeasure:
      type: string
      enum:
        - nps
        - csat
        - ces
        - custom
      description: >-
        `nps` is a 0-10 scale. `csat` and `ces` use a 1-5 or 1-7 scale. `custom`
        has no band and its responses are `unscored`. For `nps`, `csat` and
        `ces`, the first question must be a required `rating` or `scale`
        question: it carries the score.
    SurveyQuestion:
      type: object
      required:
        - text
        - type
        - required
      additionalProperties: false
      properties:
        text:
          type: string
          minLength: 1
          maxLength: 1000
          description: >-
            The question text. Use `{{company}}`, `{{first_name}}` or
            `{{score}}` to fill in details from a signed link. `{{company|your
            team}}` falls back to the text after the bar. Surveys must stay
            purely feedback, so promotional phrases such as "discount code" or
            "limited time" are rejected.
        type:
          type: string
          enum:
            - rating
            - scale
            - text
            - multiple_choice
            - multi_select
            - dropdown
            - matrix
            - ranking
            - date
            - statement
            - consent
          description: >-
            `rating` and `scale` are scored questions. `multiple_choice` picks
            one answer, `multi_select` picks several (checkboxes) and `dropdown`
            picks one from a long list. `matrix` asks one scale for several
            rows, `ranking` orders a list, `date` takes a calendar date,
            `statement` shows text with no answer, and `consent` is a required
            checkbox.
        required:
          type: boolean
          description: >-
            A `statement` can't be required. A `consent` question must be
            required.
        options:
          type: array
          minItems: 2
          maxItems: 100
          items:
            type: string
            maxLength: 255
            minLength: 1
          description: >-
            Answer choices, each different. Required for `multiple_choice`,
            `multi_select`, `dropdown` and `ranking`. Up to 20 for
            `multiple_choice` and `multi_select`, 100 for `dropdown`, and 10 for
            `ranking`. For `matrix`, these are the scale columns, lowest first,
            up to 10.
        rows:
          type: array
          minItems: 2
          maxItems: 15
          items:
            type: string
            maxLength: 255
            minLength: 1
          description: >-
            `matrix` only: the statements people rate against the columns in
            `options`. Each row is different.
        minSelections:
          type: integer
          minimum: 1
          maximum: 20
          description: >-
            `multi_select` only: the fewest boxes a person must tick. It can't
            exceed `maxSelections` or the number of options.
        maxSelections:
          type: integer
          minimum: 1
          maximum: 20
          description: >-
            `multi_select` only: the most boxes a person may tick. It can't
            exceed the number of options.
        scaleMin:
          type: integer
          minimum: 0
          maximum: 10
        scaleMax:
          type: integer
          minimum: 1
          maximum: 10
          description: Must be greater than `scaleMin` when both are set.
        scaleLabels:
          type: object
          required:
            - min
            - max
          additionalProperties: false
          properties:
            min:
              type: string
              maxLength: 100
            max:
              type: string
              maxLength: 100
        display:
          type: string
          enum:
            - faces
            - stars
            - numbers
          description: >-
            `rating` only. `stars` needs a 1 to 5 scale. `faces` is for the
            first question of a CSAT survey on a 1 to 5 scale. NPS and CES
            scores show as numbers.
        description:
          type: string
          maxLength: 2000
          description: '`statement` and `consent` only: the text under the question.'
        link:
          type: object
          required:
            - label
            - url
          additionalProperties: false
          description: >-
            `statement` and `consent` only: an optional link, for example to a
            policy.
          properties:
            label:
              type: string
              minLength: 1
              maxLength: 40
            url:
              type: string
              format: uri
              maxLength: 2048
              description: An HTTPS link.
        preset:
          type: string
          enum:
            - pmf
          description: >-
            `pmf` marks the product-market fit question. It must be a
            `multiple_choice` question with the four standard answers `Very
            disappointed`, `Somewhat disappointed`, `Not disappointed` and `I no
            longer use it`, in that order. Results then include the share who
            would be very disappointed.
        showWhen:
          type: object
          required:
            - operator
            - value
          additionalProperties: false
          description: >-
            Show this question only when an earlier answer matches. A question
            can depend only on an earlier question. The operator depends on the
            earlier question's type: `lte`, `gte` or `eq` with a number for
            `rating` and `scale`; `is` or `is_not` with one of the answer
            choices for `multiple_choice` and `dropdown`; `includes` or
            `excludes` with one of the choices for `multi_select`; `before` or
            `after` with a `YYYY-MM-DD` date for `date`. A score value must sit
            inside the earlier question's scale.
          properties:
            question:
              type: integer
              minimum: 0
              maximum: 19
              description: >-
                Zero-based index of the earlier question. Defaults to the first
                question.
            operator:
              type: string
              enum:
                - lte
                - gte
                - eq
                - is
                - is_not
                - includes
                - excludes
                - before
                - after
            value:
              oneOf:
                - type: integer
                  minimum: 0
                  maximum: 10
                - type: string
                  maxLength: 255
                  minLength: 1
        logic:
          allOf:
            - $ref: '#/components/schemas/SurveyLogicGroup'
          description: >-
            Show this question only when these conditions on earlier answers or
            hidden fields match. Never send both `logic` and `showWhen`.
        jumps:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/SurveyJumpRule'
          description: >-
            Where to go after this question. The first rule whose conditions
            match wins.
        libraryId:
          type: string
          format: uuid
          description: >-
            The workspace library question this one was copied from. Never shown
            to respondents.
    SurveySettings:
      type: object
      additionalProperties: false
      description: Optional survey settings. Unknown keys are rejected.
      properties:
        defaultLanguage:
          type: string
          enum:
            - en
            - ar
            - bg
            - bn
            - ca
            - cs
            - da
            - de
            - el
            - es
            - et
            - fa
            - fi
            - fil
            - fr
            - he
            - hi
            - hr
            - hu
            - id
            - it
            - ja
            - ko
            - lt
            - lv
            - ms
            - nl
            - 'no'
            - pl
            - pt-BR
            - pt-PT
            - ro
            - ru
            - sk
            - sl
            - sr
            - sv
            - th
            - tr
            - uk
            - ur
            - vi
            - zh-CN
            - zh-TW
          description: >-
            The language respondents see when nothing else matches. Defaults to
            `en`.
        translations:
          type: object
          maxProperties: 15
          propertyNames:
            enum:
              - en
              - ar
              - bg
              - bn
              - ca
              - cs
              - da
              - de
              - el
              - es
              - et
              - fa
              - fi
              - fil
              - fr
              - he
              - hi
              - hr
              - hu
              - id
              - it
              - ja
              - ko
              - lt
              - lv
              - ms
              - nl
              - 'no'
              - pl
              - pt-BR
              - pt-PT
              - ro
              - ru
              - sk
              - sl
              - sr
              - sv
              - th
              - tr
              - uk
              - ur
              - vi
              - zh-CN
              - zh-TW
          additionalProperties:
            $ref: '#/components/schemas/SurveyLanguageCopy'
          description: >-
            Respondent copy per language code, up to 15 languages. A respondent
            sees the language they choose or their browser asks for when the
            survey offers it, and the default language otherwise. Translations
            never change a score or answer: GainTrace maps what a respondent
            picked back to the default-language choice before it saves.
        brandColor:
          type: string
          pattern: ^#[0-9a-fA-F]{6}$
          example: '#FFAC00'
        logoUrl:
          type: string
          format: uri
          maxLength: 2048
          description: An HTTPS image URL.
        thankYouTitle:
          type: string
          maxLength: 120
        thankYouMessage:
          type: string
          maxLength: 1000
        thankYouByBand:
          type: object
          additionalProperties: false
          description: >-
            Replaces the title, message and button for respondents whose score
            lands in a band.
          properties:
            negative:
              type: object
              additionalProperties: false
              properties:
                title:
                  type: string
                  maxLength: 120
                message:
                  type: string
                  maxLength: 1000
                link:
                  type: object
                  required:
                    - label
                    - url
                  additionalProperties: false
                  description: >-
                    A button for this score group only, such as a review site
                    for promoters. Falls back to `thankYouLink`.
                  properties:
                    label:
                      type: string
                      minLength: 1
                      maxLength: 40
                    url:
                      type: string
                      format: uri
                      maxLength: 2048
                      description: An HTTPS link.
            neutral:
              type: object
              additionalProperties: false
              properties:
                title:
                  type: string
                  maxLength: 120
                message:
                  type: string
                  maxLength: 1000
                link:
                  type: object
                  required:
                    - label
                    - url
                  additionalProperties: false
                  description: >-
                    A button for this score group only, such as a review site
                    for promoters. Falls back to `thankYouLink`.
                  properties:
                    label:
                      type: string
                      minLength: 1
                      maxLength: 40
                    url:
                      type: string
                      format: uri
                      maxLength: 2048
                      description: An HTTPS link.
            positive:
              type: object
              additionalProperties: false
              properties:
                title:
                  type: string
                  maxLength: 120
                message:
                  type: string
                  maxLength: 1000
                link:
                  type: object
                  required:
                    - label
                    - url
                  additionalProperties: false
                  description: >-
                    A button for this score group only, such as a review site
                    for promoters. Falls back to `thankYouLink`.
                  properties:
                    label:
                      type: string
                      minLength: 1
                      maxLength: 40
                    url:
                      type: string
                      format: uri
                      maxLength: 2048
                      description: An HTTPS link.
        thankYouLink:
          type: object
          required:
            - label
            - url
          additionalProperties: false
          description: An optional next step on the thank-you screen.
          properties:
            label:
              type: string
              minLength: 1
              maxLength: 40
            url:
              type: string
              format: uri
              maxLength: 2048
              description: An HTTPS link.
        anonymous:
          type: boolean
          description: >-
            Anonymous surveys store no person, company or respondent identity on
            a response. This setting locks once the survey is live or has
            responses.
        hiddenFields:
          type: array
          maxItems: 10
          items:
            type: string
            pattern: ^[a-z][a-z0-9_]{0,39}$
          description: >-
            Names of link parameters saved with each response, for example
            `plan`. Values for any other name are dropped.
        endings:
          type: array
          maxItems: 10
          items:
            $ref: '#/components/schemas/SurveyEnding'
          description: Named thank-you screens that only logic jumps reach.
        customCss:
          type: string
          maxLength: 10000
          description: >-
            Styling for the respondent page and the in-app survey. It can't
            contain `<`, `@import` or `url()`.
        sendWindow:
          type: object
          required:
            - startHour
            - endHour
            - weekdaysOnly
          additionalProperties: false
          description: >-
            Approved email invitations wait for these local hours in the
            workspace time zone.
          properties:
            startHour:
              type: integer
              minimum: 0
              maximum: 23
            endHour:
              type: integer
              minimum: 1
              maximum: 24
              description: Must be greater than `startHour`.
            weekdaysOnly:
              type: boolean
        reminders:
          type: object
          required:
            - afterDays
            - max
          additionalProperties: false
          description: >-
            Re-send to people who have not answered. People who answered are
            never reminded.
          properties:
            afterDays:
              type: integer
              minimum: 1
              maximum: 14
            max:
              type: integer
              minimum: 1
              maximum: 3
        alerts:
          type: object
          required:
            - bands
          additionalProperties: false
          description: >-
            Post each new response in the chosen bands to Slack, Microsoft
            Teams, or both. Set `slackChannel`, `teamsWebhookUrl` or both.
          properties:
            bands:
              type: array
              minItems: 1
              maxItems: 3
              items:
                type: string
                enum:
                  - negative
                  - neutral
                  - positive
            slackChannel:
              type: string
              pattern: ^[CG][A-Z0-9]{6,}$
              description: A Slack channel id.
            teamsWebhookUrl:
              type: string
              format: uri
              maxLength: 2048
              description: The HTTPS webhook URL from a Teams Workflow.
        inApp:
          type: object
          required:
            - enabled
            - allowedOrigins
            - minAgeDays
            - minSessions
            - maxDisplays
            - delayMs
          additionalProperties: false
          description: In-app collection rules. See the in-app SDK guide.
          properties:
            enabled:
              type: boolean
              description: Enabling requires at least one allowed origin.
            allowedOrigins:
              type: array
              maxItems: 20
              items:
                type: string
                format: uri
                maxLength: 255
              description: >-
                Exact origins such as `https://app.example.com`. No paths, no
                wildcards. HTTPS only, except `http://localhost` and
                `http://127.0.0.1`.
            minAgeDays:
              type: integer
              minimum: 0
              maximum: 730
              description: Days since the person was first recorded in GainTrace.
            minSessions:
              type: integer
              minimum: 1
              maximum: 365
              description: >-
                Distinct UTC days on which a session was recorded for the
                person.
            maxDisplays:
              type: integer
              minimum: 1
              maximum: 10
              description: Maximum displays inside the survey's cooldown window.
            delayMs:
              type: integer
              minimum: 0
              maximum: 120000
            samplingPercent:
              type: integer
              minimum: 1
              maximum: 100
              description: >-
                Show to this share of eligible people. The same people stay in
                or out of the sample on every visit. Omit for everyone.
            position:
              type: string
              enum:
                - bottom
                - bottom-right
                - bottom-left
                - center
              description: Defaults to `bottom`. `center` is a blocking modal.
            targeting:
              $ref: '#/components/schemas/SurveyInAppTargeting'
        advocacy:
          type: object
          additionalProperties: false
          required:
            - enabled
            - ask
          description: >-
            When a respondent in the top score group (NPS 9-10, or the top two
            points of a CSAT or effort scale) at a known Company answers, the
            Company's CSM gets a task to ask them for a review, a case study or
            a reference call. At most one open ask per person; anonymous surveys
            never create one.
          properties:
            enabled:
              type: boolean
            ask:
              type: string
              enum:
                - review
                - case_study
                - reference
        aiProbe:
          type: object
          required:
            - enabled
          additionalProperties: false
          description: >-
            One optional AI-written follow-up question, asked after the response
            is saved and labelled as AI-generated. Off unless enabled. When a
            respondent answers it, the question and answer appear in the
            response `answers` under `_probe`.
          properties:
            enabled:
              type: boolean
    Error:
      type: object
      required:
        - error
      description: The standard error envelope. Every 4xx/5xx response uses this shape.
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - bad_request
                - unauthorized
                - payment_required
                - forbidden
                - not_found
                - conflict
                - unprocessable_entity
                - rate_limit_exceeded
                - internal_server_error
                - service_unavailable
                - gateway_timeout
              description: >-
                Stable, machine-readable error code. Each code maps to exactly
                one HTTP status.
            message:
              type: string
              description: >-
                Human-readable, safe description of what went wrong. Never
                contains internal or provider detail.
            doc_url:
              type: string
              format: uri
              example: https://docs.gaintrace.com/errors#not_found
              description: Deep link to this code in the Errors reference.
    SurveyLogicGroup:
      type: object
      required:
        - match
        - conditions
      additionalProperties: false
      description: >-
        Conditions on earlier answers or hidden fields. `match` is `all` or
        `any`.
      properties:
        match:
          type: string
          enum:
            - all
            - any
        conditions:
          type: array
          minItems: 1
          maxItems: 10
          items:
            oneOf:
              - type: object
                required:
                  - question
                  - operator
                  - value
                additionalProperties: false
                description: >-
                  An earlier answer. `question` is the zero-based index. `band`
                  compares the score group (negative, neutral or positive).
                properties:
                  question:
                    type: integer
                    minimum: 0
                    maximum: 19
                  operator:
                    type: string
                    enum:
                      - lte
                      - gte
                      - eq
                      - is
                      - is_not
                      - includes
                      - excludes
                      - before
                      - after
                      - band
                  value:
                    oneOf:
                      - type: integer
                        minimum: 0
                        maximum: 10
                      - type: string
                        maxLength: 255
                        minLength: 1
              - type: object
                required:
                  - hidden
                  - operator
                  - value
                additionalProperties: false
                description: A hidden field the survey lists in `settings.hiddenFields`.
                properties:
                  hidden:
                    type: string
                    pattern: ^[a-z][a-z0-9_]{0,39}$
                  operator:
                    type: string
                    enum:
                      - is
                      - is_not
                  value:
                    type: string
                    minLength: 1
                    maxLength: 200
    SurveyJumpRule:
      type: object
      required:
        - when
        - to
      additionalProperties: false
      description: >-
        Where to go after the question when the conditions match. The first
        matching rule wins, otherwise the next question.
      properties:
        when:
          $ref: '#/components/schemas/SurveyLogicGroup'
        to:
          oneOf:
            - type: object
              required:
                - question
              additionalProperties: false
              properties:
                question:
                  type: integer
                  minimum: 1
                  maximum: 19
            - type: object
              required:
                - ending
              additionalProperties: false
              properties:
                ending:
                  type: string
                  pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
                  description: The `id` of an entry in `settings.endings`.
            - type: object
              required:
                - end
              additionalProperties: false
              properties:
                end:
                  type: boolean
                  enum:
                    - true
    SurveyLanguageCopy:
      type: object
      additionalProperties: false
      description: >-
        The copy for one language. Anything you leave out falls back to the
        default language. A question translation applies only while the default
        copy it was written against is unchanged: GainTrace stamps a `source`
        fingerprint on save, and a translation whose fingerprint no longer
        matches is ignored until you update it.
      properties:
        title:
          type: string
          minLength: 1
          maxLength: 200
          description: The survey name shown as the heading.
        questions:
          type: array
          maxItems: 20
          description: >-
            One entry per question, in order. Use `null` for a question you
            don't translate.
          items:
            oneOf:
              - type: 'null'
              - type: object
                additionalProperties: false
                properties:
                  source:
                    type: string
                    pattern: ^[0-9a-f]{8}$
                    description: >-
                      Fingerprint of the default copy. GainTrace sets it on save
                      when you leave it out.
                  text:
                    type: string
                    minLength: 1
                    maxLength: 1000
                  description:
                    type: string
                    minLength: 1
                    maxLength: 2000
                  linkLabel:
                    type: string
                    maxLength: 255
                    minLength: 1
                  options:
                    type: array
                    maxItems: 100
                    items:
                      type: string
                      maxLength: 255
                      minLength: 1
                    description: Same length and order as the default `options`.
                  rows:
                    type: array
                    maxItems: 15
                    items:
                      type: string
                      maxLength: 255
                      minLength: 1
                    description: Same length and order as the default `rows`.
                  scaleLabels:
                    type: object
                    additionalProperties: false
                    properties:
                      min:
                        type: string
                        minLength: 1
                        maxLength: 100
                      max:
                        type: string
                        minLength: 1
                        maxLength: 100
        thankYou:
          type: object
          additionalProperties: false
          properties:
            title:
              type: string
              minLength: 1
              maxLength: 120
            message:
              type: string
              minLength: 1
              maxLength: 1000
            linkLabel:
              type: string
              minLength: 1
              maxLength: 40
            byBand:
              type: object
              additionalProperties: false
              properties:
                negative:
                  type: object
                  additionalProperties: false
                  properties:
                    title:
                      type: string
                      minLength: 1
                      maxLength: 120
                    message:
                      type: string
                      minLength: 1
                      maxLength: 1000
                    linkLabel:
                      type: string
                      minLength: 1
                      maxLength: 40
                neutral:
                  type: object
                  additionalProperties: false
                  properties:
                    title:
                      type: string
                      minLength: 1
                      maxLength: 120
                    message:
                      type: string
                      minLength: 1
                      maxLength: 1000
                    linkLabel:
                      type: string
                      minLength: 1
                      maxLength: 40
                positive:
                  type: object
                  additionalProperties: false
                  properties:
                    title:
                      type: string
                      minLength: 1
                      maxLength: 120
                    message:
                      type: string
                      minLength: 1
                      maxLength: 1000
                    linkLabel:
                      type: string
                      minLength: 1
                      maxLength: 40
        ui:
          type: object
          additionalProperties:
            type: string
            minLength: 1
            maxLength: 1000
          description: >-
            Overrides for the respondent page's interface strings, keyed by
            string id. An unknown key returns `422`.
        endings:
          type: object
          description: Translations of `settings.endings`, keyed by ending `id`.
          additionalProperties:
            type: object
            additionalProperties: false
            properties:
              title:
                type: string
                minLength: 1
                maxLength: 120
              message:
                type: string
                minLength: 1
                maxLength: 1000
              linkLabel:
                type: string
                minLength: 1
                maxLength: 40
        reviewedAt:
          type: string
          format: date-time
    SurveyEnding:
      type: object
      required:
        - id
        - name
      additionalProperties: false
      description: >-
        A named thank-you screen that only logic jumps reach. It overrides the
        score-group and default copy field by field.
      properties:
        id:
          type: string
          pattern: ^[a-z0-9][a-z0-9_-]{0,39}$
        name:
          type: string
          minLength: 1
          maxLength: 60
        title:
          type: string
          maxLength: 120
        message:
          type: string
          maxLength: 1000
        link:
          type: object
          required:
            - label
            - url
          additionalProperties: false
          properties:
            label:
              type: string
              minLength: 1
              maxLength: 40
            url:
              type: string
              format: uri
              maxLength: 2048
              description: An HTTPS link.
    SurveyInAppTargeting:
      type: object
      additionalProperties: false
      description: >-
        Who, where and when the in-app survey shows. GainTrace checks the page
        rules first, then the audience, then the trigger. People who don't
        qualify get a reason from `POST /surveys/{id}/session`.
      properties:
        audience:
          description: Limit the survey to a saved segment, or to rules you send here.
          oneOf:
            - type: object
              required:
                - segmentId
              additionalProperties: false
              properties:
                segmentId:
                  type: string
                  format: uuid
            - type: object
              required:
                - rules
              additionalProperties: false
              properties:
                rules:
                  $ref: '#/components/schemas/SurveyAudienceRules'
        pages:
          type: object
          required:
            - include
            - exclude
          additionalProperties: false
          description: >-
            Page rules matched against the `context.url` your backend sends when
            it mints a session. With include rules, the page must match one. A
            page that matches an exclude rule never shows the survey.
          properties:
            include:
              type: array
              maxItems: 20
              items:
                $ref: '#/components/schemas/SurveyPageRule'
            exclude:
              type: array
              maxItems: 20
              items:
                $ref: '#/components/schemas/SurveyPageRule'
        trigger:
          description: >-
            What makes the survey appear. Without a trigger it shows as soon as
            the person qualifies.
          oneOf:
            - type: object
              required:
                - kind
              additionalProperties: false
              properties:
                kind:
                  type: string
                  enum:
                    - page_load
            - type: object
              required:
                - kind
                - events
              additionalProperties: false
              properties:
                kind:
                  type: string
                  enum:
                    - event
                events:
                  type: array
                  minItems: 1
                  maxItems: 10
                  items:
                    type: string
                    pattern: ^[A-Za-z0-9][A-Za-z0-9_.:-]{0,63}$
                  description: Event names your code sends with `GaintraceSurveys.track()`.
            - type: object
              required:
                - kind
                - seconds
              additionalProperties: false
              properties:
                kind:
                  type: string
                  enum:
                    - time_on_page
                seconds:
                  type: integer
                  minimum: 1
                  maximum: 600
    SurveyAudienceRules:
      type: object
      required:
        - company
        - person
      additionalProperties: false
      description: >-
        Who to reach: People who match `person`, at Companies that match
        `company`. An empty `rules` list in a group matches everyone for that
        group. A request needs at least one rule across both groups, so nobody
        is ever invited by accident. Only People with an email address at
        Companies that aren't archived can match.
      properties:
        company:
          $ref: '#/components/schemas/SurveyFilterGroup'
        person:
          $ref: '#/components/schemas/SurveyFilterGroup'
    SurveyPageRule:
      type: object
      required:
        - match
        - value
      additionalProperties: false
      properties:
        match:
          type: string
          enum:
            - equals
            - contains
            - starts_with
        value:
          type: string
          minLength: 1
          maxLength: 512
          description: >-
            A path and query such as `/billing`. No spaces, and nothing after
            `#`.
    SurveyFilterGroup:
      type: object
      required:
        - logic
        - rules
      additionalProperties: false
      properties:
        logic:
          type: string
          enum:
            - and
            - or
        rules:
          type: array
          maxItems: 20
          items:
            $ref: '#/components/schemas/SurveyFilterRule'
    SurveyFilterRule:
      type: object
      required:
        - field
        - operator
        - value
      additionalProperties: false
      properties:
        field:
          type: string
          minLength: 1
          maxLength: 120
          description: >-
            In a Company rule group, a field key from your Company data model,
            such as `segment` or `plan`. In a People rule group, one of `email`,
            `name`, `role`, `contactRole`, `isChampion`, `lastSeenAt`,
            `engagementScore`, `createdAt`, or `traits.<key>` for a Person
            trait. `person.` and `people.` prefixes are accepted. Any other
            People field returns `422`.
        operator:
          type: string
          enum:
            - eq
            - neq
            - gt
            - gte
            - lt
            - lte
            - contains
            - not_contains
            - starts_with
            - ends_with
            - is_empty
            - is_not_empty
            - in
            - not_in
            - between
            - before
            - after
            - in_the_last
            - in_the_next
            - older_than
            - further_than
            - is
            - is_not
            - is_any_of
            - is_none_of
          description: The same operators Flow conditions use.
        value:
          oneOf:
            - type: string
              maxLength: 500
            - type: number
            - type: boolean
            - type: array
              maxItems: 50
              items:
                type: string
                maxLength: 200
        value2:
          oneOf:
            - type: string
              maxLength: 500
            - type: number
          description: The upper bound for `between`.
        unit:
          type: string
          enum:
            - minutes
            - hours
            - days
            - workdays
            - weeks
            - months
          description: The unit for date operators such as `in_the_last`.
  responses:
    Unauthorized:
      description: Missing, malformed, expired, or revoked API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: unauthorized
              message: Missing Authorization header
              doc_url: https://docs.gaintrace.com/errors#unauthorized
    Forbidden:
      description: >-
        The key is valid but lacks the required scope, the origin is not
        allowed, or API v1 is not enabled for the workspace.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: forbidden
              message: 'Insufficient scope: write:companies required'
              doc_url: https://docs.gaintrace.com/errors#forbidden
    RateLimited:
      description: >-
        The per-key rate limit was exceeded. Each API key can send 60 requests
        per minute, counted in calendar-minute windows. The `Retry-After` header
        gives the whole seconds (1 to 60) until the next window opens. Wait that
        long, then retry.
      headers:
        Retry-After:
          description: Whole seconds until the next one-minute window starts.
          schema:
            type: integer
            minimum: 1
            maximum: 60
          example: 23
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: rate_limit_exceeded
              message: >-
                Can't accept more than 60 requests a minute from one API key.
                Retry in 23 seconds.
              doc_url: https://docs.gaintrace.com/errors#rate_limit_exceeded
    InternalServerError:
      description: >-
        An unexpected error occurred on our side. The failure is logged; retry
        shortly.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: internal_server_error
              message: Something went wrong. Try again in a moment.
              doc_url: https://docs.gaintrace.com/errors#internal_server_error
    ServiceUnavailable:
      description: >-
        A backing service (for example, the database) was temporarily
        unavailable. Retry shortly.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: service_unavailable
              message: We had trouble reaching the database. Try again in a moment.
              doc_url: https://docs.gaintrace.com/errors#service_unavailable
    GatewayTimeout:
      description: >-
        The request took too long upstream before completing. Retry, and reduce
        batch size for large payloads.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            error:
              code: gateway_timeout
              message: The request timed out. Try again in a moment.
              doc_url: https://docs.gaintrace.com/errors#gateway_timeout
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Bearer API key. Secret server keys start with `gt_live_`; client-safe
        browser keys start with `gt_pub_` (write-only, origin-pinned). Create
        and scope keys in Settings → API Keys.

````

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