alchemer_tools
Alchemer API wrapper module for managing survey data and interactions with the Alchemer platform.
Requires: - databricks-sdk - dbutils (Databricks utilities) - pandas (for some operations)
Author: Gino F. Fazzi, gino.franco.fazzi@audienceproject.com
alchemer_tools._read_alchemer_resource(filename)
Read a text resource bundled with the alchemer_utils package.
Package resources work both from the source tree and from an installed wheel, including on Databricks clusters where library files live under an ephemeral site-packages directory.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Name of the resource file inside |
required |
Returns:
| Type | Description |
|---|---|
str
|
File contents decoded as UTF-8. |
alchemer_tools.AlchemerAPIError
Bases: RuntimeError
Raised when Alchemer accepts a request but reports it as unsuccessful.
Alchemer signals application-level failures by returning HTTP 200 with
result_ok set to false in the response body, so these never surface as
requests.HTTPError. Catch this to handle a rejected operation (an unknown
survey ID, an invalid option payload); catch requests.HTTPError to handle
a transport or status-code failure.
alchemer_tools._question_title(question, language='English', clean=False)
Return a question's or option's title in language.
Alchemer returns title either as a language-keyed mapping or, for some
endpoints, as a plain string. Both forms are accepted. When the requested
language is absent, the first available translation is used so that
single-language surveys still resolve.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
question
|
dict[str, Any]
|
Alchemer question or survey-option record. |
required |
language
|
str
|
Preferred title language. |
'English'
|
clean
|
bool
|
If True, strip HTML markup from the result. Title lookups enable this so that a caller-supplied plain-text title can match Alchemer's marked-up one. It stays off by default because callers that turn titles into DataFrame column names must preserve Alchemer's exact text. |
False
|
Returns:
| Type | Description |
|---|---|
str or None
|
The resolved title, or |
alchemer_tools.AlchemerAPI
Client for retrieving and managing surveys through the Alchemer API.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_token
|
Alchemer API token used to authenticate requests. |
required | |
api_token_secret
|
Secret paired with |
required | |
region
|
Alchemer service region. Supported values are |
'US'
|
Notes
The client maintains a reusable HTTP session with retries for transient failures. Credentials are included in the request parameters sent to Alchemer; they are not logged by this class.
Methods follow a three-tier naming convention:
__name
Raw transport. Builds the URL and parameters, calls Alchemer, and returns
the decoded JSON envelope unchanged. No pandas, no business rules.
_name
Internal parsing or business helper. Pure — never calls the API.
name
Public, documented API. Composes the two tiers above and returns a
business object such as a DataFrame, a list, or an ID.
The name therefore tells you what you get back: a __ method always
returns Alchemer's raw envelope, a public method always returns parsed data.
alchemer_tools.AlchemerAPI.__init__(api_token, api_token_secret, region='US')
Initialize an Alchemer client with API credentials and a region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_token
|
Alchemer API token. |
required | |
api_token_secret
|
Alchemer API token secret. |
required | |
region
|
Alchemer data-center region, which selects the API base URL. |
'US'
|
Notes
Credentials are stored privately and sent as query parameters on every request. Keep them in Databricks secrets rather than notebook literals.
alchemer_tools.AlchemerAPI.__build_session()
staticmethod
Create a reusable HTTP session for paginated Alchemer API calls.
Returns:
| Type | Description |
|---|---|
Session
|
Session whose adapter retries GET and POST up to three times with exponential backoff on 429, 500, 502, 503, and 504 responses. Reusing one session keeps connections pooled across paginated requests. |
alchemer_tools.AlchemerAPI.__set_params()
Configure the API session parameters from the current client state.
alchemer_tools.AlchemerAPI.set_api_token(api_token)
Update the Alchemer API token used for subsequent requests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_token
|
Alchemer API token to store on this client. |
required |
Returns:
| Type | Description |
|---|---|
None
|
This method updates the client in place. |
Notes
Updating the token also refreshes the internal request parameters used by the client's API calls.
alchemer_tools.AlchemerAPI.set_api_token_secret(api_token_secret)
Update the API token secret used for subsequent requests.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
api_token_secret
|
Alchemer API token secret to store on this client. |
required |
Returns:
| Type | Description |
|---|---|
None
|
This method updates the client in place and refreshes its internal request parameters. |
alchemer_tools.AlchemerAPI.set_region(region)
Select the Alchemer regional API endpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
region
|
Region code, case-insensitively matching |
required |
Returns:
| Type | Description |
|---|---|
None
|
This method updates |
Raises:
| Type | Description |
|---|---|
KeyError
|
If |
alchemer_tools.AlchemerAPI.__request(method, path, *, extra_params=None, timeout=DEFAULT_TIMEOUT, check_result_ok=True)
Send one authenticated request to Alchemer and decode the JSON envelope.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
method
|
str
|
HTTP verb to use, for example |
required |
path
|
str
|
API path appended to the region base URL, for example
|
required |
extra_params
|
dict[str, Any] | None
|
Endpoint-specific query parameters merged over the client's authentication parameters. The client's parameters are copied, never mutated. |
None
|
timeout
|
int
|
Per-request timeout in seconds. |
DEFAULT_TIMEOUT
|
check_result_ok
|
bool
|
If True, treat a false |
True
|
Returns:
| Type | Description |
|---|---|
dict
|
Raw JSON-decoded response envelope. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
JSONDecodeError
|
If the response body is not valid JSON. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__iter_pages(path, *, extra_params=None, timeout=DEFAULT_TIMEOUT)
Yield each page envelope of a paginated endpoint, starting at page 1.
Alchemer reports total_pages on every page, so the page count is only
known after the first request. Callers that need just part of the result
may stop iterating early and no further requests are made — this is what
lets title lookups return as soon as they find a match.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
API path appended to the region base URL. |
required |
extra_params
|
dict[str, Any] | None
|
Endpoint-specific query parameters. A |
None
|
timeout
|
int
|
Per-request timeout in seconds. |
DEFAULT_TIMEOUT
|
Yields:
| Type | Description |
|---|---|
dict
|
Raw JSON-decoded envelope for one page, in page order. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__collect_pages(path, *, extra_params=None, timeout=DEFAULT_TIMEOUT)
Return one envelope whose data concatenates every page's records.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
path
|
str
|
API path appended to the region base URL. |
required |
extra_params
|
dict[str, Any] | None
|
Endpoint-specific query parameters. |
None
|
timeout
|
int
|
Per-request timeout in seconds. |
DEFAULT_TIMEOUT
|
Returns:
| Type | Description |
|---|---|
dict
|
Raw envelope carrying the last page's metadata and the combined
|
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__survey_path(survey_id=None)
staticmethod
Return the API path for the account's survey list, or one survey.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. Omit it for the account-wide survey list. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
|
alchemer_tools.AlchemerAPI.__question_path(survey_id, question_id=None)
staticmethod
Return the API path for a survey's questions, or one question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
question_id
|
Alchemer question ID. Omit it for every question in the survey. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The survey-question collection path, with the question ID appended when one is given. |
alchemer_tools.AlchemerAPI.__response_path(survey_id, response_id=None)
staticmethod
Return the API path for a survey's responses, or one response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
response_id
|
Alchemer response ID. Omit it for every response in the survey. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The survey-response collection path, with the response ID appended when one is given. |
alchemer_tools.AlchemerAPI.__option_path(survey_id, question_id, option_id=None)
classmethod
Return the API path for a question's survey options, or one option.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID that owns the options. |
required | |
option_id
|
Alchemer survey-option ID. Omit it for every option on the question. |
None
|
Returns:
| Type | Description |
|---|---|
str
|
The survey-option collection path, with the option ID appended when one is given. |
alchemer_tools.AlchemerAPI.__get_survey_responses(survey_id, order_by='date_submitted', start_date=None)
Return every page of a survey's responses merged into one raw envelope.
Wraps GET /v5/survey/{survey_id}/surveyresponse.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
order_by
|
str
|
Alchemer sort field. Prefix with |
'date_submitted'
|
start_date
|
str | None
|
Optional inclusive lower bound on |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope; |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__get_survey_options(survey_id, question_id)
Return every page of a question's survey options as one raw envelope.
Wraps GET
/v5/survey/{survey_id}/surveyquestion/{question_id}/surveyoption.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID whose options are requested. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope; |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__get_survey_option(survey_id, question_id, option_id)
Return the raw envelope for one survey option.
Wraps GET
/v5/survey/{survey_id}/surveyquestion/{question_id}/surveyoption/{option_id}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope; |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__create_survey_option(survey_id, question_id, option_data)
Create a survey option and return the raw envelope.
Wraps PUT
/v5/survey/{survey_id}/surveyquestion/{question_id}/surveyoption.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID that will contain the new option. |
required | |
option_data
|
dict[str, Any]
|
Option parameters sent in the request query string. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope describing the created option. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__update_survey_option(survey_id, question_id, option_id, option_data)
Update a survey option and return the raw envelope.
Wraps POST
/v5/survey/{survey_id}/surveyquestion/{question_id}/surveyoption/{option_id}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to update. |
required | |
option_data
|
dict[str, Any]
|
Replacement option parameters sent in the request query string. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope describing the updated option. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__delete_survey_option(survey_id, question_id, option_id)
Delete a survey option and return the raw envelope.
Wraps DELETE
/v5/survey/{survey_id}/surveyquestion/{question_id}/surveyoption/{option_id}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to delete. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope confirming the deletion. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__delete_survey(survey_id)
Delete a survey and return the raw envelope.
Wraps GET /v5/survey/{survey_id} with Alchemer's _method=DELETE
override rather than a real DELETE verb, matching the request this client
has always sent for this endpoint.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID to delete. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope confirming the deletion. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.__move_survey_to_folder(survey_id, folder_id)
Move a survey into a folder and return the raw envelope.
Wraps POST /v5/survey/{survey_id}. The redundant _method=POST
override is preserved because it is what this client has always sent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID to update. |
required | |
folder_id
|
Destination folder ID. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Raw response envelope describing the updated survey. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI._titles_by_question_id(questions, language='English')
staticmethod
Map each question ID to its title, preserving Alchemer's order.
Does not call the API. Titles keep their original markup because callers turn them into DataFrame column names.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
questions
|
list[dict[str, Any]]
|
Question records, each carrying |
required |
language
|
str
|
Preferred title language. |
'English'
|
Returns:
| Type | Description |
|---|---|
dict
|
Question ID to title. Questions with no title at all are omitted. |
alchemer_tools.AlchemerAPI._append_answer_column(row_values, column, value, answer_id)
staticmethod
Store one answer in row_values under a column name unique to the row.
Does not call the API. Mutates row_values in place. Two questions can
share a label within a single response, so a colliding name is suffixed
with the answer ID to keep every answer addressable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
row_values
|
dict[str, Any]
|
Accumulator for the response currently being flattened. |
required |
column
|
Preferred column name. |
required | |
value
|
Answer value to store. |
required | |
answer_id
|
Alchemer answer ID used to disambiguate a colliding column name. |
required |
alchemer_tools.AlchemerAPI._append_subquestion_columns(row_values, parent_question, subquestions)
Store a parent question's shown subquestion answers in row_values.
Does not call the API. Mutates row_values in place. Alchemer returns
subquestions in two shapes: a flat record carrying its own type, or a
mapping of option ID to option record. Both are handled here.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
row_values
|
Accumulator for the response currently being flattened. |
required | |
parent_question
|
Title of the parent question, used to build the column name. |
required | |
subquestions
|
The parent question's |
required |
alchemer_tools.AlchemerAPI._responses_to_dataframe(response_data, question_ids_by_title, status_flag='all', debug=False)
staticmethod
Reduce raw response records to one column per requested question title.
Does not call the API.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response_data
|
list[dict[str, Any]]
|
Raw response records, as found under a response envelope's |
required |
question_ids_by_title
|
dict[str, Any]
|
Question title to Alchemer question ID, for example
|
required |
status_flag
|
str
|
Response status to keep: |
'all'
|
debug
|
bool
|
If True, print filtering details. |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per kept response, with |
alchemer_tools.AlchemerAPI.get_surveys_list(timeout=60, newer_than=None)
Return the account's surveys as a DataFrame, newest pages first.
The statistics and links objects Alchemer nests in each record are
flattened into their own columns.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
timeout
|
int
|
Request timeout in seconds for each survey-list page. |
60
|
newer_than
|
datetime | None
|
If given, stop paging once a page's oldest survey predates this date. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per survey, with the nested statistics and links expanded. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If a survey-list request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
Notes
The newer_than cutoff assumes Alchemer returns surveys newest-first.
This client does not request an explicit order_by, so it relies on the
API's default ordering.
alchemer_tools.AlchemerAPI.get_survey_id_by_title(title, timeout=60, debug=False)
Return the survey ID for an exact Alchemer survey title.
The lookup scans survey-list pages until it finds a match, so a survey near the start of the list costs a single request. Matching is exact and case-sensitive.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
title
|
str
|
Exact survey title to find. |
required |
timeout
|
int
|
Request timeout in seconds for each survey-list page. |
60
|
debug
|
bool
|
If True, print page-level lookup details. |
False
|
Returns:
| Type | Description |
|---|---|
str
|
Alchemer survey ID. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no survey with the exact title is found. |
HTTPError
|
If a survey-list request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.delete_survey(survey_id, request_verification=True)
Delete a survey, optionally requesting interactive confirmation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID to delete. |
required | |
request_verification
|
bool
|
If True, prompt for confirmation and proceed only when the user enters
|
True
|
Returns:
| Type | Description |
|---|---|
dict or None
|
Alchemer's JSON response, or |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If the deletion request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.move_survey_to_folder(survey_id, folder_id)
Move a survey into an Alchemer folder.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID to update. |
required | |
folder_id
|
Destination folder ID. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
JSON response returned by Alchemer. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If the update request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.test()
Return the first raw survey-list page for a connectivity check.
Returns:
| Type | Description |
|---|---|
dict
|
Raw JSON payload from the Alchemer survey-list endpoint. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If the request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
Notes
This method is retained as a lightweight compatibility and debugging
helper. Use get_surveys_list for normal survey discovery. The 60 second
timeout is longer than the client default because listing surveys is slower
than the per-survey endpoints.
alchemer_tools.AlchemerAPI.get_survey_questions(survey_id, attributes=['id', 'base_type', 'type', 'title', 'options', 'show_rules_ids', 'sub_questions'])
Return selected fields for every question in a survey.
The method follows all pages of the Alchemer survey-question endpoint and preserves the API's question order.
Parameters
survey_id:
Alchemer survey ID.
attributes:
Question fields to include in each returned dictionary. Missing fields
are returned with a value of None.
Returns
list of dict One dictionary per survey question with the requested fields.
Raises
requests.HTTPError
If a survey-question request returns an unsuccessful HTTP status.
AlchemerAPIError
If Alchemer reports result_ok false.
alchemer_tools.AlchemerAPI.get_question_ids_by_titles(survey_id, question_titles, language='English', debug=False)
Return question IDs for the requested question titles.
Looks up survey questions by their localized title and returns a dictionary mapping each requested title to its Alchemer question ID. Missing titles are skipped. If a question does not have a title for the requested language, the first available title value is used as a fallback.
Titles are compared verbatim, including any HTML markup Alchemer returns.
Use get_question_id_by_title to match against plain text instead.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
question_titles
|
list[str]
|
Question titles to search for. |
required |
language
|
str
|
Title language to match. |
'English'
|
debug
|
bool
|
If True, print lookup details for troubleshooting. |
False
|
Returns:
| Type | Description |
|---|---|
dict
|
Title to question ID, for example |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If a survey-question request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
Examples:
>>> client.get_question_ids_by_titles(12345, ["How old are you?"])
{'How old are you?': '123'}
alchemer_tools.AlchemerAPI.get_question_id_by_title(survey_id, question_title, language='English', debug=False)
Return the ID of the question whose plain-text title matches.
HTML markup is stripped from Alchemer's titles before comparing, so
question_title should be given as plain text. Pages are fetched only
until a match is found.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
question_title
|
str
|
Plain-text question title to find. |
required |
language
|
str
|
Title language to match. |
'English'
|
debug
|
bool
|
If True, print each title evaluated during the lookup. |
False
|
Returns:
| Type | Description |
|---|---|
str or None
|
Alchemer question ID, or |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If a survey-question request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.get_survey_options(survey_id, question_id)
Return every survey option belonging to a question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID whose options are requested. |
required |
Returns:
| Type | Description |
|---|---|
list of dict
|
Survey-option records from all pages, in Alchemer's order. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.get_survey_option(survey_id, question_id, option_id)
Return a specific survey option.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to retrieve. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Survey-option record. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.get_survey_option_id_by_title(survey_id, question_id, option_title, language='English', debug=False)
Return the ID of the survey option whose plain-text title matches.
HTML markup is stripped from Alchemer's titles before comparing, so
option_title should be given as plain text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_title
|
str
|
Plain-text title of the survey option to find. |
required |
language
|
str
|
Language of the option title to match. |
'English'
|
debug
|
bool
|
If True, print each option title evaluated during the lookup. |
False
|
Returns:
| Type | Description |
|---|---|
int or None
|
Survey-option ID, or |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
Examples:
>>> client.get_survey_option_id_by_title(12345, 67, "Prefer not to say")
10045
alchemer_tools.AlchemerAPI.create_survey_option(survey_id, question_id, option_data)
Create a new survey option for a specific question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID that will contain the new option. |
required | |
option_data
|
dict[str, Any]
|
Option parameters sent in the request query string. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Full API response describing the created survey option. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
ValueError
|
If |
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.update_survey_option(survey_id, question_id, option_id, option_data)
Update an existing survey option for a specific question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to update. |
required | |
option_data
|
dict[str, Any]
|
Replacement option parameters sent in the request query string. Only the fields present are changed. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Full API response describing the updated survey option. |
Raises:
| Type | Description |
|---|---|
TypeError
|
If |
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.delete_survey_option(survey_id, question_id, option_id)
Delete a survey option from a specific question.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID containing the question. |
required | |
question_id
|
Alchemer question ID containing the option. |
required | |
option_id
|
Alchemer survey-option ID to delete. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Full API response confirming the deletion. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If Alchemer returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
alchemer_tools.AlchemerAPI.get_filtered_survey_responses(survey_id, question_titles, language='English', status_flag='all', debug=False)
Return survey responses reduced to the requested question titles.
The returned DataFrame includes one row per response, a response_id
column, and one column for each requested question title that was found in
the survey. Missing question titles are skipped.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
question_titles
|
list[str]
|
Question titles to include as DataFrame columns. |
required |
language
|
str
|
Title language to match when resolving titles to IDs. |
'English'
|
status_flag
|
str
|
Response status filter: |
'all'
|
debug
|
bool
|
If True, print lookup and response filtering details. |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
|
Raises:
| Type | Description |
|---|---|
HTTPError
|
If a survey-question or survey-response request fails. |
AlchemerAPIError
|
If Alchemer reports |
Examples:
>>> client.get_filtered_survey_responses(
... 12345, ["How old are you?"], status_flag="Complete"
... )
alchemer_tools.AlchemerAPI.get_survey_responses_by_title(survey_name, start_date=None, debug=False, as_spark=False)
Return all responses for an exact survey title as a DataFrame.
This is a convenience wrapper around get_survey_responses with
formatted="default". The returned DataFrame includes response metadata
and flattened answers for questions that were shown in each response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_name
|
str
|
Exact Alchemer survey title to retrieve. |
required |
start_date
|
str | None
|
Optional inclusive lower bound for |
None
|
debug
|
bool
|
If True, print lookup details while resolving the survey title. |
False
|
as_spark
|
bool
|
If True, return a Spark DataFrame instead of a pandas DataFrame. |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame or DataFrame
|
Response metadata plus flattened survey answer columns. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no survey with the exact title is found. |
alchemer_tools.AlchemerAPI.get_survey_responses(survey_id, start_date=None, formatted='default')
Return all responses for a survey, formatted or raw.
The raw payload is also cached on self.raw_survey_responses under
survey_id so it can be inspected after a formatting failure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
survey_id
|
Alchemer survey ID. |
required | |
start_date
|
str | None
|
If given, only responses submitted at or after this moment are
retrieved, formatted as |
None
|
formatted
|
bool | Literal['default', 'synpop']
|
|
'default'
|
Returns:
| Type | Description |
|---|---|
DataFrame or dict
|
A DataFrame for either formatted mode; the raw envelope when
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
FileNotFoundError
|
If |
RuntimeError
|
If a response cannot be mapped onto the synthetic-population schema. |
HTTPError
|
If a survey-response request returns an unsuccessful HTTP status. |
AlchemerAPIError
|
If Alchemer reports |
Examples:
>>> client.get_survey_responses(12345) # flattened
>>> client.get_survey_responses(12345, formatted="synpop") # SynPop schema
>>> client.get_survey_responses(12345, formatted=False) # raw envelope
alchemer_tools.AlchemerAPI._synpop_responses_to_dataframe(raw_survey_responses)
Map complete responses onto the synthetic-population schema.
Does not call the API. Partial responses are skipped, because the SynPop
mappings assume every question was reached. Column order follows the
bundled col_order.txt when present, with any unlisted columns appended.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
raw_survey_responses
|
dict[str, Any]
|
Raw response envelope as returned by the survey-response endpoint. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
One row per complete response, in synthetic-population schema. |
Raises:
| Type | Description |
|---|---|
FileNotFoundError
|
If the bundled |
RuntimeError
|
If a response cannot be resolved through the mappings. |
alchemer_tools.AlchemerAPI.format_default_response(response, survey_id)
Flatten a raw survey-response payload into a pandas DataFrame.
Response metadata is retained, while shown survey answers become columns.
Parent-question options, including nested subquestion options, use
"option:question" column names. Flat subquestions use
"subquestion:parent question" names. When answer labels collide, the
answer ID is appended to keep names unique.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Raw Alchemer response payload containing a |
required | |
survey_id
|
Survey ID used to retrieve question titles for parent questions. |
required |
Returns:
| Type | Description |
|---|---|
DataFrame
|
Response metadata and flattened answer columns, with one row per response. |
Raises:
| Type | Description |
|---|---|
HTTPError
|
If retrieving the survey's question metadata fails. |
KeyError
|
If required response or question fields are missing. |
alchemer_tools.AlchemerAPI.format_synpop_response(response, main_mappings)
Map one raw survey response to the synthetic-population schema.
The method copies response metadata, ignores questions that were not shown, and applies the configured mappings for hidden values, text boxes, checkboxes, subquestions, and radio questions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
One Alchemer response dictionary containing metadata and
|
required | |
main_mappings
|
Mapping configuration keyed by Alchemer question and answer IDs. The input is deep-copied before dynamic piping information is added. |
required |
Returns:
| Type | Description |
|---|---|
dict
|
Flattened response ready to become a synthetic-population DataFrame record. |
Raises:
| Type | Description |
|---|---|
RuntimeError
|
If one or more shown answers cannot be resolved through the supplied mappings. All answers are inspected before the collected errors are raised. |
alchemer_tools.AlchemerAPI.execute_finecast_extract(s3_base_path=f's3://ap-synthetic-population/dev/raw_data/surveys/finecast_surveys', finecast_survey_ids={'GB': 8344353, 'DE': 7636573}, logger=None, file_extension='parquet')
Extract the given Finecast surveys and save each to S3.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
s3_base_path
|
str
|
Base S3 prefix. Each country is written to
|
f's3://ap-synthetic-population/dev/raw_data/surveys/finecast_surveys'
|
finecast_survey_ids
|
dict
|
Mapping of country code to Finecast survey ID. |
{'GB': 8344353, 'DE': 7636573}
|
logger
|
Optional logger. Progress is logged only when one is supplied. |
None
|
|
file_extension
|
Output format, either |
'parquet'
|
Returns:
| Type | Description |
|---|---|
None
|
Extracts are written to S3 rather than returned. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If |
Notes
Every column is cast to string before writing, so downstream readers must handle their own type conversion. Parquet output overwrites the target path.
alchemer_tools.AlchemerAPI.execute_synpop_extract(countries=None, s3_base_path='s3://ap-synthetic-population/raw_data/surveys/synpop_surveys', synpop_identifier='Synthetic', logger=None, list_of_surveys=None, legacy_version_files=None, file_extension='parquet')
Extract SynPop surveys per country and save each to S3.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
countries
|
list | None
|
Optional country codes to keep. Surveys are matched by title substring. When omitted, every discovered SynPop survey is extracted. |
None
|
s3_base_path
|
str
|
Base S3 prefix for the written extracts. |
's3://ap-synthetic-population/raw_data/surveys/synpop_surveys'
|
synpop_identifier
|
str
|
Substring identifying a SynPop survey by title. |
'Synthetic'
|
logger
|
Optional logger. Progress is logged only when one is supplied. |
None
|
|
list_of_surveys
|
Optional pre-fetched surveys list. When omitted, surveys created after 2025-12-01 are listed from the API. |
None
|
|
legacy_version_files
|
Optional mapping used to also write legacy-format copies. |
None
|
|
file_extension
|
Output format, either |
'parquet'
|
Returns:
| Type | Description |
|---|---|
None
|
Extracts are written to S3 rather than returned. |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If |