

- Preparatory Chapter
- curl Chapter
- Python Chapter
- Pre-upload Chapter
- Error-handling Chapter
- Debug Chapter
- Continuous Execution Notes
- WordPress Form Chapter
- Google Apps Script Chapter
This article introduces a way to start a Case in Questetra BPM Suite by calling a [Message Start Event (HTTP)] from a form embedded in WordPress. Using a reference-implementation WordPress plugin called Case Starter Form, we’ll walk through both the setup steps and how it works internally, so you can see the behavior for yourself.
This plugin adopts a preset registry approach, which lets a single installation serve multiple Start Events (form) across different pages.
Like the curl edition and Python edition, this is one entry in the “Starting a Case from Outside Questetra BPM Suite” series, covering the pattern of starting a business process from an external web form.
This is a reference implementation (not an official plugin).
The plugin introduced in this article is a sample intended to demonstrate how it works. It is not provided or supported as an official plugin, and is MIT licensed software with no warranty. Please make sure you understand the content and use it at your own risk.
Repository: https://github.com/Questetra/wordpress-case-starter-form
When to Use This (and When to Use [Message Start Event (form)] Instead)
If you just need to start a Case from an external web form, first consider Questetra’s standard [Message Start Event (form)]. For most business scenarios, this is sufficient. The form can be designed and managed entirely within Questetra, with built-in support for mapping to data items, input validation, and multi-language support, all while keeping maintenance simple (see “Let’s Create Public Web Forms” in the intermediate section of this series).
The approach in this article — building the form on the WordPress side and starting the case over HTTP — is suited to a narrower set of situations where strong design control is required, such as marketing-oriented forms that need to blend seamlessly into the site’s design and branding.
Furthermore, if you’re planning full-scale, public-facing operation aimed at an unspecified number of general consumers, it’s more appropriate to combine this with a dedicated form-building service, from the standpoint of spam countermeasures and operational overhead.
One more point regarding response speed: in this setup, WordPress waits synchronously for its request to Questetra to complete before returning the completion screen, so response time is affected by the round trip to Questetra (some delay between submission and the completion display is likely). By contrast, many hosted form services return a completion response to the respondent immediately, while handling external integrations (such as webhooks) in the background — which is more favorable in terms of perceived speed for the respondent (in that case, the case in Questetra is started after the fact).
Overall Picture
[WordPress]
Input form (only the preset name is embedded in the page)
│ Submit (browser → own site)
▼
Plugin (server side)
│ Looks up endpoint/key from the preset name (registry lives server-side)
│ URL and API key are kept server-side only
│ POST as multipart/form-data
▼
[Questetra BPM Suite]
Message Start Event (HTTP)
│
▼
Case startedThe key point is that the browser does not send directly to Questetra; instead, WordPress (the server side) receives the submission first, and then forwards it to Questetra. This means the start URL and API key never appear in the browser (i.e., in the page source) at all, and the browser is not subject to CORS restrictions.
Design Invariants
This plugin is designed to uphold the following invariants.
Secrets and connection details (endpoint / key) stay in the preset registry — i.e., on the server side — and only the preset name is passed to the content layer (shortcode attributes).
endpoint(the start URL) andkey(the API key) cannot be specified via shortcode attributes.- Only the preset name appears in the browser (the page body); the server side looks up the actual values from the registry.
This allows editors working at the content layer (posts and pages) to place forms on any page without ever needing to touch the secrets.
Prerequisites (Preparation)
On the Questetra Side
- A workflow app containing a [Message Start Event (HTTP)] (an edition in which Message Start Event (HTTP) is available)
- That event’s start URL and API key (available on the app’s settings screen)
- The names and types of the incoming parameters (data items) you want to receive
For how to check the incoming parameters, please refer to the “Preparation” article in this series.
On the WordPress Side
- A WordPress environment where you can install a custom plugin is required.
- WordPress.com’s free plan does not allow custom plugins to be installed (available on all paid plans).
- If you just want to try it out locally, the Docker environment bundled with the repository (
example-docker/) or a local WordPress setup (Studio, Local, etc.) is a convenient option.
Setup Steps
1. Get the Plugin
Obtain the questetra-case-starter-form/ folder from the repository (https://github.com/Questetra/wordpress-case-starter-form).
2. Configure the Presets
Edit only the QSCF_PRESETS definition block at the top of questetra-case-starter-form/questetra-case-starter-form.php. Nothing below the ■■■ Logic body starts below ■■■ marker in the file needs to be edited (comments in the file indicate exactly where the configurable section ends). To add more forms, simply add more presets.
define( 'QSCF_PRESETS', array(
// preset name 'contact' (contact form)
'contact' => array(
'endpoint' => 'https://your-tenant.questetra.net/System/Event/MessageStart/0000/00/start',
'key' => 'PUT-YOUR-API-KEY-HERE', // ← replace with your own API key
'fields' => array(
array( 'param' => 'title', 'label' => 'Subject', 'type' => 'text', 'required' => false ),
array( 'param' => 'q_string0', 'label' => 'Name', 'type' => 'text', 'required' => true ),
array( 'param' => 'q_string1', 'label' => 'Inquiry details', 'type' => 'textarea', 'required' => true ),
array( 'param' => 'q_file11', 'label' => 'Attachment', 'type' => 'file', 'required' => true ),
),
'thanks' => 'Thank you for your inquiry.', // Optional. Uses a default message if omitted
'max_file_bytes' => 10 * 1024 * 1024, // Optional. Defaults to 10MB if omitted
),
// For each additional preset, just copy this block and change the name and contents
// 'apply' => array( ... ),
) );About the API Key
Write the target start event’s API key directly into key (replace PUT-YOUR-API-KEY-HERE with your own key). Since the request is sent from the server side, the key never appears in the page source. Even if you version-control the plugin, this is designed on the assumption that you’ll use a private repository, so writing the key directly is fine.
(Bonus) If you’re in an environment where you can edit wp-config.php, you can define the key there and reference it like 'key' => defined( 'QSCF_CONTACT_KEY' ) ? QSCF_CONTACT_KEY : '',, separating the key from the plugin body itself (useful if you’re managing things in a public repository, for example). However, since WordPress.com typically does not allow wp-config.php to be edited, use the direct-write approach above in that case.
Each Key Under fields
| Key | Description |
|---|---|
param | The name of the incoming parameter on the Questetra side (e.g., title / q_string0 / q_file11) |
label | The label displayed on screen |
type | text (single-line text) / textarea (multi-line text) / file (file) |
required | true makes the field required (for text/textarea, input is mandatory; for file, an attachment itself is mandatory). Optional if omitted |
Multiple files can always be attached. Count checks such as “at least N files” are handled by the data item settings on the Questetra side, and any resulting errors are displayed directly on the relevant field (the plugin itself has no rules regarding file counts).
3. Zip It Up, Upload, and Activate
Once configured, compress the questetra-case-starter-form/ folder into a ZIP file (with questetra-case-starter-form.php directly inside the folder). In the WordPress admin screen, go to [Plugins] → [Add New] → [Upload Plugin], upload that ZIP file, and activate “Questetra Case Starter Form (Reference).”
On WordPress.com (Business plan or above), in addition to ZIP upload, you can also deploy files via SFTP or GitHub integration, but ZIP upload is the simplest way to start. Since it may not be possible to edit the plugin’s source after uploading, be sure to finish the configuration (Step 2) before creating the ZIP file.
4. Embed the Form in a Page
In the body of any page or post, write a shortcode specifying the preset name.
[[qscf_form preset="contact"]]preset… the name of the preset to use (required; if omitted, the plugin looks for"default", and if that doesn’t exist either, a notice is shown only to administrators)thanks… overrides the success message on submission (optional). Example:[[qscf_form preset="contact" thanks="Your request has been received"]]endpoint,key, andfieldscannot be specified via shortcode attributes (per the invariants described above).
To place a different form on a different page, just add another preset and paste [[qscf_form preset="other-name"]].
Testing It Out
Open the published page, fill in the form, and submit it.
- If the input is valid, a case is started in Questetra, and the page displays a thank-you message along with the submitted content (including the ID of the case that was started).
- A record of the case being started also appears in the “Auto-Processing Log” for the target event, on the app settings screen in Questetra.
If there’s a problem with the input, an error message is displayed beneath the relevant field, and any values already entered are preserved (file fields, however, must be reselected due to browser limitations). Validation errors from the Questetra side (e.g., “Please attach 2 or more files”) are also displayed beneath the corresponding field.
How It Works
As a reference implementation, here are the key design points worth understanding.
Only the Preset Name Is Passed to the Content Layer
The form embeds only the preset name, in a hidden field. The server-side handler that receives the submission validates that preset name against an allow-list (checking whether it exists in QSCF_PRESETS), and if it’s registered, retrieves endpoint, key, and fields from the registry. The endpoint and key are never received from the browser.
Relaying Through the Server Side (Keeping the URL and Key Secret, No CORS Needed)
The form’s submission target is not Questetra, but WordPress’s admin-post.php (server-side processing). On the server side, the API key is attached to the start URL, and the request is sent to Questetra via wp_remote_post(). As a result, the start URL and API key are never passed to the browser, and the browser is not subject to CORS restrictions.
Sending Files Too, via multipart/form-data
Text fields are sent as regular form values, while file fields are sent as file parts of a multipart/form-data request, each under its incoming parameter name (param). When there are multiple files, they are sent repeatedly under the same parameter name.
Post / Redirect / Get (Preventing Duplicate Submissions)
Upon receiving a submission (POST), the result is first saved to temporary data (a transient), and the browser is redirected back to the original page carrying only a passphrase (a random token). When that page reloads (GET), the passphrase is used to retrieve the data, and the thank-you screen is rendered.
This approach provides the following benefits:
- It prevents resubmission (duplicate case creation) caused by reloading the completion screen
- Submitted content can be carried over without appearing in the URL (avoiding information exposure and URL clutter)
The temporary data is also tied to the preset name, so even if multiple forms are placed on the same page, they won’t be mixed up.
Per-Field Validation
In addition to the plugin’s own required-field checks, errors returned by Questetra (the <key> / <detail> in the XML response) are parsed, and messages are routed to whichever field’s incoming parameter name matches for display. Errors that aren’t tied to any particular field (such as a communication failure) are displayed together at the top of the form. Note that if the CSRF token has expired, the error page displays guidance to go back.
Supporting Multiple Forms
Because this plugin uses the preset registry approach, you can support multiple forms simply by adding presets to QSCF_PRESETS.
- To add a form with a different connection target or different fields → add one more preset (configuring
endpoint/key/fields) - Paste
[[qscf_form preset="preset-name"]]onto each respective page
With a single installation, you can run multiple start events — for inquiries, applications, and so on — on separate pages.
Notes and Limitations
- Spam prevention for public forms: If you’re placing this on a page anyone can access, consider adding countermeasures such as reCAPTCHA separately.
- Types of input fields: The three field types provided are
text(single line),textarea(multi-line), andfile. Since HTTP incoming parameters are always passed as strings, they can still be set on QBPMS numeric-type or date-type data items as long as the text input sends a value in the appropriate format (validity is checked on the Questetra side). On the other hand, dedicated input UIs such as dropdown selects or date pickers are not provided (though they could be added within the same framework if needed). - Per-field constraints are validated on the Questetra side: Field-level rules such as maximum character length or required file counts are validated by Questetra’s data item settings rather than by the plugin, and any resulting errors are displayed beneath the relevant field.
Summary
By calling a [Message Start Event (HTTP)] from a WordPress form, you can turn web-based intake — inquiries, applications, and the like — directly into a Questetra case. The reference implementation introduced in this article, Case Starter Form, serves as teaching material where you can see, all in one place, the key implementation points: supporting multiple forms via the preset registry approach, relaying through the server side, sending files, the completion screen, and per-field error display.
The plugin introduced in this article is a reference implementation (unofficial, MIT-licensed, no warranty, not supported).


