Documentation
Connect a form
Mailiy accepts form data via POST and emails it to your confirmed addresses. It accepts application/x-www-form-urlencoded, multipart/form-data and JSON (max. 128 KB, 50 fields).
Endpoint: https://v3.mailiy.com/api/submit
Instead of the access_key field you can also put the key in the URL: https://v3.mailiy.com/api/submit/YOUR-KEY
Websites and forms
In the dashboard you create a website first, then your forms inside it. The website's recipients, sender name, allowed domains and retention are the defaults for every new form. You can change them per form afterwards.
Your plan sets how many websites, deliveries per month and recipients per form you get. Deliveries count across all forms in your account and reset on the first of each month.
Sign-in and security
You sign in with email address and password. Mailiy then always asks for a second factor: a code by email, or a code from your authenticator app if you set one up under Account → Security. Setting it up gives you 10 recovery codes. Keep them offline; each works once. A new password needs at least 10 characters and must not appear in any known data breach. We check this against a list on our own server in the EU; your password is not sent to anyone else.
Account → Security also lists where you are signed in and lets you sign out single devices.
Under Account → Notifications you choose which emails you get: one for every sign-in, a warning when you have used 90 % and 100 % of your quota, and a monthly report. Sign-in mails and warnings start switched on, the report starts off.
You change your sign-in address under Account → Security with your password. We send a link to the new address and the change applies once you click it. The old address gets a note about the change.
When you delete your account, your forms stop accepting submissions right away. For 30 days you can undo this in the dashboard; after that we delete all data for good.
HTML
<form action="https://v3.mailiy.com/api/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR-KEY">
<input type="hidden" name="subject" value="New contact request">
<input type="text" name="name" required>
<input type="email" name="email" required>
<textarea name="message" required></textarea>
<label><input type="checkbox" name="consent" value="yes" required> I agree to the processing.</label>
<input type="checkbox" name="botcheck" class="hidden" style="display:none">
<button type="submit">Send</button>
</form>Without JavaScript, Mailiy redirects to the thank-you page after submitting (HTTP 303), or to your own URL. Errors land on the same page with ?error=code.
JavaScript
const res = await fetch("https://v3.mailiy.com/api/submit", {
method: "POST",
headers: { "Content-Type": "application/json", Accept: "application/json" },
body: JSON.stringify({ access_key: "YOUR-KEY", email, message }),
});
const { success, message } = await res.json();If you send JSON or the Accept: application/json header, Mailiy answers with JSON instead of a redirect.
Emails in your inbox
A form's emails show up in your inbox as one conversation. If you want each submission on its own, turn off grouping under Settings. Each subject then gets a short number.
If an email to one of your addresses bounces for good, for example because the mailbox no longer exists, we mark the address as undeliverable under Account. Once you have fixed it, click “Deliver again”. We delete the mark after 90 days at the latest.
Templates and auto-reply
Under Settings you pick one of six templates for the email you receive, or write your own HTML. In it, {fields} inserts the table with all fields, {intro} the intro text, {form} the form name and {field:name} the value of a single field. We always add a plain-text version.
{field:name} also works in the subject, the intro text and the auto-reply, for example “Thanks, {field:name}”. In the auto-reply each inserted value is cut to 100 characters. “Preview” shows both emails with sample data before you save. On the Agency Plus plan the Mailiy name no longer appears in the emails.
Control fields
These fields control delivery and do not appear in the email:
| Field | Meaning |
|---|---|
access_key | Required. The form's public key. |
subject | Email subject. Overrides the form setting. |
from_name | Sender name in the email. |
replyto / email | Reply-to address. Falls back to the email field. |
redirect | URL to redirect to after submitting (http/https). |
botcheck | Honeypot. Keep hidden; filled in = spam. |
consent | Consent. Required when enabled for the form. |
ccemail | More recipients, separated by semicolons. Only addresses confirmed in your account; others are ignored. |
bccemail | Like ccemail, but as a blind copy. The other recipients don't see these addresses. |
altcha / h-captcha-response / cf-turnstile-response / g-recaptcha-response | Token from the captcha widget. The widget fills it in. |
Spam protection and captcha
Every form has a honeypot field (botcheck), a rate limit and, if you want, allowed domains. That is usually enough. If spam still gets through, pick a captcha under Settings, for one form or as the website default.
ALTCHA has the browser solve a small computing task, with no picture puzzles and no third party. Mailiy hands out the task. Once ALTCHA is on, the snippet under Setup includes the widget:
<altcha-widget challengeurl="https://v3.mailiy.com/api/altcha"></altcha-widget>
<script type="module" src="https://v3.mailiy.com/api/altcha.js"></script>Mailiy serves the script itself, so your page loads nothing from a CDN. You can also put the file from the npm package altcha on your own server.
hCaptcha, Cloudflare Turnstile and reCAPTCHA work too. You create an account there, add their widget with your site key and enter the secret key in the dashboard. Mailiy stores it encrypted and never shows it again. We do not pass your visitors' IP address on when checking.
If the token is missing or wrong, Mailiy answers captcha_failed (403) and counts the submission as spam.
Spam filter and spam tab
Under Settings you turn on a spam filter per form. Normal sorts out link dumps and typical sales pitches, Strict any submission with a link or HTML. The sender still gets a normal success answer so bots learn nothing. You get no email; the submission sits in the Spam tab for 7 days and is then deleted. “Not spam” delivers it after all and moves it to the normal list. If retention is set to “Don't store”, we drop spam right away.
Under Blocked IP addresses you enter single addresses or ranges like 198.51.100.0/24 (IPv4 and IPv6). We drop submissions from there silently and store nothing.
Submissions from servers
Browsers always send the page they come from. If that is missing, the request comes from a server or script. With “Accept server submissions only with an API key” on, we refuse such requests with api_key_required (403) unless they send your API key as Authorization: Bearer mk_…. With the key, the allowed-domains check and the captcha are skipped too, and the rate limit rises to 60 a minute. Never put the key in browser code.
Responses and error codes
{ "success": true, "message": "Submission received.", "body": { "data": { "email": "…" }, "message": "Submission received." } }
{ "success": false, "code": "consent_required", "message": "…", "body": { "data": {}, "message": "…" } }The body field has the same shape as web3forms, so existing scripts keep working. On 429 the Retry-After header says how many seconds to wait: 60 for rate_limited (more than 5 submissions a minute), until the first of the month for limit_reached.
| Code | HTTP |
|---|---|
invalid_body | 400 |
origin_not_allowed | 403 |
api_key_required | 403 |
captcha_failed | 403 |
form_disabled | 403 |
invalid_access_key | 404 |
consent_required | 422 |
empty_submission | 422 |
limit_reached | 429 |
rate_limited | 429 |
delivery_failed | 500 |
Privacy checklist
- You concluded the DPA when you signed up. Read it once and keep a printout or PDF on file.
- Name Mailiy as a processor in your privacy policy.
- Choose the shortest retention possible, ideally “Don't store”.
- Set allowed domains so nobody else can use your form.
- Only ask for fields you really need (data minimisation).
- hCaptcha, Turnstile and reCAPTCHA are US providers that you add yourself. Name them in your privacy policy or use ALTCHA.
Webhook
If a webhook URL is set, Mailiy also POSTs each submission there as JSON: { form: { id, name }, created_at, data }. Only HTTPS targets with public IPs are allowed, redirects are not followed, timeout 5 seconds.