all guides

// how to fix

Mailgun "401 Forbidden": wrong API key or EU/US region mismatch

Mailgun returns 401 Forbidden or Unauthorized. Check the API key type, the "api" username and whether your domain uses the US or EU endpoint.

What it means

Your app called the Mailgun API and got HTTP 401 Unauthorized. The response body is often just the word Forbidden, which is confusing. Mailgun's API reference says 401 means the API key is missing or invalid, while 403 means the key is valid but access to that resource is denied. In practice, a 401 almost always comes from one of the problems below.

Why it happens

  • Region mismatch. Each sending domain is created in the US or the EU region. A domain created in the EU must be called on https://api.eu.mailgun.net/, a US domain on https://api.mailgun.net/. Calling the wrong one fails even with a good key. Many libraries and plugins default to the US endpoint.
  • Wrong kind of key. Mailgun has several keys: the private Mailgun API key (account level), domain sending keys (send only, for one domain), the HTTP webhook signing key and the public verification key. The last two cannot send email.
  • A sending key used for another domain or endpoint. A domain sending key only works for /messages and /messages.mime on the domain it was created for. Calling /v3/domains or another domain with it fails.
  • Bad Basic Auth. The username must be exactly api and the password the key. Some code sends the key as username, or adds spaces or quotes. Older keys start with key-, and this prefix is part of the key.
  • Deleted or regenerated key. Keys are shown only once; a teammate may have rotated the key you still have in .env.
  • IP allowlist: if API access is restricted to some IP addresses in your account security settings, calls from a new server are refused.

A 404 "Domain not found" usually means the domain name in the URL is wrong or exists in the other region.

How to check

  1. In the Mailgun panel, open Send, Domains: the list shows each domain's region (US or EU).
  2. Test your key with curl, using the endpoint of that region:
curl -s --user 'api:YOUR_API_KEY' \
  https://api.eu.mailgun.net/v3/mg.yourdomain.com/messages \
  -F from='Test <hello@mg.yourdomain.com>' \
  -F to='you@example.com' \
  -F subject='Mailgun test' \
  -F text='Hello'

If this returns a JSON answer with an id and "Queued", the key and region are right and the problem is in your app's configuration. Try the other endpoint if it fails: if one works and the other does not, it is a region mismatch. Remove .eu for a US domain.

How to fix it

1. Set the region in your library. Examples:

// mailgun.js (Node)
const mg = new Mailgun(FormData).client({
  username: 'api',
  key: process.env.MAILGUN_API_KEY,
  url: 'https://api.eu.mailgun.net', // only for EU domains
});

# Laravel .env
MAILGUN_DOMAIN=mg.yourdomain.com
MAILGUN_SECRET=your-private-or-sending-key
MAILGUN_ENDPOINT=api.eu.mailgun.net

# Symfony Mailer
MAILER_DSN=mailgun+api://KEY:mg.yourdomain.com@default?region=eu

In WordPress SMTP plugins, choose the matching Region option. Then:

  1. Use the right key. Create a new private API key or a domain sending key in the Mailgun panel (API security / sending keys) and store it immediately; you will not see it again. Use the sending key only for sending on its own domain.
  2. Check for hidden characters: no quotes inside the value, no trailing space or line break from copy and paste.
  3. Update the IP allowlist if you use one, with the public IP of the server that calls the API.
  4. For SMTP, the equivalent error is a 535 authentication failure. SMTP credentials are per domain and per region: use smtp.eu.mailgun.org for EU domains and smtp.mailgun.org for US ones, with the domain's SMTP login (for example postmaster@mg.yourdomain.com). If you use PHPMailer, see PHPMailer "Could not authenticate".

If the call is accepted but the message is refused because you still use the sandbox domain, read Mailgun sandbox: authorized recipients only. If your domain is not verified yet, fix its DNS first with Mailgun domain not verified.

Check that it is fixed

Send a message from your app to the unique address on the Delivmail home page. If it arrives, authentication works; the report then tells you whether SPF, DKIM and DMARC pass for your Mailgun domain. Then resend the messages that failed with 401, and keep the region and key in one configuration place so the next deployment does not bring the error back.

Check that it is fixed

DNS changes can take from a few minutes to a few hours. Then send a new test email or scan your domain again.

Related guides