MailZeno Forms
Build hosted forms, embed them on any website, and accept secure submissions through MailZeno.
MailZeno Forms supports:
- Hosted form pages (
/f/:slug) - Short links (
/s/:code) - No-code iframe embeds
- Script-based auto-submit integration
- Public API key or slug-based submission
- Conditional fields and schema validation modes
- Built-in rate limiting and spam honeypot
Forms workflow
Go to your dashboard, create a form, and configure fields/settings.
Use hosted page, embed script, or direct SDK/script submit.
Share the hosted URL, short link, or embed snippet.
Submissions are validated, rate-limited, and stored with metadata.
Hosted form URL
Each form automatically gets a public URL:
https://mailzeno.dev/f/<form-slug>And an optional short URL:
https://mailzeno.dev/s/<short-code>Embed form (no code backend)
Use the embed endpoint in any HTML page:
<div data-mailzeno-form="your-form-slug" data-height="680px"></div>
<script src="https://mailzeno.dev/api/v1/forms/embed/your-form-slug" async></script>This renders an iframe-hosted form inside your page.
Script + form slug integration
For native HTML forms, load the forms script and tag your form:
<script src="https://mailzeno.dev/mz.forms.js?v=2.2.0" defer></script>
<form
data-mz-form-slug="your-form-slug"
data-mz-public-key="fpk_your_public_key_optional"
data-mz-success-message="Thanks. We received your request."
>
<input name="name" required />
<input name="email" type="email" required />
<!-- add only schema fields in strict mode -->
<button type="submit" data-loading-text="Submitting...">Submit</button>
</form>
<p data-mz-success hidden></p>
<p data-mz-error hidden></p>If you want to self-host from your app domain, use:
<script src="https://mailzeno.dev/mz.forms.js?v=2.2.0" defer></script>data-mz-public-key is optional when using slug-based submit. If present, it is validated.
API endpoints
Public endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/forms/:slug | Fetch public form schema and public-safe settings |
POST | /api/v1/forms/submit/:slug | Submit form data using slug route |
POST | /api/v1/forms/public/submit | Submit form data using slug or public key in body/header |
GET | /api/v1/forms/embed/:slug | Serve hosted iframe embed script |
GET | /api/v1/forms/sdk | Serve loader script for forms SDK |
Authenticated dashboard endpoints
| Method | Path | Purpose |
|---|---|---|
GET | /api/v1/forms | List your forms |
POST | /api/v1/forms | Create a form |
DELETE | /api/v1/forms | Delete a form |
PATCH | /api/v1/forms | Regenerate public API key |
GET | /api/v1/forms/manage/:id | Fetch form for editing |
PATCH | /api/v1/forms/manage/:id | Update schema/settings |
Submission payload
For direct submit endpoints, send JSON body data by field name:
{
"name": "Aman",
"email": "aman@example.com",
"message": "Need pricing details"
}Or for POST /api/v1/forms/public/submit, send explicit identifiers:
{
"form_slug": "contact-us",
"data": {
"name": "Aman",
"email": "aman@example.com",
"message": "Need pricing details"
}
}{
"public_api_key": "fpk_xxxxx",
"data": {
"name": "Aman",
"email": "aman@example.com"
}
}Schema modes
Forms support two schema modes:
strict: unknown fields are rejectedflexible: unknown fields are accepted and stored as top-level keys (original field names)
Use strict for controlled integrations and flexible for evolving forms.
Security and anti-abuse
MailZeno Forms includes:
- Origin allowlist support (
allowed_origins) - Field-level validation (required/type/options)
- Honeypot spam field (
company) - Per-form + IP rate limiting
- Public-safe settings exposure in public schema endpoint
Never place secrets in frontend form markup. Public form keys are intended to be public identifiers, not private credentials.
Rate limiting
Forms use the same plan-aware limiter as API traffic with a dedicated form scope. Exceeding limit returns:
- HTTP
429 X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-ResetRetry-After(when applicable)
See Rate Limits for details.
Common errors
| Status | Code | Meaning |
|---|---|---|
400 | validation_error | Required field missing or invalid field value |
400 | unknown_field | Extra field rejected in strict schema mode |
400 | spam_detected | Honeypot field was filled |
401 | invalid_public_api_key | Provided public key is invalid |
403 | origin_not_allowed | Request origin is not allowed for this form |
404 | form_not_found | Form slug/key does not exist or inactive |
429 | rate_limited | Too many submissions from same source |