Have you inspected the logs in storage/logs/laravel.log for any errors?
[ip stanatized] - - [10/Jun/2025:17:07:44 +0000] “POST /api/v1/mailgun_inbound_webhook HTTP/1.1” 403 57 “-” “Go-http-client/2.0” “35.212.98.13”
Describe the bug
Expense Inbox doesn’t work, I have mailgun forwarding and the requests are recieved, but it’s giving me error 403 in the logs.
You’re encountering a 403 Forbidden error when Mailgun tries to hit the /api/v1/mailgun_inbound_webhook endpoint on your Invoice Ninja installation. This typically indicates unauthorized access, most often due to missing or incorrect authentication.
Confirmed Setup
Invoice Ninja Version: v5.12.0
Deployed via: Docker
Mailgun forwarding works: Yes
Webhook endpoint hit: Yes
Error in response: HTTP 403
Root Cause
Invoice Ninja requires a secret token to authorize the Mailgun webhook request.
From the relevant pull request and source code, the /api/v1/mailgun_inbound_webhook endpoint checks for an X-Mailgun-Signature or custom token to validate the request.
If no valid token is passed or it doesn’t match, the system will return 403.
Fix Instructions
Set your webhook signing secret in .env:
Add a variable like:
MAILGUN_WEBHOOK_SECRET=mysecret
Restart Docker containers so .env changes take effect:
docker-compose down
docker-compose up -d
Update your Mailgun forwarding to use the secret token:
When setting up the webhook in Mailgun, you must ensure that either:
The POST includes a custom header (e.g., X-Mailgun-Token: mysecret)
Or, if you’re using Mailgun’s signing mechanism, ensure Invoice Ninja is checking X-Mailgun-Signature.
If Mailgun doesn’t support custom headers in webhooks, you might need to:
Modify Invoice Ninja’s webhook handling code to skip token validation (not recommended for production)
Or proxy the Mailgun request through a small script that adds the required header/token
Alternative Debugging Tips
Double-check the IP whitelist (some apps reject unknown IPs).
Confirm the webhook is POSTing to the correct base URL, especially behind proxies or Docker.
Run php artisan route:list and check that the route /api/v1/mailgun_inbound_webhook is active and accessible.