Forms
Create embeddable signup forms that capture contacts, apply tags, add to lists, and enroll in sequences automatically.
Overview
Forms let you collect email subscribers directly from your website without writing backend code. Each form has a unique slug and can be shared as a hosted page (/f/{slug}) or embedded via iframe. When a visitor submits a form, PushMail automatically creates or updates the contact and runs any configured auto-actions (tagging, list assignment, sequence enrollment).
The form object
{
"id": 1,
"orgId": 1,
"siteId": 1,
"name": "Newsletter Signup",
"slug": "a1b2c3d4e5f6",
"designJson": "{...}",
"status": "active",
"sequenceId": 3,
"listId": 1,
"tags": "[\"newsletter\"]",
"notifyEmail": "leads@yourdomain.com",
"notifySubject": null,
"doubleOptIn": false,
"submissionCount": 142,
"createdAt": "2026-03-01T10:00:00.000Z",
"updatedAt": "2026-03-01T10:00:00.000Z"
}Status values
| Status | Description |
|---|---|
draft | Form is being designed, not publicly accessible |
active | Form is live and accepting submissions |
archived | Form is disabled and no longer accepting submissions |
List forms
GET /v1/forms
Returns all forms for the authenticated organization. Optionally filter by site.
| Parameter | Type | Description |
|---|---|---|
siteId | integer | Filter forms by site ID (query parameter) |
curl https://pushmail.dev/api/v1/forms?siteId=1 \
-H "Authorization: Bearer pm_live_YOUR_KEY"{
"data": {
"forms": [
{ "id": 1, "name": "Newsletter Signup", "slug": "a1b2c3d4e5f6", "status": "active", "submissionCount": 142, "..." : "..." }
]
}
}Create a form
POST /v1/forms
| Parameter | Type | Description |
|---|---|---|
siteIdrequired | integer | The site this form belongs to |
namerequired | string | Display name for the form (max 200 chars) |
designJson | string | JSON string of form design (fields, styles, settings) |
sequenceId | integer | null | Sequence to auto-enroll contacts in on submission |
listId | integer | null | List to add contacts to on submission |
tags | string[] | Tag names to apply to contacts on submission |
notifyEmail | string | null | Email this address on each submission (Reply-To is the submitter). Null disables. |
notifySubject | string | null | Subject for the notification email (default: "New {form name} submission") |
doubleOptIn | boolean | Require email confirmation before subscribing (default: false) |
curl -X POST https://pushmail.dev/api/v1/forms \
-H "Authorization: Bearer pm_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"siteId": 1,
"name": "Newsletter Signup",
"listId": 1,
"tags": ["newsletter"]
}'{
"data": {
"form": {
"id": 1,
"slug": "a1b2c3d4e5f6",
"name": "Newsletter Signup",
"status": "draft",
"..." : "..."
}
}
}A random 16-character hex slug is generated automatically. Use this slug to build the public form URL: https://pushmail.dev/f/{slug}.
Get a form
GET /v1/forms/:id
curl https://pushmail.dev/api/v1/forms/1 \
-H "Authorization: Bearer pm_live_YOUR_KEY"Update a form
PUT /v1/forms/:id
| Parameter | Type | Description |
|---|---|---|
name | string | Update display name |
designJson | string | Update form design JSON |
status | string | Set status: draft, active, or archived |
sequenceId | integer | null | Update sequence auto-enrollment |
listId | integer | null | Update list auto-assignment |
tags | string[] | Update auto-applied tags |
notifyEmail | string | null | Update the submission-notification address (null disables) |
notifySubject | string | null | Update the notification email subject |
doubleOptIn | boolean | Toggle double opt-in |
curl -X PUT https://pushmail.dev/api/v1/forms/1 \
-H "Authorization: Bearer pm_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "status": "active" }'Delete a form
DELETE /v1/forms/:id
Deleting a form also deletes all its submissions (cascade).
curl -X DELETE https://pushmail.dev/api/v1/forms/1 \
-H "Authorization: Bearer pm_live_YOUR_KEY"List submissions
GET /v1/forms/:id/submissions
Returns paginated submissions for a form.
| Parameter | Type | Description |
|---|---|---|
page | integer | Page number (default: 1) |
limit | integer | Items per page (default: 50, max: 100) |
curl https://pushmail.dev/api/v1/forms/1/submissions?page=1&limit=20 \
-H "Authorization: Bearer pm_live_YOUR_KEY"{
"data": {
"submissions": [
{
"id": 1,
"formId": 1,
"contactId": 42,
"siteId": 1,
"data": "{\"email\":\"jane@example.com\",\"firstName\":\"Jane\"}",
"ipAddress": "203.0.113.1",
"userAgent": "Mozilla/5.0 ...",
"createdAt": "2026-03-05T14:30:00.000Z"
}
],
"pagination": { "page": 1, "limit": 20, "total": 1, "totalPages": 1 }
}
}Public submission endpoint
POST /v1/forms/:id/submit
This endpoint is public (no authentication required) and processes form submissions from your website visitors.
The endpoint:
- Looks up the form by ID and verifies it is
active - Parses submitted field values and maps them to contact fields using the form's
designJson - Creates or updates the contact (upsert by email within the site)
- Applies configured tags, list membership, and sequence enrollment
- Sends a notification email if
notifyEmailis set (see Submission notifications) - Records the submission and increments the form's submission counter
- Rate limited to 10 submissions per IP per minute
- Returns CORS headers for cross-origin embedding
curl -X POST https://pushmail.dev/api/v1/forms/1/submit \
-H "Content-Type: application/json" \
-d '{ "email": "jane@example.com", "firstName": "Jane" }'{
"data": {
"success": true,
"message": "Thanks for submitting!"
}
}Submission notifications
Set notifyEmail on a form to have PushMail email that address every time the
form is submitted. This is how you route form submissions into a shared inbox
or helpdesk.
The notification is a plain operational email — no unsubscribe footer, no
open/click tracking. Critically, its Reply-To is the person who submitted
the form, so replying to the notification from your inbox reaches the
submitter directly. The From display name is {submitter} via {form name},
and the body lists every submitted field.
curl -X PUT https://pushmail.dev/api/v1/forms/1 \
-H "Authorization: Bearer pm_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "notifyEmail": "leads@yourdomain.com" }'Set notifySubject to override the default subject (New {form name} submission). Sending the notification consumes one email credit and uses the
organization's sending config, so its From domain must be a verified sending
domain. A notification failure never blocks the submission itself.
Notifications can also be configured per form in the dashboard form editor via the Notifications button in the toolbar.
Hosted form page
Each form with an active status is accessible at:
https://pushmail.dev/f/{slug}This serves a standalone HTML page with the rendered form. The page is fully styled based on the form's designJson settings and submits to the public submission endpoint via JavaScript.
You can also embed the hosted page in your site with an iframe:
<iframe src="https://pushmail.dev/f/a1b2c3d4e5f6"
style="width:100%;border:none;min-height:500px;"
loading="lazy"></iframe>Campaigns
Campaigns are one-off email broadcasts sent to a list or tagged group of contacts. Schedule them for later or send immediately.
Sending
PushMail sends emails via 10 supported providers. Use our managed infrastructure or bring your own API key for full control over your sending domain and reputation.