Overview
SimpleFlare treats sending and receiving as two halves of the same conversation. Your product calls one REST endpoint to send transactional email; the replies land in a unified inbox where your team answers them. Every business you run gets its own sender identity, templates, and inbox, all managed from one hub.
Send
One endpoint per project, authenticated with a rotating key. Template, wrapped HTML, or fully rendered HTML.
Receive
Inbound mail is threaded per project in a shared inbox with inline replies.
Deliver
Open, click, and bounce tracking, an automatic suppression list, and one-click unsubscribe.
Quickstart
Every request goes to a single endpoint:
POSThttps://simpleflare.app/api/email/send
Send your first email with a stored template and some data:
curl -X POST https://simpleflare.app/api/email/send \
-H "X-Project-Key: sk_your_project_key" \
-H "Content-Type: application/json" \
-d '{
"template": "welcome",
"to": "[email protected]",
"vars": { "name": "Ann" }
}'
# => {"ok":true}
That is the whole loop: the API renders your project's welcome template with the data you passed and sends it from that project's support@ identity.
Authentication
Each project has its own Send API key, shown in the admin under the project's email templates. Pass it on every request in the X-Project-Key header. The key both authenticates the call and selects which project (identity, templates, design) the email is sent from.
| Header | Value |
|---|---|
X-Project-Key | Your project's secret key, e.g. sk_live_.... Rotate it any time from the admin; the old key stops working immediately. |
Content-Type | application/json |
Send from a template
Reference a stored template by key and pass its data in vars. Four variables are injected automatically and never need to be passed: brand, app_url, login_url, and support_email.
curl -X POST https://simpleflare.app/api/email/send \
-H "X-Project-Key: sk_your_project_key" \
-H "Content-Type: application/json" \
-d '{
"template": "welcome",
"to": "[email protected]",
"vars": { "name": "Ann", "plan": "Studio" }
}'
From Laravel:
Http::withHeaders(['X-Project-Key' => config('services.simpleflare.key')])
->post('https://simpleflare.app/api/email/send', [
'template' => 'welcome',
'to' => $user->email,
'vars' => ['name' => $user->name],
]);
Dynamic HTML (loops, model data)
Most real emails (order confirmations, digests) are code: they loop over line items and translated strings that do not fit a string template. Render that content in your own app and pass it as content_html. SimpleFlare wraps it in the project's design shell and sends it from the project identity, so it still matches your brand.
curl -X POST https://simpleflare.app/api/email/send \
-H "X-Project-Key: sk_your_project_key" -H "Content-Type: application/json" \
-d '{
"to": "[email protected]",
"subject": "Order #1234 confirmed",
"content_html": "<h1>Thanks!</h1><table>...your rows...</table>"
}'
Rule of thumb: simple emails (welcome, notifications) use template; dynamic emails render in your app and use content_html. Either way, every email leaves with one unified design and identity.
Fully rendered HTML
If your project renders the complete email, including its own <html> shell, send it as html and SimpleFlare relays it as-is with no wrapping. Optional from, from_name, and text override the identity and add a plain-text part.
curl -X POST https://simpleflare.app/api/email/send \
-H "X-Project-Key: sk_your_project_key" -H "Content-Type: application/json" \
-d '{
"to": "[email protected]",
"subject": "Order #1234 confirmed",
"html": "<!doctype html><html>...full email...</html>"
}'
Recipients, CC and BCC
to is required; cc and bcc are optional. Each field accepts a single email string, an array of emails, or an array of {email, name} objects, and you can mix those freely. Invalid addresses are dropped, and each field is capped at 50 recipients.
curl -X POST https://simpleflare.app/api/email/send \
-H "X-Project-Key: sk_your_project_key" -H "Content-Type: application/json" \
-d '{
"template": "notify",
"to": ["[email protected]", {"email": "[email protected]", "name": "Ben"}],
"cc": "[email protected]",
"bcc": ["[email protected]"],
"vars": { "name": "Team" }
}'
| Field | Required | Notes |
|---|---|---|
to | Yes | String, array, or {email,name} objects. Max 50. |
template / content_html / html | One of | How the body is produced. See the sending sections above. |
subject | For HTML sends | Templates carry their own subject; HTML sends set it here. |
vars | No | Data for template placeholders. Auto vars are added for you. |
cc, bcc | No | Same shapes as to. Max 50 each. |
Receiving replies
Every project has a support@<domain> address. Inbound mail is parsed and threaded into the unified inbox, grouped by project, where your team reads and replies inline. Replies go out wrapped in that project's design, so a conversation stays on-brand from the first send to the last answer.
Attachments on inbound mail are stored with a 25MB cap. Dangerous executable types are blocked for safety and shown as blocked rather than downloaded.
Already on Google Workspace or Microsoft 365? You can route just your support address into SimpleFlare and leave everything else untouched. See the step-by-step guide: Use SimpleFlare for support email, keep Google or Microsoft.
Live chat widget
Add a chat bubble to any website with one line. Visitors message you, and their messages land in the same inbox as your email, threaded per project. You answer from the inbox and your replies appear in the visitor's chat in seconds. Each project gets its own public widget key (pk_...), which is safe to put in your page.
Install
Paste this once, right before the closing </body> tag, on every page where you want the bubble:
<!-- from SimpleFlare admin: Projects → your project → Live chat -->
<script src="https://simpleflare.app/widget/embed" data-key="pk_your_widget_key" async></script>
Works on plain HTML, WordPress (footer / a headers-and-footers plugin), Shopify (theme.liquid), Webflow (Footer Code), or Google Tag Manager (a Custom HTML tag on All Pages). It loads asynchronously and never blocks your page.
Tell it who is signed in
Optional, and the thing most people wish they had added first. Without it a signed-in customer arrives in your inbox as Anonymous, with no address to reply to. Add two attributes to the same tag:
<script src="https://simpleflare.app/widget/embed" data-key="pk_your_widget_key"
data-name="{{ user.name }}"
data-email="{{ user.email }}" async></script>
If people sign in without the page reloading, those attributes were already read. Call this instead, any time after login:
SimpleFlare.identify({ name: 'Bella Pavlova', email: '[email protected]' })
This is a claim, not proof. The widget key is public, so anyone can send any address. It is enough to know who you are replying to; do not use it to decide what someone is allowed to see. If your chat should ever reveal account data, ask us for signed identity - your server signs the address with a secret only the two of us hold, and we verify it before trusting the name.
Prove who is writing
The attributes above are a claim. If your chat should ever show account or order data, sign the address on your server first. Take the signing secret from Projects → your project → Live chat, keep it server-side, and send the digest of the lowercased address:
// PHP hash_hmac('sha256', strtolower($user->email), $secret)
// Node crypto.createHmac('sha256', secret).update(email.toLowerCase()).digest('hex')
// Ruby OpenSSL::HMAC.hexdigest('SHA256', secret, email.downcase)
Pass it as data-hash (or identify({ name, email, hash })). A verified visitor carries a green badge in our inbox, so your team can see at a glance whether an address is proven or merely asserted.
A wrong or missing signature never blocks the message - the visitor still reaches you, just without the badge. Someone with a real problem must always be able to write to support.
Content Security Policy
If your site sends a Content-Security-Policy header, allow SimpleFlare in two directives, or the widget will silently not load:
script-src ... https://simpleflare.app;
connect-src ... https://simpleflare.app;
Chat without email
Chat works on its own, you do not need to set up email. Create a project, turn the widget on, and embed the snippet. Visitor messages arrive in the inbox and your replies reach them through the widget (no email is sent). If a visitor leaves an email or phone in their message, you will see it in the thread so you can follow up later.
Languages
The widget is bilingual (English and Bulgarian). It reads your page's <html lang> and shows the matching language, and it switches live the moment the site language changes. Set the greeting, reply-time line and questions for each language in the admin (Projects → your project → Live chat → the English / Български tabs).
Theme, colour and questions
- Theme: light, dark, or auto (follows the visitor's device / your site).
- Colour: the widget uses the project's accent colour, with automatic contrast on the buttons.
- Common questions: add a FAQ that shows on the widget's home screen so easy questions answer themselves, with a "still need help" link into the chat.
- Notifications: add a Slack incoming-webhook to get pinged when a new chat starts.
Configure all of this on the project's Live chat page, then answer conversations from the inbox like any other message.
Templates
Templates are per-project and editable in the admin, with a live preview, test sends, and versioning. Each has a subject, an HTML body, and a plain-text fallback, and uses {{var}} placeholders. System templates such as welcome and notify fall back to built-in defaults until you save your own.
To carry over an existing email: open the project's templates, create a new key, paste your HTML, swap dynamic values for {{var}} placeholders, preview, and save. Your product then references it by key through the API.
Deliverability
- Tracking: opens, clicks, and bounces are recorded per message.
- Suppression: permanent (hard) bounces are added to a suppression list automatically, so you stop mailing addresses that will never deliver.
- Unsubscribe: one-click
List-Unsubscribeheaders are supported. - A/B: template variants let you compare subject lines and content.
Responses and errors
A successful send returns 200 with {"ok":true}. Errors return a matching status code and an error message.
| Status | Meaning |
|---|---|
200 | Sent. Body is {"ok":true}. |
401 | Missing or invalid X-Project-Key. |
402 | Trial ended. Pick a plan to resume sending. |
403 | Transactional email is not part of the current plan. |
422 | Validation failed, for example no valid recipient or a body that could not render. |
429 | Rate limited, or the send allowance stopped this call. See below. |
Send allowance
Each plan includes a block of outbound emails per month. Only sends through this API count. Replies from the inbox and live chat are free and are never counted against it.
| Account | What happens |
|---|---|
| On a paid plan | Past the included block, sends keep going out and the extra is metered per 1,000 at your plan's published rate. A hard ceiling of 3x the included block stops runaway usage, and returns 429. |
| On trial | Sending stops at the included block with 429, because there is no payment method to meter against. Choose a plan to continue. |
| Lapsed or canceled | Sending is paused with 402 until a plan is active again. |
We email the account owner once at 80% and once at 100% of the included block each month, so usage never surprises you. One recipient equals one send, so a message addressed to three people counts as three.
Ready to build? Start a free 14-day trial, add your first business, and send a test in minutes.