Build a survey with its questions through the API
You can build a survey and its questions entirely through the API. Create the survey and its questions in one request, add more questions later, and remove the ones you no longer need.
You need an API token to call these endpoints. API access is on Solo and above. See Authentication for how to create a token and send it, and Getting Started with the API if this is your first call. Your token needs the surveys:write scope to create a survey and to publish it, elements:write to add or remove questions, and elements:read to list a survey’s questions.
Create a survey with its questions
Section titled “Create a survey with its questions”- Send a
POSTrequest to/api/v1/surveyswith the survey’s details, as you would for an empty survey. - Add an optional
questionslist to the request. Each item in the list describes one question. - Read the response.
data.questionslists each question in the order you sent it, with its newelementId. Keep these ids if you may want to remove a question later.
If you leave questions out, you get an empty survey, as before.
The list is all or nothing. SurveyRock checks the whole list first, and if any question is refused, no survey is created. You can send up to 100 questions in one request.
Here is a request that creates a survey with a rating question and an open-text question:
curl https://app.surveyrock.com/api/v1/surveys \ -H "Authorization: Bearer srk_live_..." \ -H "Content-Type: application/json" \ -d '{ "name": "Customer satisfaction", "questions": [ { "type": "rating_scale", "text": "How easy was it to get started?", "required": true }, { "type": "text_input", "text": "What could we do better?" } ] }'The response gives each question’s id and the text respondents will see:
{ "success": true, "data": { "surveyId": "mv99t7e6HFj3SfPq", "name": "Customer satisfaction", "questions": [ { "elementId": "mv99t7grUE5iYMcR", "type": "rating_scale", "text": "How easy was it to get started?" }, { "elementId": "mv99t7gr2vhyQ3Qf", "type": "text_input", "text": "What could we do better?" } ] }}The response also carries other fields, such as createdAt and meta. They’re left out here.
What each question takes
Section titled “What each question takes”| Field | Needed | What it does |
|---|---|---|
type |
Yes | One of text_input, multiple_choice, rating_scale, matrix, slider, nps, yes_no, email, date, ranking, file_upload. |
text |
Yes | The question as respondents read it, up to 5,000 characters. |
helpText |
No | Guidance shown under the question. |
required |
No | true if a respondent must answer. Defaults to false. |
choices |
No | The answer options, up to 50, for multiple_choice and ranking. |
multipleAnswers |
No | For multiple_choice: let respondents pick more than one. |
rows |
No | For matrix and slider: the statements to rate, up to 50. |
columns |
No | For matrix: the answer columns, up to 10. Leave it out for the standard scale. |
subject |
No | For nps only: who or what is being recommended, such as “our support team”. |
pageTitle |
No | Starts a new page at this question, with this title. |
Each question comes out as the survey editor would make it for that type, with that type’s defaults. A field the type doesn’t use is ignored. A field SurveyRock doesn’t know is refused.
An NPS question always asks the standard sentence about its subject (“How likely is it that you would recommend us to a friend or colleague?”), so its text isn’t shown to respondents. The response gives the text respondents will see.
Dropdown questions aren’t available through the API.
The full field list, with limits, is in the OpenAPI schema at GET /api/v1/schema.
Add questions to an existing survey
Section titled “Add questions to an existing survey”- Send a
POSTrequest to/api/v1/surveys/{id}/questions, where{id}is the survey’s id. - Put the new questions in a
questionslist, described the same way as above. The list needs at least one question. - Choose where they go:
- No
pageId: the questions are added at the end of the survey. - With
pageId: the questions are added at the end of the page you name. - With
pageTitleon a question: that question starts a new page with that title.
- No
{ "questions": [ { "type": "yes_no", "text": "Can we contact you?", "pageTitle": "Follow-up" } ]}The response gives each new question’s elementId and the pageId it landed on.
To find a page’s id, list the survey’s questions with GET /api/v1/surveys/{id}/elements. The response is a list of questions in order, and each carries a page_id.
pageTitle is refused when pageId names a page that isn’t the last one, because a new page always starts at the end of the survey.
Questions are only ever added after the last question of the survey or of the page you name. You can’t insert a question in the middle of a page, and you can’t move a question once it’s added.
Adding questions isn’t idempotent. Send an Idempotency-Key header with your request, so that a retry doesn’t add the questions twice. A retry with the same key and the same body replays the first response.
Remove a question
Section titled “Remove a question”- Send a
DELETErequest to/api/v1/elements/{id}, where{id}is theelementIdyou got when you created or added the question. - What happens next depends on whether anyone has answered it:
- Nobody has answered it: the question is deleted for good.
- It has responses: the question is retired. It leaves the survey, and it and its answers stay in your results.
The response says which one happened:
{ "success": true, "data": { "elementId": "mv99t7gr2vhyQ3Qf", "retired": false, "responses": 0 } }retired is true when the question had answers, and responses is how many.
Skip logic that pointed at the question is cleaned up, and the rest of the page closes up. A question that a page loop takes its items from is refused until the loop no longer uses it.
Plan limits
Section titled “Plan limits”Your plan sets how many questions one survey can hold. A request that would take a survey past that limit is refused with a 403 and the error code quota_exceeded, and nothing is created or added. The error’s details give the limit, the number requested and the plan that allows more.
Publish the changes
Section titled “Publish the changes”Everything on this page changes the survey’s draft. If the survey is already published, respondents keep seeing the live version until you publish again. Republish the survey, in SurveyRock or with POST /api/v1/surveys/{id}/publish, to make your changes live.
Publishing through the API doesn’t create a link to share. A survey with no active link is live, but nobody can answer it yet. The publish response tells you this in data.sharing, and the next step is to create a web link with POST /api/v1/distribution/surveys/{surveyId} and activate it with POST /api/v1/distribution/{id}/activate. See Publishing and your first responses for what publishing does and how links work.
Example
Section titled “Example”You’re setting up a customer satisfaction survey from your own system.
- You
POSTto/api/v1/surveyswith the survey’s details and aquestionslist holding a rating question and an open-text “What could we do better?” question. The response returns anelementIdfor each question. - Later you decide to add a short follow-up on a new page. You
POSTto/api/v1/surveys/{id}/questionswith one question that has apageTitle. It lands at the end of the survey, on a new page with that title. - After the survey has been live for a week, you want to drop the open-text question. You
DELETEit by itselementId. Because it has responses, it’s retired and the answers you’ve already collected stay in your results. - You republish the survey so respondents see the updated version.
The same operations are available to Claude through the connector. See Use SurveyRock from Claude.
Troubleshooting
Section titled “Troubleshooting”A new question doesn’t appear for respondents. The change is in the draft. Republish the survey.
I can’t add a question in the middle of a page. New questions go at the end of the survey or at the end of the page you name with pageId. Inserting mid-page isn’t available through the API.
I can’t move a question. Moving questions isn’t available through the API.
A dropdown question is refused. You get a 422 saying the question type can’t be created this way. Use one of the other types, or add the dropdown question in the survey builder.
The request is refused with a 422. The response names each question at fault. Check its type against the list above, and that it has no fields SurveyRock doesn’t know. The message lists the fields it does know.
The request is refused with quota_exceeded. The survey would hold more questions than your plan allows. Send fewer questions, or move to a plan with a higher limit.
I deleted a question but its answers are still in my results. That’s intended. A question with responses is retired, not erased, so the answers you collected aren’t lost.
Deleting a question a second time fails. Once a question is removed it can’t be removed again. A retired question returns a 404. A question that was deleted for good returns a 403, the same as an id your token can’t see.
The request is refused with another error. Check the response body against Error Format. If you see a rate-limit response, see Rate Limits. If the token is rejected, see Authentication.