Form handling
Para provides HTML form handling and sending emails from structured form submissions in two modes:
- Authenticated direct API calls to
POST /v1/_emails(without CAPTCHA) - Public HTML form submissions to
POST /v1/_forms/{appid}/{formid}(CAPTCHA configuration required)
Public form submissions are configured through the form object and can:
- enforce CAPTCHA validation
- send notifications to a predefined recipient list (max 10 emails per request)
- optionally store submitted messages
- optionally redirect the browser after submission
- control whether the message body is treated as plain text, raw HTML, or Markdown-rendered HTML
Authenticated email sending does not require a stored Form object. The client provides the recipients and
content formatting flags directly in the request payload.
The public /v1/_forms/{appid}/{formid} URL is used only after a new form object has been created in Para through the standard object API.
Once created, the form has an id and a computed formActionURI which can be used directly as the HTML form action URL.
The form object
Section titled “The form object”The form object is defined in para-core > Form.java and configures the behavior of a public email form.
Fields
Section titled “Fields”| Field | Type | Required | Notes |
|---|---|---|---|
id | String | yes | Used as {formid} in the public endpoint. |
appid | String | yes | Used as {appid} in the public endpoint. |
name | String | no | Used as a prefix in the outgoing email subject for public forms. |
captchaSecretKey | String | yes | Secret used to verify CAPTCHA responses. |
notifyEmails | String[] | yes | Destination email addresses for public submissions. Limited to 10 recipients. |
messageStorageEnabled | boolean | no | When true, successful submissions are stored as Sysprop objects. Default: false. |
plaintextOnly | boolean | no | When true, HTML is stripped from the message body. Default: true. |
markdownEnabled | boolean | no | Enables Markdown-to-HTML conversion, but only when plaintextOnly is false. Default: false. |
redirectTo | String | no | Optional absolute URL to redirect the browser to after submission. |
Form action URL
Section titled “Form action URL”The public submission URL generated by Form.getFormActionURI() is:
/v1/_forms/{appid}/{formid}Creating a public HTML form
Section titled “Creating a public HTML form”Before the public endpoint can be used, create a Form object through the standard Para object API:
POST /v1/formExample payload:
{ "type": "form", "name": "My Website Contact Form", "captchaSecretKey": "YOUR_CAPTCHA_SECRET_KEY", "messageStorageEnabled": false, "plaintextOnly": false, "markdownEnabled": true, "redirectTo": "https://yoursite.com/thanks-page"}After creation, the stored object can be referenced by:
id, for example123456formActionURI, for example/v1/_forms/myapp/123456
After the form has been created, configure the client-side HTML and CAPTCHA scripts.
<form action="https://paraio.com/v1/_forms/myapp/123456" method="post" enctype="multipart/form-data"> <input type="text" name="name" required> <input type="email" name="email"> <input type="text" name="subject"> <textarea name="message" required></textarea> <input type="file" name="file"> <input type="hidden" name="cf-turnstile-response" value="TOKEN_FROM_WIDGET"> <!-- Cloudflare Turnstile widget --> <div class="cf-turnstile" data-sitekey="YOUR_TURNSTILE_SITE_KEY"></div> <button type="submit">Send</button></form>The endpoint is public and does not require authentication. It is intended only for browser-based HTML forms or
other unauthenticated clients submitting multipart/form-data. Request behavior:
- The target
formobject is loaded by{appid}and{formid}. - The field
notifyEmailsreplaces any recipient list from the incoming request. plaintextOnlyandmarkdownEnabledreplace any formatting flags from the incoming request.- CAPTCHA verification is required before sending the email.
- If sending succeeds and the form is configured with
messageStorageEnabled: truethe submitted messages are stored as Para objects with typeformdata
Supported CAPTCHA services:
- reCAPTCHA v3
- hCaptcha
- Cloudflare Turnstile
The client is expected to render and complete a CAPTCHA challenge before submitting the form. The resulting token must be submitted with the form request. The server accepts any one of the following request parameters:
g-recaptcha-responseh-captcha-responsecf-turnstile-response
The verification target is selected automatically based on which parameter is present.
If you want to allow Markdown formatting in the message body, set plaintextOnly: false and markdownEnabled: true on your Form object.
By default, Para will simply treat each message as plain text and strip all HTML tags from it.
Optionally, you can enable HTML tags in the form body with plaintextOnly: false and markdownEnabled: false.
Comparison table
| Feature | Public endpoint /v1/_forms | API endpoint /v1/_emails |
|---|---|---|
| Authentication | None (CAPTCHA required) | API key / signed request |
| Request content type | multipart/form-data | application/json |
| CAPTCHA | Required | Not required |
| Recipients | Set on Form object | Set in request payload |
| File attachment | Yes | Yes (base64 data URI) |
| Message storage | Optional via Form | No |
| Redirect | Optional via Form | No |