Anleitungen

Building a survey

Create a survey from a short draft, publish it, change its questions and settings, and know which limits apply along the way.

Die Entwickler-Dokumentation gibt es nur auf Englisch, wie die API selbst.

This guide creates a survey through the API, publishes it, and changes it afterwards. It needs a key with the scope surveys:write, and surveys:read to read the survey back. The shell variables SF_API and SF_KEY are set up as in the Quickstart.

How a survey is built

A survey is a list of pages, called modules, plus settings:

  • a start page with a headline and a button
  • one or more questions pages
  • an end page that thanks the respondent

Every text is an object keyed by language code, for example { "en": "How was the workshop?" }. The full shape has around thirty fields per page: ids, order, presentation defaults. You rarely write it by hand. Describe the survey as a short draft instead, and the server builds the rest.

Create a survey from a draft

bash
curl -X POST "$SF_API/v1/surveys" \
  -H "Authorization: Bearer $SF_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Workshop feedback",
    "draft": {
      "pollName": "Workshop feedback",
      "language": "en",
      "welcomeTitle": "Thanks for joining the workshop",
      "questions": [
        { "kind": "rating", "text": "How was the workshop?" },
        { "kind": "choice", "text": "Which session did you attend?", "options": ["Morning", "Afternoon", "Evening"] },
        { "kind": "nps", "text": "How likely are you to recommend us?" },
        { "kind": "open_text", "text": "Anything we should improve?" }
      ]
    }
  }'

The answer is 201 with the whole survey, including the generated modules and settings. Keep its id:

bash
export SURVEY_ID="4c303674-1dd4-4836-ada7-0092fe2c7df3"

name is the internal name shown in the dashboard; draft.pollName is the survey's own name. Without venueId the survey goes to the organization's default venue, or to the key's venue for a venue key.

Draft fields

Field Required Meaning
pollName yes Name of the survey
language yes Language code all texts are written in
welcomeTitle yes Headline of the start page
welcomeDescription no Text under the headline
startButtonText no Label of the start button
questions yes The questions, in order
endTitle no Headline of the end page
endMessage no Text on the end page

Question kinds

Every question has a kind and a text, and optionally a subtitle.

kind Asks for Extra fields
rating A rating on a scale ratingSymbol: star, heart, thumbs_up, smiley or number; ratingLevels: 3 to 10, default 5
choice One or more of a list of options options: at least two labels; multipleChoice: true to allow several; exclusiveOptions: labels that rule out every other answer, like "None of these"
nps Net Promoter Score, 0 to 10 none
open_text Free text multiline: false for a single line
section Nothing; a heading between questions none

In a full modules body the same thing is exclusive: true on the option itself. A respondent who picks an exclusive option loses the other ticks, and picking another option clears the exclusive one.

An invalid draft answers 400 VALIDATION_FAILED with the message Invalid survey draft, and details.errors says which field is wrong. Nothing is created.

Publish it

A new survey is a draft that respondents can't open yet. Publish it with a separate call:

bash
curl -X PATCH "$SF_API/v1/surveys/$SURVEY_ID" \
  -H "Authorization: Bearer $SF_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "active": true }'

Publishing needs two things:

  • The person who created the API key has verified their email address. Otherwise the call answers 403 EMAIL_NOT_VERIFIED, with details.reason set to EMAIL_NOT_VERIFIED as well.
  • The plan has room for another active survey. Otherwise it answers 409 TIER_LIMIT_REACHED.

Once published, share its link or print QR codes.

Change a question

PATCH replaces every field you send as a whole, so change a question by editing the survey you read:

  1. Read the survey with GET /v1/surveys/$SURVEY_ID.
  2. Change what you need in its modules array, for example a question's text.
  3. Send the whole array back:
bash
curl -X PATCH "$SF_API/v1/surveys/$SURVEY_ID" \
  -H "Authorization: Bearer $SF_KEY" \
  -H "Content-Type: application/json" \
  -d @modules.json

where modules.json is { "modules": [ ... ] } with all pages. Keep the id of every question you don't mean to replace: responses refer to questions by id, so a question with a new id starts without answers.

Change the settings

settings holds the survey's name and languages (general), how it is shown (display) and how often a respondent may answer (participation). Like modules, it is replaced as a whole and validated as a whole: read it, change a field, and send all of it back.

json
{
  "settings": {
    "general": { "active": false, "pollName": "Workshop feedback", "languages": ["en"], "defaultLanguage": "en" },
    "display": {
      "pageMode": "one_page",
      "theme": { "font": "Inter", "colorScheme": "system" },
      "showProgressBar": true,
      "showQuestionNumbers": true
    },
    "participation": { "repeatParticipation": "daily", "allowModuleBack": true, "allowQuestionBack": true }
  }
}

A settings object with parts missing answers 400 VALIDATION_FAILED.

Setting Values
display.pageMode one_page, one_page_per_module, one_page_per_question
display.pagePerSection true: each section starts a page with its questions; otherwise one per page
participation.repeatParticipation always, once, daily, weekly, monthly: how often one device may answer
participation.accessMode open (or missing): anyone with the link; code: only with an unused single-use code

daily, weekly and monthly count 24 hours, 7 days and 30 days from the device's last response.

branding sets the bar above and below every page. Each has a mode: default shows the Simple Feedback bar, custom shows your text, links and logo, hidden shows nothing. surface tints the bar with default, tinted, accent or bold, a colour role from the survey's theme. The full shape is in the API reference and, for agents, in the MCP resource simplefeedback://schema/survey-branding.

For a logo, upload the image first. This needs the scope files:write:

bash
curl -X POST "$SF_API/v1/images" \
  -H "Authorization: Bearer $SF_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"kind\": \"survey_logo\", \"fileName\": \"logo.png\", \"imageBase64\": \"$(base64 -w0 logo.png)\"}"
json
{
  "id": "3dea5e0b-2c14-42a5-85fc-386b84768671",
  "kind": "survey_logo",
  "width": 400,
  "height": 400
}

The image is PNG, JPEG or WebP and at most 2 MB. Then put the id into the header:

bash
curl -X PATCH "$SF_API/v1/surveys/$SURVEY_ID" \
  -H "Authorization: Bearer $SF_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "branding": {
      "header": {
        "mode": "custom",
        "logoAssetId": "3dea5e0b-2c14-42a5-85fc-386b84768671",
        "text": { "en": "Visitor survey" },
        "surface": "tinted"
      },
      "footer": {
        "mode": "custom",
        "text": { "en": "Thank you for your time." },
        "links": [{ "id": "web", "label": { "en": "Our website" }, "url": "https://example.com", "icon": "web" }],
        "showPoweredBy": true
      }
    }
  }'

The same id works as a start page's logoAssetId. Upload with "kind": "survey_background" for a page's background.backgroundImageAssetId. Images count against your plan's storage, and an image that no survey refers to within 24 hours is deleted.

Delete it

bash
curl -X DELETE "$SF_API/v1/surveys/$SURVEY_ID" -H "Authorization: Bearer $SF_KEY"

The answer is 204. The survey and its link stop working at once, and it can't be restored.

Limits

Your plan limits how many surveys can be active and how many pages and languages a survey may have. A create or change that goes over a limit answers 409 TIER_LIMIT_REACHED and changes nothing. Custom branding needs a plan that includes it, otherwise 403 FEATURE_NOT_IN_TIER. An image upload over the plan's storage answers 403 TIER_LIMIT_REACHED. All codes are in Errors.