Connect Bubble to Mailgun using the API Connector with Basic Auth — username is the literal string 'api' (not your email, not 'apikey'), password is your Mailgun Private API Key, both marked Private. The request body must be form-data (not JSON). Use the US base URL (api.mailgun.net) or EU base URL (api.eu.mailgun.net) depending on where you signed up — using the wrong region returns empty results even though authentication succeeds.
| Fact | Value |
|---|---|
| Tool | Mailgun |
| Category | Communication |
| Method | Bubble API Connector |
| Difficulty | Beginner |
| Time required | 1–2 hours |
| Last updated | July 2026 |
Two gotchas that break every Mailgun setup in Bubble
Mailgun has two idiosyncratic requirements that catch nearly every developer who sets it up in Bubble for the first time:
**1. The Basic Auth username is the literal string 'api' — nothing else.** Not your Mailgun email address, not 'apikey', not 'anystring'. Mailgun's own documentation uses the phrase 'api' as the username so often it looks like a placeholder, but it is the actual required value. If you recently configured Twilio (which uses the Account SID as the username), do not let muscle memory make you type the Account SID here.
**2. The request body must be form-data (application/x-www-form-urlencoded), not JSON.** Mailgun's `/messages` endpoint does not accept JSON for the basic send call. If Bubble's API Connector body type is 'JSON body', Mailgun returns a 400 error with a message that looks like an authentication problem. Switch to 'Form data' and it works immediately.
A third less-obvious gotcha: the regional base URL matters. US-signed accounts use `api.mailgun.net`. EU-signed accounts use `api.eu.mailgun.net`. Confusingly, Mailgun authenticates successfully on both regional URLs — your API key is valid globally — but querying domain information or sending emails through the wrong regional endpoint returns empty results or incorrect routing. Check your Mailgun Dashboard URL: if it reads `eu.mailgun.com`, use the EU base URL.
Integration method
Bubble API Connector with Basic Auth — username is the literal string 'api', password is the Mailgun Private API Key (key-xxx), both marked Private — POSTing form-data to the Mailgun send endpoint.
Prerequisites
- A Mailgun account at mailgun.com (Flex plan is free for the first 1,000 emails/month)
- A verified sending domain in Mailgun (requires DNS access to add TXT, MX, and CNAME records — see Step 2)
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → API Connector by Bubble)
- For inbound delivery event webhooks: a Bubble paid plan (Starter or above) for Backend Workflows
Step-by-step guide
Get your Mailgun API key and identify your region
Log into your Mailgun account at app.mailgun.com (or eu.mailgun.com if you signed up for the EU region). Navigate to Settings → API Keys in the left sidebar. You will see two types of keys: - **Private API Key** — starts with `key-`, used for server-side API calls. This is the key you will use in Bubble. Copy it now. - **Public Validation Key** — starts with `pubkey-`, used only for client-side email validation widgets. Do NOT use this in Bubble's API Connector. Now identify your region. Look at the URL in your browser: - If it shows `app.mailgun.com` — you are on the US region. Use base URL: `https://api.mailgun.net/v3` - If it shows `eu.mailgun.com` — you are on the EU region. Use base URL: `https://api.eu.mailgun.net/v3` Store your Private API Key securely. If it is ever exposed, go to Settings → API Keys → click the trash icon next to it to delete it and generate a new key immediately. Old API calls using the deleted key will fail within seconds. Also note your sending domain. Go to Sending → Domains in Mailgun. Your domain might be a custom domain you added (mg.yourdomain.com) or Mailgun's sandbox domain (sandboxXXXXX.mailgun.org) if you have not added a custom domain yet. The sandbox domain only sends to authorized recipients — for production you need a verified custom domain.
1// Mailgun credentials checklist:2// Private API Key: key-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (Settings → API Keys)3// → This is the password in Basic Auth4// → Keep it Private5//6// Region:7// US: app.mailgun.com → base URL: https://api.mailgun.net/v38// EU: eu.mailgun.com → base URL: https://api.eu.mailgun.net/v39//10// Sending domain:11// Production: mg.yourdomain.com (must be verified)12// Testing: sandboxXXXXX.mailgun.org (verified emails only)Pro tip: If you are not sure which region you are on, try sending a test API call to the US base URL first. If it returns authentication errors or empty domain results, switch to the EU URL. Authentication succeeds on both — but domain data and email routing only work on the correct regional endpoint.
Expected result: You have your Mailgun Private API Key (key-xxx), know your region (US or EU), and know your sending domain name.
Verify your sending domain in Mailgun
Before Mailgun can send emails on your behalf, your domain must be verified with DNS records. This proves to Mailgun (and receiving mail servers) that you own the domain. Sandbox domains are pre-verified but restricted to authorized recipients — for production, you need a custom domain. In Mailgun, go to Sending → Domains → Add New Domain. Enter your sending subdomain — the best practice is to use a subdomain like `mg.yourdomain.com` (not the root domain) so that email settings do not conflict with your root domain's existing MX records. Mailgun shows you the DNS records to add: - **TXT record for SPF**: proves Mailgun is authorized to send from your domain - **TXT record for DKIM**: a cryptographic signature for email authentication - **MX records**: required only if you want Mailgun to receive inbound emails on this domain (optional for outbound-only setups) - **CNAME record for tracking**: enables Mailgun's open and click tracking Log into your domain registrar's DNS settings (GoDaddy, Namecheap, Cloudflare, etc.) and add these records exactly as shown by Mailgun. DNS propagation takes between 5 minutes (Cloudflare) and 24–48 hours (some registrars). In Mailgun, click 'Verify DNS Settings' to check. The status should change from 'Unverified' to 'Active.' Until your domain shows 'Active' status, any send attempts to that domain will fail with a 'Domain not found' or 'Unauthorized' error.
1// DNS records to add for mg.yourdomain.com in Mailgun:2// (values shown as examples — use the exact values from Mailgun's UI)34// SPF (TXT record):5// Name: mg.yourdomain.com6// Value: v=spf1 include:mailgun.org ~all78// DKIM (TXT record):9// Name: mailo._domainkey.mg.yourdomain.com10// Value: k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQK...1112// Tracking CNAME (optional but recommended for click/open tracking):13// Name: email.mg.yourdomain.com14// Value: mailgun.orgPro tip: Use a subdomain for Mailgun (mg.yourdomain.com) rather than your root domain. Adding MX records on the root domain would redirect all your incoming email to Mailgun — usually not what you want. A subdomain gives Mailgun its own email namespace without affecting your existing email setup.
Expected result: Your domain shows 'Active' status in Mailgun's Sending → Domains section. Mailgun's DNS checker shows green checkmarks next to SPF and DKIM records.
Configure the Mailgun API Connector in Bubble
In your Bubble editor, click 'Plugins' → 'API Connector.' Click 'Add another API' and name it 'Mailgun.' Click 'Add another call' and name it 'Send Email.' Set the method to POST. For the URL, use your region-specific endpoint with your domain: - US: `https://api.mailgun.net/v3/mg.yourdomain.com/messages` - EU: `https://api.eu.mailgun.net/v3/mg.yourdomain.com/messages` Replace `mg.yourdomain.com` with your actual verified Mailgun sending domain. Set up authentication: click the authentication dropdown and select 'Basic auth.' In the Username field, type exactly: `api` — that is the literal string 'api', nothing more. In the Password field, paste your Mailgun Private API Key (key-xxx). Check 'Private' on both fields. CRITICAL: Change the body type to 'Form data' (not JSON body). Mailgun's `/messages` endpoint requires `application/x-www-form-urlencoded` encoding. JSON body returns a 400 error. Add the following form-data body fields: - `from` — the sender address, format: `Name <email@mg.yourdomain.com>`. Mark it with a default value or make it dynamic. The email address must be on your verified Mailgun domain. - `to` — the recipient email address (dynamic) - `subject` — the email subject line (dynamic) - `text` — plain text version of the email (dynamic; provide at least this or `html`) - `html` — HTML version of the email (optional but recommended for branded emails; dynamic) Click 'Initialize call.' Enter real values for from, to (use your own email), subject, and text, then click Initialize. You should receive a test email within a few minutes.
1// API Connector: Mailgun → Send Email2// Method: POST3// URL: https://api.mailgun.net/v3/mg.yourdomain.com/messages4// (or https://api.eu.mailgun.net/v3/mg.yourdomain.com/messages for EU)5//6// Authentication: Basic Auth7// Username: api // literal string 'api' — NOT your email — mark Private8// Password: key-xxxx // Mailgun Private API Key — mark Private9//10// Body type: Form data (NOT JSON)11// Form fields:12// from: Sender Name <noreply@mg.yourdomain.com> (can be static default)13// to: <dynamic_recipient_email>14// subject: <dynamic_subject_line>15// text: <dynamic_plain_text_body>16// html: <dynamic_html_body> (optional — for branded emails)Pro tip: Store your Mailgun sending domain (mg.yourdomain.com) as a reusable value. If you need to reference it in multiple API calls (send, bounce lookup, etc.), consider storing it in Bubble's Option Sets or a single-row App Settings data type so you can update it in one place if the domain ever changes.
Expected result: The Initialize call returns `{"id": "<message-id>", "message": "Queued. Thank you."}` and you receive a test email at the address you used in the 'to' field.
Build a Bubble workflow that sends email on trigger
Wire the Mailgun API Connector call to real Bubble workflow events. The pattern is: a triggering event fires a workflow that calls the Mailgun Send Email action. For secure server-side execution, wrap the Mailgun action in a Backend Workflow (Bubble paid plan). This ensures your API Key stays completely server-side and the email is sent even if the user navigates away. Trigger the Backend Workflow from client-side actions using 'Schedule API Workflow' at 'Current date/time.' Common email scenarios: **Order confirmation**: Trigger: When an Order record is created → Backend Workflow → Send Email - from: `Acme Shop <orders@mg.yourdomain.com>` - to: Order's customer_email - subject: `Your order #` + Order's order_number + ` is confirmed!` - text: `Hi ` + Order's customer_name + `, thank you for your order. Total: $` + Order's total_amount - html: Build an HTML template with Bubble's text formatting, wrapping the dynamic values in styled HTML **Welcome email**: Trigger: When a User record is created → Backend Workflow → Send Email - to: New User's email - subject: `Welcome to [App Name]!` **Password reset / email verification**: Generate a unique token, store in the User record with expiry, build a verification URL containing the token as a URL parameter, and include the URL in the email body. For bulk sends (e.g., newsletter to a list of users), use Mailgun's batch sending with recipient variables rather than looping through users in Bubble with a 'Do a search for' each. Looping sends individual API calls — one per user — which burns WU unnecessarily. Mailgun's batch send accepts a `to` field with multiple addresses and a JSON `recipient-variables` parameter for personalizing each email.
1// Backend Workflow: Send Order Confirmation Email2// Trigger: When Order is created3// Step 1: Plugins → Mailgun → Send Email4// from: "Acme Shop <orders@mg.yourdomain.com>"5// to: Order's customer_email6// subject: "Order #" + Order's order_number + " Confirmed"7// text: "Hi " + Order's customer_name + ",\n\nThank you for your order.\nTotal: $" + Order's total_amount + "\n\nWe'll notify you when it ships."8// html: "<h1>Order Confirmed</h1><p>Hi " + Order's customer_name + "</p>..."910// Email verification workflow:11// Step 1: Set User's email_token = Generate random string (length 32)12// Step 2: Set User's email_token_expires = Current date/time + 86400 seconds13// Step 3: Backend Workflow → Send Email14// subject: "Verify your email address"15// text: "Click to verify: https://yourapp.bubbleapps.io/verify?token=" + User's email_tokenPro tip: Mailgun's Flex plan includes the first 1,000 emails per month for free, then charges approximately $0.80 per 1,000 emails. For apps with moderate volume, this is extremely cost-effective. At scale, consider Mailgun's Foundation plan ($35/month for 50,000 emails) for better per-email pricing and dedicated IP options.
Expected result: Triggering the workflow sends a real email to the specified address. Mailgun's Dashboard → Logs shows the message with 'Delivered' status. The Bubble Logs tab shows the API Connector action completed with a 200 response.
Set up bounce and delivery event webhooks in Bubble
Mailgun can notify your Bubble app when emails are delivered, opened, clicked, bounced, or marked as spam. This is essential for maintaining email list hygiene — sending repeatedly to bounced addresses damages your sender reputation and wastes API calls. For inbound Mailgun events, you need a Bubble paid plan for Backend Workflows. In Bubble, go to Settings → API → check 'This app exposes a Workflow API.' Copy your workflow API base URL. In Backend Workflows, create a new workflow named `mailgun_events`. Click 'Detect data' and Bubble listens for the next incoming request. In Mailgun Dashboard, go to Sending → Webhooks. Click 'Add webhook.' Select the event types you want to track (Delivered, Permanent Failure/Bounced, Spam Complaint, Unsubscribed). Enter your Bubble workflow URL: `https://appname.bubbleapps.io/api/1.1/wf/mailgun_events`. Mailgun sends a test request when you save the webhook — Bubble's Detect Data captures the schema. Mailgun's webhook payload is a JSON POST with a nested structure: the event data lives inside `event-data` → all fields are under this parent key. Key fields to detect and use: - `event-data.event` — event type: 'delivered', 'failed', 'complained', 'unsubscribed' - `event-data.recipient` — the recipient email address - `event-data.timestamp` — Unix timestamp of the event - For failed events: `event-data.reason` — bounce reason, `event-data['delivery-status'].code` — SMTP code In the Backend Workflow actions: 1. Find the User record where email = Step 1's event-data.recipient 2. If event = 'failed' (permanent bounce): Set User's email_valid = 'no' 3. Create an Email_Event record logging the event type, recipient, and timestamp 4. Return HTTP 200 with `{"status": "received"}` to acknowledge the webhook RapidDev has built email delivery tracking systems for multiple Bubble clients — if you need complex bounce handling with suppression management, book a free consultation at rapidevelopers.com/contact.
1// Mailgun webhook POST body structure (JSON):2{3 "event-data": {4 "event": "failed",5 "timestamp": 1735900000,6 "recipient": "user@example.com",7 "message": {8 "headers": {9 "message-id": "<msg-id@mg.yourdomain.com>"10 }11 },12 "reason": "bounce",13 "delivery-status": {14 "code": 550,15 "message": "5.1.1 The email account does not exist"16 },17 "flags": {18 "is-test-mode": false,19 "is-routed": false20 }21 }22}2324// Bubble Backend Workflow detected fields:25// event-data.event → text (delivered, failed, complained, unsubscribed)26// event-data.recipient → text27// event-data.timestamp → number (Unix)28// event-data.reason → text (for failed events)29// event-data.delivery-status.code → numberPro tip: Mailgun wraps all event data inside the `event-data` key, unlike some other email providers that send flat JSON. When Bubble detects the schema, you will see nested field names like `event-data.event` and `event-data.recipient` — use these exact nested references in your workflow actions.
Expected result: Mailgun's webhook test request is detected by Bubble. Your Backend Workflow can read event-data.event and event-data.recipient. When a real email bounces, the corresponding User record's email_valid field is automatically set to 'no' within seconds.
Add suppression checking before sending emails
Sending emails to addresses that have previously bounced harms your deliverability. Mailgun maintains a suppression list — a database of bounced and unsubscribed addresses for your domain. Before sending important emails, check whether the recipient is on the suppression list. Add a second API Connector call in Bubble named 'Check Email Suppression.' Set the method to GET and the URL to: `https://api.mailgun.net/v3/mg.yourdomain.com/bounces/{{email_address}}` Use the same Basic Auth credentials (username: 'api', password: your Private API Key, both Private). Make `email_address` a dynamic parameter. Mailgun returns HTTP 200 if the address is on the bounce list, and HTTP 404 if it is NOT on the bounce list (meaning it is safe to send). This inverse logic can confuse developers — a 404 response means 'not found in bounces = safe to email.' In a Bubble workflow, handle this by: 1. Call the Check Suppression API Connector action 2. If the response status is 404 (not in bounces), proceed to send the email 3. If the response returns a bounce record (200), skip sending and mark the email as invalid in the database Bubble's API Connector handles HTTP 404 responses as errors — check the workflow's error step to capture 404s and treat them as the 'safe to send' signal. For better performance, cache this check: once you verify an email is not bounced, flag it as `email_verified: yes` in your Bubble User record and skip the suppression check for subsequent sends. Re-check only when a new bounce webhook arrives.
1// API Connector: Mailgun → Check Email Suppression2// Method: GET3// URL: https://api.mailgun.net/v3/mg.yourdomain.com/bounces/{{email_address}}4// Authentication: Basic Auth → username: api, password: key-xxx (Private)56// Response logic:7// HTTP 200 → address IS on bounce list → do NOT send email8// HTTP 404 → address is NOT on bounce list → safe to send910// Bubble workflow:11// Step 1: Call Check Email Suppression with recipient email12// Step 2: If Step 1 returned data (200 - found in bounces):13// → Set User's email_valid = 'no'14// → End workflow (skip send)15// Step 3 (on Step 1 error / 404):16// → Continue to Send Email actionPro tip: You can also proactively remove addresses from the bounce list after a bounce was caused by a temporary issue (e.g., the recipient's mailbox was full but now has space). Use the DELETE /bounces/{email} endpoint in a separate API Connector call to clear the suppression entry and re-enable sending to that address.
Expected result: Your email sending workflow checks Mailgun's bounce list before sending. Known bounced addresses are skipped, preventing damage to your sending reputation. New bounces are automatically added to the suppression list by Mailgun and your Bubble bounce webhook marks them as invalid.
Common use cases
Transactional notification emails — receipts, confirmations, status updates
Send branded, custom emails from your Bubble app when users complete actions: order confirmations, payment receipts, appointment reminders, and subscription renewal notices. Mailgun delivers these from your verified domain so emails arrive in the inbox, not the spam folder.
When an Order record's status changes to 'Confirmed', trigger a Backend Workflow that calls the Mailgun API to send an order confirmation email to Order's customer_email with the order number, item list, and total amount in the email body.
Copy this prompt to try it in Bubble
Email verification and OTP delivery
Send verification links or one-time passcodes to users' email addresses during sign-up or sensitive actions. Generate a unique token in Bubble, store it with an expiry timestamp, and email it via Mailgun. Verify the token when the user clicks the link or submits the code.
When a user clicks 'Verify Email', generate a random 32-character token, store it as User's email_verification_token with email_token_expires_at = Current date/time + 24 hours, then send a Mailgun email containing a verification link that includes the token as a URL parameter.
Copy this prompt to try it in Bubble
Bounce and delivery tracking for email hygiene
Use Mailgun's webhook events to track bounced emails and automatically suppress or flag invalid addresses in your Bubble database. When Mailgun reports a permanent bounce, mark the User's email as invalid to prevent wasting future sends on dead addresses.
When a Mailgun bounce webhook arrives at the Bubble Backend Workflow endpoint, find the User record matching event-data.recipient, set that User's email_valid field to 'no', and create an Email_Event record logging the bounce timestamp and bounce code.
Copy this prompt to try it in Bubble
Troubleshooting
API Connector Initialize call returns 401 Unauthorized
Cause: The Basic Auth username is wrong. The most common mistake: entering your Mailgun email address or the string 'apikey' instead of the literal string 'api'. Mailgun's Basic Auth requires exactly 'api' as the username — this is Mailgun's own hard-coded convention, not a placeholder.
Solution: In Bubble's API Connector → Mailgun → Send Email → Basic auth settings, verify the Username field contains exactly: `api` (four lowercase letters, no spaces, no quotes). Delete whatever is in there and retype it manually. The Password should be your Private API Key starting with `key-`.
API Connector returns 400 Bad Request when sending email
Cause: The body type is set to 'JSON body' instead of 'Form data.' Mailgun's /messages endpoint requires application/x-www-form-urlencoded encoding — JSON body returns a 400 error.
Solution: In Bubble's API Connector → Mailgun → Send Email call settings, find the body type selector and change it from 'JSON body' to 'Form data.' Your from, to, subject, text, and html fields should then appear as individual form fields (not inside a JSON object). Click 'Initialize call' again after making this change.
Emails authenticate successfully but no messages appear in Mailgun Logs and recipients never receive them
Cause: You are using the wrong regional base URL. If your Mailgun account is on the EU region but you are posting to `api.mailgun.net` (US endpoint), authentication succeeds (API keys work globally) but Mailgun cannot find your EU-registered domain to send from.
Solution: Check your Mailgun dashboard URL. If it shows `eu.mailgun.com`, change the API Connector URL from `https://api.mailgun.net/v3/...` to `https://api.eu.mailgun.net/v3/...`. Update the base URL in both the Send Email call and any other Mailgun API calls in Bubble.
'There was an issue setting up your call' when initializing the Send Email call
Cause: The Initialize call requires real values to return a successful response that Bubble can parse for the schema. If the 'to' field is empty, the 'from' field is not in the correct format, or the domain is not verified, Mailgun returns an error and Bubble cannot complete initialization.
Solution: Before clicking Initialize, fill in all required body fields with real values: from = 'Test <noreply@mg.yourdomain.com>' (using your verified Mailgun domain), to = a real email you can check, subject = 'Test', text = 'Test email from Bubble'. Make sure your Mailgun domain is fully verified (Active status in Mailgun dashboard) before attempting the Initialize call.
Trial / sandbox domain only sends to your own email and fails for other recipients
Cause: Mailgun sandbox domains (sandboxXXXXX.mailgun.org) and new accounts on the Flex free tier restrict outbound email to 'Authorized Recipients' — email addresses manually verified in your Mailgun account.
Solution: For testing: in Mailgun Dashboard → Sending → Overview → Authorized Recipients, add each email address you want to test with. For production: add and verify a custom sending domain (mg.yourdomain.com) as described in Step 2. Custom verified domains remove the authorized recipient restriction.
Best practices
- Always mark your Mailgun Private API Key (in the Basic Auth Password field) as Private in Bubble's API Connector. The key starts with 'key-' and gives full access to send, delete, and manage your Mailgun domain — treat it with the same security as a database password.
- Use a subdomain for Mailgun sending (mg.yourdomain.com) rather than your root domain. This prevents Mailgun's MX records from interfering with your existing email setup on the root domain, and keeps email routing clean.
- Always set body type to 'Form data' for Mailgun's send endpoint, not JSON. This is the single most common configuration error in Mailgun integrations across all platforms.
- Implement bounce handling via Mailgun webhooks and apply Bubble privacy rules to any data type storing email addresses or delivery event logs. Email addresses are PII and should not be readable by all users.
- Check the regional base URL before building your integration. Using api.mailgun.net for an EU-region account authenticates without error but silently fails to find your domains. Confirm the base URL matches your Mailgun region.
- Cache suppression checks in your Bubble User data type. Once you have confirmed an email is not bounced (404 response from the bounces endpoint), set a flag like `email_verified: yes` on the User and skip the suppression check on future sends. Only re-check when a bounce webhook arrives for that address.
- For high-volume campaigns, use Mailgun's batch sending with recipient variables rather than looping through individual Bubble workflows. Looping creates one API call per recipient, burning WU and hitting rate limits — Mailgun's batch API sends all recipients in a single request with personalized content per address.
Alternatives
SendGrid uses a Bearer API key (not Basic Auth) and JSON body (not form-data) — which many developers find more intuitive. SendGrid also provides a stronger visual email template builder in its dashboard. Choose SendGrid if you prefer JSON-based API configuration or need robust email template management. Both deliver equivalent transactional email performance.
Twilio delivers notifications via SMS and WhatsApp, not email. Both integrations use Basic Auth in Bubble's API Connector with form-data body, but Twilio's username is the Account SID (not 'api'). Use Mailgun for email delivery; use Twilio when you need to reach users via their phone numbers.
Slack delivers messages to a team workspace in real time — not to external email addresses. If your notification recipients are all members of your Slack workspace, Slack Incoming Webhooks are simpler to configure than Mailgun. Use Mailgun when you need to reach external users or customers via their email inboxes.
Frequently asked questions
Why is the Mailgun API username 'api' and not my email address?
This is Mailgun's own API convention, not a placeholder or variable. Mailgun requires Basic Auth where the username is always the literal string 'api' and the password is your Private API Key. This is documented in Mailgun's official API reference. The pattern dates from Mailgun's original API design and has not changed. Always type 'api' exactly (lowercase, four letters) as the username.
How do I know if my Mailgun account is on the US or EU region?
Check the URL in your browser when you are logged into Mailgun. If it shows `app.mailgun.com`, you are on the US region — use base URL `https://api.mailgun.net/v3`. If it shows `eu.mailgun.com`, you are on the EU region — use base URL `https://api.eu.mailgun.net/v3`. Your API key works for authentication on both endpoints, but domain operations and email sending only work on the correct regional endpoint.
How many emails can I send for free with Mailgun?
Mailgun's Flex plan includes the first 1,000 emails per month at no cost, then charges approximately $0.80 per 1,000 emails beyond that. The Foundation plan ($35/month) includes 50,000 emails with no per-email charge up to that limit. There is no free trial of the Foundation plan — Flex's free tier is the entry point.
Can I send HTML emails with Mailgun from Bubble?
Yes. In the API Connector form-data body, add an `html` field alongside `text` and populate it with your HTML content as a dynamic text string. It is best practice to include both `text` and `html` — some email clients prefer plain text and Mailgun uses `text` as the fallback. Build your HTML template as a Bubble text expression combining static HTML tags with dynamic data, or store HTML templates in your database and reference them dynamically.
What does it mean when Mailgun says my domain is 'Unverified'?
An Unverified domain in Mailgun means you have added the domain but not yet added the required DNS records, or the DNS records have not propagated yet. You cannot send emails from an Unverified domain — Mailgun rejects the send attempt. Go to Sending → Domains in Mailgun, click your domain, and verify that the DNS records (TXT for SPF, TXT for DKIM) are correctly added in your domain registrar's DNS settings. After adding the records, click 'Verify DNS Settings' in Mailgun — it checks in real time.
Does Mailgun work on Bubble's Free plan?
The basic email send action works on Bubble Free as a client-side action. However, for security, the API Key should run through a Backend Workflow (Bubble paid plan) to ensure it never appears in browser network requests. Inbound Mailgun webhooks for bounce tracking also require Backend Workflows and therefore a paid Bubble plan. For a production email integration with proper security and bounce handling, a Bubble Starter plan or above is recommended.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation