Quick Summary: A survey is one run of a survey template against a population of people. A template with its questions can be created over the API (
POST /api/v1/survey-templates) or in the app; the API creates runs from a template version, manages who receives them, drives the lifecycle, and reads the results.Attributes
Templates
A run points at a template version, so a brand-new company needs a template before its first survey.
Create takes the template’s
name, an optional description and visibility (visible_to_all — the default — or private), and its questions in order. Each question is { name, text, type, responseRequired?, allowsMultipleResponses?, options? }; type is one of rating, text, multiple_choice, drop_down. Choice questions need at least two options ({ "label": "HQ" }); rating and text questions take none. The response carries latestVersion.id — the value to send as templateVersionId when creating a survey — and the questions in the same shape GET /surveys/{id}/questions returns. The list shows each template’s newest version with questions: null; the single read includes them. Editing a template (which cuts a new version) is done in the app.
Lifecycle
draft → scheduled → launched → ended, with cancelled reachable before ending. The transitions are explicit operations, and an out-of-order call answers a 409 conflict describing the required state:
POST /api/v1/surveys/{id}/schedule— set a future launch time on a draft; re-scheduling is allowed while the current time is still more than an hour away.POST /api/v1/surveys/{id}/launch— launch now: the population is materialised into participants and notified. A survey nobody would receive is a 409.POST /api/v1/surveys/{id}/end— close a launched survey to further responses.POST /api/v1/surveys/{id}/cancel— cancel a run.POST /api/v1/surveys/{id}/nudge— remind everyone who has not completed; answers 202, the reminders send asynchronously.
Population
The population is defined while the survey is a draft (or still more than an hour from a scheduled launch), and materialised at launch:GET /api/v1/surveys/{id}/scope— the definition:toAllPeople, the nine org-dimension id lists,personIds(named individuals),excludedPersonIds. State ids appear read-only.PUT /api/v1/surveys/{id}/scope— replace the definition. TurningtoAllPeopleoff and namingpeoplescopes the run to exactly those individuals.POST /api/v1/surveys/{id}/exclusions/DELETE …/exclusions— exclude named individuals from any population, or lift the exclusion. Refused once launched.
personId and the email.
Reading a run
GET /api/v1/surveys— paginated, filterable bystatus(public values above), name and dates.GET /api/v1/surveys/{id}— one run.GET /api/v1/surveys/{id}/questions— the pinned question set:{ id, name, text, description, version, type, responseRequired, allowsMultipleResponses, options }withtypeone ofmultiple_choice,drop_down,rating,text,document_upload,certification_update.GET /api/v1/surveys/{id}/people— participants withperson {id, name, email},status(assigned,in_progress,completed,archived), how each was included (all_people,org_schema,manual), and timestamps.GET …/people/{person}reads one participation; the person slot takes an email or the opaque id.
Scopes
Reads requiresurveys:read; every write requires surveys:write. Employee-bound credentials are read-only apart from submitting their own responses.