The Web Service block lets a survey call an external HTTP API in the middle of the flow. Use it to push responses out to another system (a CRM, an automation tool, a webhook) or to pull data back into the survey and save it to variables.
Add it from the Flow tab, click Add a New Element Here, and pick Web Service. Then configure it in the block's panel. It sits alongside branches, randomizers, and end-of-survey elements in the Flow Editor.
Requests always run on our server. The respondent's browser never makes the outbound call and never sees your secrets. Private and loopback addresses are rejected.
You can open the short in-product version of this guide any time: Flow tab, select the Web Service block, then click Guide in the panel header.
The editor at a glance#
The panel is grouped into cards:
- Request with Method, Endpoint URL, Query parameters, and Headers.
- Request body, shown only for
POST/PUT/PATCH. - Authentication, where secrets are entered inline.
- Response, with Fire and forget, Save response fields to variables, and Send a test request.
- Advanced, with Timeout (ms), Retries, and failure handling.
There is no saved-credential store. You supply secrets inline on the block, or reference a global variable, and they are added to the request on the server.
Configuration reference#
| Setting | Notes |
|---|---|
| Method | GET / POST / PUT / PATCH / DELETE. |
| Endpoint URL | The endpoint to call. May contain tokens in the path or query, but not in the host. See Security. |
| Query parameters | Appended to the URL. Values support tokens. Add parameter adds a row. |
| Headers | Any request headers you need. Values support tokens. |
| Request body | Only for POST / PUT / PATCH. Modes are listed below. |
| Authentication | No authentication, Basic (username & password), API key, or Bearer token. Secrets are entered inline or referenced from a global variable. There is no native OAuth flow. |
| Fire and forget | When ticked, the survey does not wait for a reply and response mapping is hidden. Good for "notify and move on". |
| Save response fields to variables | Maps a field in the JSON reply to a survey global variable. Hidden while Fire and forget is on. |
| Timeout (ms) | 500 to 20000, with a 20 second hard cap. |
| Retries | 0 to 3, and only on 5xx, 429, or a network error. A 4xx is not retried. |
| Continue the survey if this request fails | When unticked, a failed call that is not fire-and-forget stops the survey. |
Request body modes#
| Mode | What it sends |
|---|---|
| Don't send a body | No body. |
| Build fields (recommended) | Only the rows you add, wrapped in the response envelope described below. |
| Send all answers | The whole response envelope, covering every answered question. |
| Write raw JSON (advanced) | A raw JSON body you author, with tokens substituted. |
| Send as form data | key=value pairs sent as form data. |
In Build fields (recommended), each row has a field-name box on the left (its placeholder reads Field name (e.g. email)) and a Value (type or insert) box on the right. Add field adds another row. The dropdown above the rows, + Add a whole question (sends its full answer)…, adds a row pre-filled with a question's full answer.
Inserting dynamic values#
Anywhere a value is accepted, including the Endpoint URL, query parameters, headers, Build fields values, form data values, raw JSON, and the authentication secrets, there is a small green variable icon button. It opens the same insert menu used in question text and logic, so you insert the same tokens the same way:
| Token | Resolves to |
|---|---|
${gv://Field/name} | a global variable |
${q://QID/SelectedValue} and other sub-keys | a question's answer |
${m://ResponseID} and other metadata | session metadata, listed below |
${m://…} metadata (filled by the server)#
The browser cannot see server-side data, so these are filled by the server:
| Token | Value |
|---|---|
${m://ResponseID} | the response or session id |
${m://SurveyID} | the survey id |
${m://RecipientEmail} | the respondent's email on non-anonymous surveys, empty otherwise |
${m://StartDate}, ${m://EndDate}, ${m://Duration} | response timestamps |
${m://IPAddress}, ${m://UserAgent} | stored request metadata |
${m://DisplayLanguage} | the response language |
Valid JSON reminder: in the raw JSON body, wrap string tokens in quotes. Write
{"email": "${m://RecipientEmail}"}, not{email: ${m://RecipientEmail}}.
The response envelope (Send all answers and Build fields)#
Both Send all answers and Build fields (recommended) ship the same JSON envelope, so the receiving system sees one stable shape:
{
"surveyId": "SV_abc123",
"sessionId": "RSP_xyz789",
"recipientEmail": "[email protected]",
"submittedAt": "2026-07-14T12:00:00Z",
"values": { "Q1": 2, "Q9_1": 3, "NPS_Score": 9 },
"labels": { "Q1": "Option 2", "Q9_1": "Disagree", "NPS_Score": 9 },
"questions": { "Q1": "Pick one", "Q9": "Rate the statements", "NPS_Score": "How likely?" },
"choices": { "Q1": { "2": "Option 2" }, "Q9": { "1": "Statement 1" } }
}
valuesholds the machine codes: choice, row and column recode values, numbers, or text, keyed by a stable export tag (matrix rows astag_row, grid cells astag_row_col, multi-answer as an array). Unanswered questions are left out.labelsholds the readable text, keyed the same way asvalues.questionsholds the question wording as plain text.choicesholds, per choice-based question,{ recode: label }for the selected options.surveyId,sessionIdandsubmittedAtare stamped by the server.recipientEmailis added only for non-anonymous responses.
Variables: with Send all answers, every global variable is folded into labels, and an answer with the same key wins. With Build fields (recommended) the payload is filtered to the rows you add, so reference a variable explicitly with ${gv://Field/name} if you want it included.
The snapshot is assembled when the block fires, so place the block where you want that snapshot taken, usually near the end of the flow.
Authentication#
| Type | Fields | Sent as |
|---|---|---|
| No authentication | none | nothing |
| Basic (username & password) | Username, Password | an Authorization header using Basic auth |
| Bearer token | Token | an Authorization header using a Bearer token |
| API key | API key, then either Send in a header or Send in the query string, plus a name box for the header or parameter (its placeholder reads X-API-Key) | a header or a query parameter |
Every secret box is masked, with an eye button beside it that toggles between Show secret and Hide secret.
A blank secret means nothing is attached. Any secret can itself be a ${gv://Field/name} token, so it is not hard-coded in the survey.
OAuth is not supported natively, so there is no token endpoint or automatic refresh. If you already hold an access token, paste it into Token under Bearer token, optionally via a variable. A client-credentials flow can be approximated with two chained blocks: fetch the token, save access_token to a variable, then send ${gv://Field/access_token} from the second block.
Pulling data back (response to variables)#
For lookups such as enrichment or eligibility, leave Fire and forget unticked:
- Configure a
GETorPOSTto the API. - Click Send a test request. The button reads Testing… while it runs, then lists the reply's fields underneath. Test calls use sample metadata.
- Click a listed field to create a mapping for it, or click Add mapping under Save response fields to variables and fill the row yourself. The left box is the Response field, a JSON path such as the editor's own example
data.user.email, and the right one is Save to variable, which offers Select or create variable.
Mapped variables become survey global variables and can drive display logic, branching, quotas, piping into question text, and auto-answering a question, described below.
The block also writes status variables keyed by its Section Label, with spaces turned into underscores: ws_<label>_ok, ws_<label>_status, ws_<label>_error, and ws_<label>_response. Give each block a unique label if you need to inspect more than one.
Auto-answering a question from a mapped variable#
A mapped variable can pre-fill a question's answer so the respondent never sees the question. On the question's Logic tab:
- Under Auto-Answer Question Rules, click Add. A Rule 1 card appears.
- Click Configure on the card. In the Auto-Answer Question dialog, build the condition, for example your variable with the operator Is Not Empty.
- Back on the rule card, tick Override the default answer for this rule, then fill the answer box that appears. For a text question that box shows the placeholder Default answer text; use the variable icon button on it to insert
${gv://Field/name}.
When the variable is set, the question is hidden and recorded with the resolved value, not the literal token. When the variable is empty, the question is shown normally. If you leave the override unticked, the stored value may be blank, which the panel warns about on the card.
When the block runs (placement matters)#
Web Service blocks, like all flow blocks, run when the respondent completes the section just before the block in the flow. They do not run in the middle of a page and not any earlier. A block placed after Section 3 does not call the service until Section 3 is finished, so a pulled variable is available to questions in a later section, not to a question shown on the same first screen.
If you need the pulled data before the very first question, for example to skip it, give the survey a lead-in section such as a short welcome page, and put the consuming question in the next section. A block placed before the first section will not run until a section has been completed. Verify the end-to-end behaviour on the live survey link with a real session.
Chaining calls#
Several Web Service blocks in one flow step run in order, and each block's saved response variables feed the next block's tokens. So you can fetch an OAuth token in the first block, map access_token to a variable, and send ${gv://Field/access_token} as the Bearer secret in the second, all within the same navigation step. Fire-and-forget blocks return immediately and contribute no variables.
Walkthrough: send survey responses to a webhook#
Goal: POST answers to a webhook URL when the respondent reaches a point in the flow. Any service that gives you a webhook URL works the same way.
-
In the other system, create the webhook and copy its URL. The Endpoint URL box shows an example URL as its placeholder, so you can see the shape expected.
-
Add a Web Service block. Set Method to
POST, paste the webhook URL into Endpoint URL, leave Authentication on No authentication, and tick Fire and forget. -
Open Request body and choose Build fields (recommended). Add rows with Add field, putting the name on the left and a literal or an inserted token in Value (type or insert):
Field name Value email${m://RecipientEmail}on a non-anonymous survey, or a questionnpsadded from + Add a whole question (sends its full answer)…, picking your NPS question sourcesurvey-app, typed as a literal -
Optionally click Send a test request. The result line reads Success with the HTTP status, or Failed with the error. The receiving system should show the payload it got.
Test requests are not available while you are editing a template. The button is disabled and the panel says so. Create a survey from the template first.
Security and limits#
- Server-side only. The outbound request is made by our backend, not the browser, so respondents cannot see or tamper with your secrets.
- Internal hosts blocked. Private, loopback and internal addresses are rejected, and only
httpsis allowed. - The host is never templated. A token may appear in the path, query, headers or body, but not in the domain, so a respondent's answer can never redirect the call. On a cross-host redirect the credentials are stripped.
- Injection-safe. Token values are percent-encoded in URLs and JSON-escaped in raw bodies, so an answer cannot inject parameters or forge keys.
${m://…}metadata is filled by the server. - Inline or variable. Inline secrets are stored in the survey definition. Reference a global variable instead if that is a concern.
- Hard limits. A 20 second timeout, at most 3 retries, at most 3 redirects, a 256 KB reply cap, and per-session rate limiting.
Related guides#
- Flow Editor, the visual survey path where the block lives.
- Logic, Flow & Conditions, every logic feature and a learning path.
- Variables & Panel Redirects, the global variables the block reads and writes.
- Custom JS limits & security, when to use a Web Service block instead of custom JavaScript.
Was this page helpful?