PushMail.dev

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\"]",
  "doubleOptIn": false,
  "submissionCount": 142,
  "createdAt": "2026-03-01T10:00:00.000Z",
  "updatedAt": "2026-03-01T10:00:00.000Z"
}

Status values

StatusDescription
draftForm is being designed, not publicly accessible
activeForm is live and accepting submissions
archivedForm is disabled and no longer accepting submissions

List forms

GET /v1/forms

Returns all forms for the authenticated organization. Optionally filter by site.

ParameterTypeDescription
siteIdintegerFilter forms by site ID (query parameter)
Request
curl https://pushmail.dev/api/v1/forms?siteId=1 \
  -H "Authorization: Bearer pm_live_YOUR_KEY"
Response
{
  "data": {
    "forms": [
      { "id": 1, "name": "Newsletter Signup", "slug": "a1b2c3d4e5f6", "status": "active", "submissionCount": 142, "..." : "..." }
    ]
  }
}

Create a form

POST /v1/forms

ParameterTypeDescription
siteIdrequiredintegerThe site this form belongs to
namerequiredstringDisplay name for the form (max 200 chars)
designJsonstringJSON string of form design (fields, styles, settings)
sequenceIdinteger | nullSequence to auto-enroll contacts in on submission
listIdinteger | nullList to add contacts to on submission
tagsstring[]Tag names to apply to contacts on submission
doubleOptInbooleanRequire email confirmation before subscribing (default: false)
Request
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"]
  }'
Response (201)
{
  "data": {
    "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

Request
curl https://pushmail.dev/api/v1/forms/1 \
  -H "Authorization: Bearer pm_live_YOUR_KEY"

Update a form

PUT /v1/forms/:id

ParameterTypeDescription
namestringUpdate display name
designJsonstringUpdate form design JSON
statusstringSet status: draft, active, or archived
sequenceIdinteger | nullUpdate sequence auto-enrollment
listIdinteger | nullUpdate list auto-assignment
tagsstring[]Update auto-applied tags
doubleOptInbooleanToggle double opt-in
Request
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).

Request
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.

ParameterTypeDescription
pageintegerPage number (default: 1)
limitintegerItems per page (default: 50, max: 100)
Request
curl https://pushmail.dev/api/v1/forms/1/submissions?page=1&limit=20 \
  -H "Authorization: Bearer pm_live_YOUR_KEY"
Response
{
  "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
  • 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
Request
curl -X POST https://pushmail.dev/api/v1/forms/1/submit \
  -H "Content-Type: application/json" \
  -d '{ "email": "jane@example.com", "firstName": "Jane" }'
Response
{
  "data": {
    "success": true,
    "message": "Thanks for submitting!"
  }
}

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>

On this page