How to integrate X-Mailgun-Variables when using custom HTML content in Mailgun API

I’m working with the Mailgun API to send emails and I want to use my own HTML content directly in the API call instead of creating templates through their interface.

The issue I’m facing is that my variables aren’t getting replaced in the HTML content. I’m wondering if I need to create the template in Mailgun first before I can use variables, or if there’s a way to do variable substitution with inline HTML.

Most documentation I found shows examples using the template parameter with variables, but I haven’t seen any examples that show how to use variables with the html parameter.

Here’s my HTML content:

Hello there {{user_name}}

And here’s my Python code:

requests.post("https://api.mailgun.net/v3/mydomain.mailgun.org/messages",
    auth=("api", "my-api-key"), 
    data={
        "from": "System <[email protected]>", 
        "to": ["[email protected]"], 
        "html": "<html><body>Hello there {{user_name}}</body></html>",
        "subject": "Test Message", 
        "text": "Plain text version", 
        "h:X-Mailgun-Variables": json.dumps({"user_name": "John Doe"})
    }
)

Is there something I’m missing in my approach?

yup, mailgun requires their templates for variables in html. if you wanna use inline, you’ll have to replace variables in python first. just stick with string.replace() or format() to swap out {{user_name}} with the real name before sending.

You’re right - X-Mailgun-Variables only works with Mailgun templates, not inline HTML. When you use the html parameter directly, Mailgun won’t process template variables automatically. I hit this same issue migrating from another email service. The fix is handling variable replacement yourself before calling the API. You can use Python’s string methods or something like Jinja2 for complex cases. Here’s how I tweaked similar code: ```python
html_content = “Hello there {user_name}”
processed_html = html_content.format(user_name=“John Doe”)
requests.post(“https://api.mailgun.net/v3/mydomain.mailgun.org/messages”,
auth=(“api”, “my-api-key”),
data={
“html”: processed_html,

rest of your parameters,

})

This actually gives you more flexibility since you're not stuck with Mailgun's template syntax.

Been wrestling with this for months too. X-Mailgun-Variables header is basically useless unless you’re using their stored templates. I ended up creating a preprocessing function that handles variable substitution before the API call. Works well but you lose Mailgun’s built-in features like conditional blocks and loops. For basic variable replacement, doing it client-side is more reliable since you control the logic. Just escape user input properly to avoid XSS when injecting variables into HTML. Worth the trade-off if you want templates in your codebase instead of managing them through Mailgun’s interface.