Documentation
FormSMTP docs
Everything you need to send email from a website through your own SMTP account.
Quickstart
- Create an account at app.formsmtp.com. Email and password, Google or GitHub.
- Add a project for your site and connect your SMTP account. Choose your provider (Gmail, Zoho, Outlook, SES…) and the host and port fill in. Click Test connection.
- Copy your API key from API & code, then use the HTML form below or call the JSON API.
That's it. Every send shows up under Logs with its status and, if something fails, the exact error from your SMTP server.
HTML form endpoint
The fastest way to add a working contact form: no JavaScript, no backend. Point a regular form at your project's form URL.
<form action="https://app.formsmtp.com/api/v1/form/YOUR_API_KEY" method="POST">
<input name="name" required>
<input name="email" type="email" required>
<textarea name="message" required></textarea>
<!-- optional -->
<input type="hidden" name="_subject" value="New message from my site">
<input type="hidden" name="_next" value="/thanks.html">
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
<button>Send</button>
</form>Every field is included in the email. The message goes to you: the first address under Allowed recipients, or the project's From address. A visitor can never choose who receives it, so the key is safe in public HTML.
| Special field | What it does |
|---|---|
_subject | Subject line. Default: "New form submission from |
_next | Where to send the visitor after a successful submit. Must be on the same site as the form; otherwise a thank-you page is shown. |
_replyto | Reply-to address. If absent, a field named email is used, so replying answers the visitor. |
_to | Pick one of several inboxes. Only used if it matches your Allowed recipients. |
_gotcha | Honeypot. Keep it hidden; if a bot fills it, the submission is silently dropped. |
Send Accept: application/json (or a JSON body) to get a JSON response instead of a page, which is handy for fetch(). File uploads (multipart/form-data) aren't supported.
Send API
POST https://app.formsmtp.com/api/v1/send with your key as Authorization: Bearer <key> (or X-API-Key).
curl -X POST https://app.formsmtp.com/api/v1/send \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"someone@example.com","subject":"Hello","html":"<p>It works!</p>"}'const res = await fetch("https://app.formsmtp.com/api/v1/send", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ to: "someone@example.com", subject: "Hello", text: "It works!" }),
});
const data = await res.json(); // { success: true, messageId: "…" }import os, requests
requests.post(
"https://app.formsmtp.com/api/v1/send",
headers={"Authorization": f"Bearer {os.environ['FORMSMTP_KEY']}"},
json={"to": "someone@example.com", "subject": "Hello", "text": "It works!"},
timeout=30,
)| Field | Description |
|---|---|
to * | Recipient(s): "a@x.com", "Name <a@x.com>", comma-separated, or an array. |
subject * | Subject line. Optional when the template has one. |
html / text * | Body. At least one, unless you use template. |
template | Name or id of a template from the dashboard. Fills subject and body. |
variables | Object for the template’s {{variables}}. |
cc, bcc | Same format as to. Max 50 recipients in total. |
replyTo | Reply-to address, for example the visitor’s email. |
fromName | Display name override. The address is always your project’s From email. |
attachments | [{ "filename", "content": "<base64>", "contentType" }]. 15 MB request limit. |
Templates & variables
Design emails in the visual builder (or paste HTML) and send them by name. Use {{variable}} anywhere, with an optional fallback: {{first_name|there}}.
{
"to": "ana@example.com",
"template": "Welcome",
"variables": { "first_name": "Ana", "login_url": "https://example.com/login" }
}If the recipient is one of your contacts, their name, email and custom fields are filled in automatically, along with {{unsubscribe_url}}.
Contacts API
POST https://app.formsmtp.com/api/v1/contacts adds or updates a contact. Perfect for a newsletter or waitlist form.
await fetch("https://app.formsmtp.com/api/v1/contacts", {
method: "POST",
headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
email: "ana@example.com",
name: "Ana Silva",
tags: ["newsletter"],
fields: { plan: "pro" },
}),
});Then email a tag, everyone, or specific people from Emails: now, at a set time, or on a daily, weekly or monthly schedule. Each person gets a personal copy with a working unsubscribe link.
Keeping a public key safe
Keys used in browser code are visible to anyone, so lock them down under Settings → Security:
- Allowed websites: only these origins may call the API from a browser (for example
https://yoursite.com). - Allowed recipients: only these addresses or
@domainscan receive email. For a contact form, list just yourself. - Max emails per hour: caps how much a copied key can send.
Origin checks only stop browsers. A script can fake an Origin header, which is why the recipient list and hourly limit matter most. For server-side code, leave Allowed websites empty and keep the key in an environment variable.
Responses & errors
Success: 200 {"success": true, "messageId": "…"}. Errors: {"success": false, "error": "…"} with:
| Status | Meaning |
|---|---|
400 | Invalid request: missing or malformed fields. |
401 | Missing or wrong API key. |
403 | Website or recipient not allowed, or the project is turned off. |
404 | Template name not found. |
429 | Hourly limit reached. A Retry-After header says when to try again. |
502 | Your SMTP server refused or failed. The message says why (for example, wrong password). |
SMTP settings
Common providers. The dashboard fills these in when you pick one.
| Provider | Settings |
|---|---|
Gmail / Google Workspace | smtp.gmail.com, port 465, SSL. Needs an App Password. |
Outlook / Microsoft 365 | smtp.office365.com, port 587, STARTTLS. |
Zoho Mail | smtp.zoho.com, port 465, SSL. See the Zoho guide. |
Amazon SES | email-smtp.<region>.amazonaws.com, port 587, SMTP credentials from the SES console. |
Brevo | smtp-relay.brevo.com, port 587. |
Resend | smtp.resend.com, port 465, user resend, password = your Resend API key. |
Spacemail | mail.spacemail.com, port 465, SSL. |