API Reference
API Reference

/surveys/templates

Creates a survey master template. Required scope: w_surveys.

Recent Requests
Log in to see full request history
TimeStatusUser Agent
Retrieving recent requests…
LoadingLoading…
🚧

This endpoint uses the w_surveys scope, which must be enabled through the Integrations section found within the Settings menu.

Requires a user token whose member has permission to manage survey templates, or an account token together with the member_id of such a member (the request is then evaluated with that member's permissions). An account token without member_id gets 403 Account tokens need a member_id for this operation. Pass member_id as a query parameter (?member_id=...), not in the request body: the body rejects unknown fields with 400. The account must have the Surveys feature enabled. The template is saved in the survey category; use the list endpoint to retrieve it afterwards.

The request body is validated before authorization, so an invalid body returns 400 even when the token lacks the required scope or permission.

📘

Unknown keys are rejected with 400.

Request body

{
  "title": "Quarterly Engagement Pulse",
  "questionnaire": {
    "sections": [
      {
        "body": "Your experience",
        "questions": [
          {
            "body": "What part of your role gives you the most energy right now?",
            "type": "paragraph"
          },
          {
            "body": "Do you feel supported by your manager?",
            "type": "single_choice",
            "metadata": {
              "mandatory": true,
              "answer_options": {
                "choices": {
                  "yes": "Yes",
                  "no": "No"
                }
              },
              "has_conditional_navigation": true,
              "navigation_config": {
                "rules": {
                  "yes": { "type": "submit" },
                  "no": { "type": "go_to_question", "id": "7d1e2f30-4a5b-4c6d-8e9f-0a1b2c3d4e5f" }
                }
              }
            }
          },
          {
            "id": "7d1e2f30-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
            "body": "What could your manager do differently?",
            "type": "paragraph"
          }
        ]
      }
    ]
  }
}
keytypedescription
titlestringTitle of the template (required, trimmed)
questionnaire.sectionsarrayOrdered list of sections (required)
questionnaire.sections[].idstringOptional client-assigned id (UUID)
questionnaire.sections[].bodystringSection title / header text (required, may contain HTML)
questionnaire.sections[].positionintegerOrder of the section (≥ 0). Defaults to the section's index when omitted
questionnaire.sections[].questionsarrayOrdered list of questions (required, may be empty)
questionnaire.sections[].questions[].idstringOptional client-assigned id (UUID). Required if another question's navigation rule needs to target it
questionnaire.sections[].questions[].bodystringQuestion text (required, may contain HTML)
questionnaire.sections[].questions[].positionintegerOrder of the question within the section (≥ 0). Defaults to the question's index when omitted
questionnaire.sections[].questions[].typestringQuestion type. Accepts snake_case (e.g. single_choice) or PascalCase (e.g. SingleChoice). One of: paragraph, paragraph_star_rated, paragraph_numeric_rated, paragraph_custom_rated, single_choice, multiple_choice, star_rated, numeric_rated, custom_rated
questionnaire.sections[].questions[].metadataobject | nullOptional question metadata
questionnaire.sections[].questions[].metadata.mandatorybooleanWhether an answer is required
questionnaire.sections[].questions[].metadata.semantic_typestringSemantic role of the question. Accepts snake_case or PascalCase. One of: section_rating, overall_rating
questionnaire.sections[].questions[].metadata.rating_optionsobjectMap of rating value to label (string values)
questionnaire.sections[].questions[].metadata.answer_options.choicesobjectMap of choice key to label (string values)
questionnaire.sections[].questions[].metadata.has_conditional_navigationbooleanEnables conditional navigation (skip logic). When true, navigation_config is required
questionnaire.sections[].questions[].metadata.navigation_config.rulesobjectMap of choice key to navigation rule (required when navigation_config is present)
questionnaire.sections[].questions[].metadata.navigation_config.rules.*.typestringRule type. Accepts snake_case or camelCase. One of: next_question, go_to_question, go_to_section, submit
questionnaire.sections[].questions[].metadata.navigation_config.rules.*.idstringTarget question / section id (UUID). Required for go_to_question and go_to_section; not allowed for other types

Response

The created template is returned with status 201, in snake_case, with the ids and version assigned by the template registry.

{
  "id": "b2f0c1de-5a7e-4c1b-9d2a-0f6c3e8a91d4",
  "title": "Quarterly Engagement Pulse",
  "updated_at": "2025-01-10T09:30:00Z",
  "version": 1,
  "questionnaire": {
    "sections": [
      {
        "id": "2501ee00-0002-51cc-8e1c-6b29548a3d01",
        "body": "Your experience",
        "questions": [
          {
            "id": "2501ee00-0003-51cc-8e1c-6b29548a3d01",
            "body": "What part of your role gives you the most energy right now?",
            "type": "paragraph"
          },
          {
            "id": "2501ee00-0004-51cc-8e1c-6b29548a3d01",
            "body": "Do you feel supported by your manager?",
            "type": "single_choice",
            "metadata": {
              "mandatory": true,
              "answer_options": {
                "choices": {
                  "yes": "Yes",
                  "no": "No"
                }
              },
              "has_conditional_navigation": true,
              "navigation_config": {
                "rules": {
                  "yes": {
                    "type": "submit"
                  },
                  "no": {
                    "type": "go_to_question",
                    "id": "7d1e2f30-4a5b-4c6d-8e9f-0a1b2c3d4e5f"
                  }
                }
              }
            }
          },
          {
            "id": "7d1e2f30-4a5b-4c6d-8e9f-0a1b2c3d4e5f",
            "body": "What could your manager do differently?",
            "type": "paragraph"
          }
        ]
      }
    ]
  }
}

See GET /surveys/templates/:id for the full field reference. default, sample and disabled are included only when returned by the template registry.

Error responses

StatusCondition
400Validation failed (missing title or questionnaire, missing section / question body, invalid type, semantic_type or navigation rule type, non-UUID ids, has_conditional_navigation: true without navigation_config, unknown fields)
401Missing or invalid token
403Missing w_surveys scope, account token without member_id, the Surveys feature is not enabled for the account, or the user lacks permission to manage survey templates
409{"message": "Template title already exists", "errorCode": "template_title_already_exists"}: a template with the same title already exists

Error bodies: 401 / 403 responses are plain text holding the reason (e.g. Required scopes missing: ["w_surveys"]). 400 validation errors are JSON keyed by the offending field, e.g. {"title": {"code": "any.required", "message": "\"title\" is required"}}.

Query Params
string

Required when using an account token: the member (SPI key, from GET /members) to act as. The request is evaluated with that member's permissions; without it the request gets 403. Ignored for user tokens. Must be sent as a query parameter, not in the body.

Body Params
string
required

Title of the template

questionnaire
object
required
Headers
string
enum
Defaults to application/json

Generated from available response content types

Allowed:
Responses

Language
Credentials
Header
URL
LoadingLoading…
Response
Click Try It! to start a request and see the response here! Or choose an example:
application/json
text/plain