Forms
Build and embed signup forms that automatically subscribe contacts to your mailing lists
Forms capture leads directly from your website or landing page. When someone submits a form, they are created (or updated) as a subscribed contact and, if configured, added to an audience segment.
Authentication
The management endpoints use session (cookie-based) authentication and are intended for dashboard use — they do not accept API keys. The public submit endpoint requires no authentication. Base URL: https://api.misar.io/mail.
Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
GET | /api/forms | session | List forms |
POST | /api/forms | session | Create form |
GET | /api/forms/:id | session | Get form |
PATCH | /api/forms/:id | session | Update form |
DELETE | /api/forms/:id | session | Delete form |
GET | /api/forms/:id/embed | session | Get embed snippet |
GET | /api/forms/:id/submissions | session | List submissions |
POST | /api/public/forms/:id/submit | None | Submit a form (public) |
Field definitions
A form's fields array defines the inputs it renders. Each field is:
idstringbodyrequiredUnique field key (1–100 chars). Submissions are keyed by this id.
typeemail | text | first_name | last_name | phone | custombodyrequiredField type. A form must include at least one email field.
labelstringbodyrequiredDisplay label (1–200 chars).
requiredbooleanbodyrequiredWhether the field must be filled.
placeholderstringbodyOptional placeholder text (max 200 chars).
The settings object controls behaviour: success_message, redirect_url, add_to_list_id (a segment UUID to add subscribers to), and double_optin.
List forms
/mail/api/formsList all forms for the authenticated account, newest first.
Response fields
successbooleantrue when the request succeeded.
dataArray<Form>Each form includes id, name, description, is_active, submission_count, created_at, and updated_at.
curl https://api.misar.io/mail/api/forms \
-H "Cookie: session=..."{
"success": true,
"data": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Newsletter signup — homepage",
"description": null,
"is_active": true,
"submission_count": 312,
"created_at": "2026-05-27T10:00:00Z",
"updated_at": "2026-05-27T10:00:00Z"
}
]
}Create a form
/mail/api/formsCreate a new signup form. The fields array must contain 1–20 fields including at least one email field. Subject to your plan's form quota.
Request body
namestringbodyrequiredInternal name (1–255 chars).
descriptionstringbodyMax 1000 characters.
fieldsarraybodyrequired1–20 field definitions (see Field definitions).
settingsobjectbody{ success_message?, redirect_url?, add_to_list_id?, double_optin? }. add_to_list_id is the UUID of a segment to add subscribers to.
Response fields
successbooleantrue when the form was created.
dataobjectThe created form (id, name, description, is_active, fields, settings, submission_count, timestamps).
curl -X POST https://api.misar.io/mail/api/forms \
-H "Cookie: session=..." \
-H "Content-Type: application/json" \
-d '{
"name": "Newsletter signup — homepage",
"fields": [
{ "id": "email", "type": "email", "label": "Email address", "required": true },
{ "id": "first_name", "type": "first_name", "label": "First name", "required": false }
],
"settings": {
"success_message": "Thank you for subscribing!",
"redirect_url": "https://yoursite.com/thank-you",
"add_to_list_id": "b2c3d4e5-f6a7-8901-bcde-f23456789012"
}
}'{
"success": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Newsletter signup — homepage",
"description": null,
"is_active": true,
"fields": [],
"settings": {},
"submission_count": 0,
"created_at": "2026-05-27T10:00:00Z",
"updated_at": "2026-05-27T10:00:00Z"
}
}Get a form
/mail/api/forms/:idReturns the full form object.
Path parameters
idstringpathrequiredUUID of the form to retrieve.
curl https://api.misar.io/mail/api/forms/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Cookie: session=..."Update a form
/mail/api/forms/:idSend only the fields you want to change. Passing fields replaces the full array. Use is_active to activate or deactivate the form.
Path parameters
idstringpathrequiredUUID of the form to update.
Request body
namestringbody1–255 characters.
descriptionstringbodyMax 1000 characters (nullable).
fieldsarraybodyReplacement field definitions (1–20).
settingsobjectbody{ success_message?, redirect_url?, add_to_list_id?, double_optin? }.
is_activebooleanbodyActivate or deactivate the form.
curl -X PATCH https://api.misar.io/mail/api/forms/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
-H "Cookie: session=..." \
-H "Content-Type: application/json" \
-d '{ "name": "Newsletter signup — footer" }'Delete a form
/mail/api/forms/:idDelete a form.
Path parameters
idstringpathrequiredUUID of the form to delete.
Response fields
successbooleantrue when the form was deleted.
{ "success": true }Get the embed snippet
/mail/api/forms/:id/embedReturns a ready-to-paste embed snippet. The script tag loads the form widget for the given form.
Path parameters
idstringpathrequiredUUID of the form.
Response fields
successbooleantrue when the request succeeded.
embedCodestringThe <script> tag to paste into your page.
{
"success": true,
"embedCode": "<script src=\"https://mail.misar.io/api/embed/form/a1b2c3d4-e5f6-7890-abcd-ef1234567890\" async></script>"
}List submissions
/mail/api/forms/:id/submissionsList the submissions for a form, newest first.
Path parameters
idstringpathrequiredUUID of the form.
Query parameters
pageintegerquerydefault: 1Page number.
limitintegerquerydefault: 20Results per page (max 100).
Response fields
successbooleantrue when the request succeeded.
dataArray<Submission>Each submission includes id, form_id, data (the raw submitted key/value record), contact_id, ip_address, submitted_at, and a joined contacts object (email, first_name, last_name).
paginationobjectpage, limit, total, and totalPages.
curl "https://api.misar.io/mail/api/forms/a1b2c3d4-e5f6-7890-abcd-ef1234567890/submissions?limit=50" \
-H "Cookie: session=..."{
"success": true,
"data": [
{
"id": "5f6a7b8c-9d0e-1234-abcd-ef5678901234",
"form_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": { "email": "user@example.com", "first_name": "Alex" },
"contact_id": "c1a2b3c4-d5e6-7890-abcd-ef1234567890",
"ip_address": "203.0.113.0",
"submitted_at": "2026-05-26T14:22:00Z",
"contacts": { "email": "user@example.com", "first_name": "Alex", "last_name": null }
}
],
"pagination": { "page": 1, "limit": 50, "total": 312, "totalPages": 7 }
}Public form submit
/mail/api/public/forms/:id/submitNo authentication required. Called by the embed script or your own frontend. The request body is a flat key/value object keyed by each field's id (max 20 keys, each value ≤ 1000 chars) — there are no fixed email/firstName keys. The endpoint validates required fields, creates or updates the contact, optionally adds them to the form's segment, and records the submission.
Path parameters
idstringpathrequiredUUID of the form being submitted.
Request body
A flat object of { "<field id>": "<value>" }. The value of the field whose type is email becomes the contact's email (required). Fields typed first_name / last_name populate the contact name.
Response fields
successbooleantrue when the submission was recorded.
messagestringThe form's configured success message (defaults to "Thank you for subscribing!").
curl -X POST https://api.misar.io/mail/api/public/forms/a1b2c3d4-e5f6-7890-abcd-ef1234567890/submit \
-H "Content-Type: application/json" \
-d '{ "email": "user@example.com", "first_name": "Alex" }'{
"success": true,
"message": "Thank you for subscribing!"
}If the email already exists, the submission is recorded and the contact's name is refreshed (only while they are subscribed). New emails are created as subscribed contacts with source: "form". Submitting to a deactivated form returns 410.
Status codes
| Code | Meaning |
|---|---|
200 | Request succeeded (submit / list / delete) |
201 | Form created |
400 | Validation failed, invalid form ID, or missing/invalid email |
401 | Not authenticated (management endpoints) |
402 | Form quota reached for your plan |
404 | Form not found |
410 | Form is no longer active (public submit) |
413 | Submission payload too large |
429 | Rate limit exceeded |