A secure proxy endpoint for Mailerlite API requests to keep API keys private and prevent exposure in public WordPress plugins.
- Overview
- Quick Start
- Installation
- Configuration
- API Documentation
- Security
- Testing & Verification
- Troubleshooting
- Remote Deployment Guide
- Changelog
- Support
This plugin was created to solve a security issue where the Mailerlite API key was hardcoded in the Ultimate Dashboard plugin (a public WordPress plugin). By using this proxy, the API key is kept private on the server while the plugin communicates through a secure REST API endpoint.
Ultimate Dashboard Plugin → Proxy Endpoint (this plugin) → Mailerlite API
Benefits:
- API key is no longer exposed in public plugin code
- Centralized API key management
- Easier to rotate keys without updating multiple plugins
Known Limitation:
- The proxy endpoint URL is still visible in the public plugin code
- Potential for endpoint spam (mitigated by WordPress nonce and capability checks)
-
Activate Plugin
WordPress Admin → Plugins → Activate "Mailerlite Proxy" -
Secure API Key (Optional but Recommended)
// Add to wp-config.php define( 'MAILERLITE_API_KEY', 'your-mailerlite-api-key-here' );
-
Test
Go to Ultimate Dashboard onboarding → Subscribe with test email
- Upload the
mailerlite-proxyfolder to/wp-content/plugins/ - Activate the plugin through the 'Plugins' menu in WordPress
- Configure the API key (see Configuration section below)
- Flush permalinks: Settings → Permalinks → Save Changes
Add the following line to your wp-config.php file (above the "That's all, stop editing!" line):
define( 'MAILERLITE_API_KEY', 'your-mailerlite-api-key-here' );If your hosting supports environment variables, set:
MAILERLITE_API_KEY=your-mailerlite-api-key-hereThen update line 151 in mailerlite-proxy.php:
$api_key = getenv( 'MAILERLITE_API_KEY' ) ?: 'fallback-key';The plugin has a fallback API key hardcoded for development. For production, use Option 1 or 2.
For maximum security, deploy this plugin to a separate WordPress installation. See Remote Deployment Guide below.
Endpoint: POST /wp-json/mailerlite-proxy/v1/subscribe
Authentication:
- Local: WordPress REST API nonce (X-WP-Nonce header)
- Remote: Proxy API Key (X-Proxy-API-Key header)
Required Capability: manage_options (local deployment only)
Parameters:
email(string, required) - Subscriber email addressname(string, required) - Subscriber namegroup_id(string, required) - Mailerlite group ID
- Onboarding Wizard:
112818510 - Plugin Onboarding:
111311793
wp.apiFetch({
path: '/mailerlite-proxy/v1/subscribe',
method: 'POST',
data: {
email: 'user@example.com',
name: 'John Doe',
group_id: '112818510'
}
});$response = wp_remote_post(
rest_url( 'mailerlite-proxy/v1/subscribe' ),
[
'body' => wp_json_encode([
'email' => 'user@example.com',
'name' => 'John Doe',
'group_id' => '112818510',
]),
'headers' => [
'Content-Type' => 'application/json',
'X-WP-Nonce' => wp_create_nonce( 'wp_rest' ),
],
'timeout' => 15,
]
);
if ( ! is_wp_error( $response ) ) {
$response_code = wp_remote_retrieve_response_code( $response );
if ( $response_code >= 200 && $response_code < 300 ) {
// Success
}
}curl -X POST https://yourdomain.com/wp-json/mailerlite-proxy/v1/subscribe \
-H "Content-Type: application/json" \
-H "X-WP-Nonce: YOUR_NONCE" \
-d '{
"email": "test@example.com",
"name": "Test User",
"group_id": "112818510"
}'Success:
{
"success": true,
"message": "Successfully subscribed to mailing list.",
"data": {
// Mailerlite API response data
}
}Error:
{
"code": "invalid_email",
"message": "Invalid or missing email address.",
"data": {
"status": 400
}
}- WordPress Nonce Verification - Prevents CSRF attacks
- Capability Check - Only users with
manage_optionscapability can use the endpoint - Input Sanitization - All inputs are sanitized before processing
- Email Validation - Ensures valid email addresses
- API Key Isolation - API key never exposed to client-side code
- Timing-Safe Comparison - Uses
hash_equals()for API key validation
The proxy plugin supports two authentication methods:
- Used when proxy is on the same WordPress site
- Requires logged-in user with
manage_optionscapability - Header:
X-WP-Nonce: [nonce]
- Used when proxy is on a different WordPress site
- No user login required
- Header:
X-Proxy-API-Key: [your-secure-key]
✅ Mailerlite API key never exposed to public
✅ Proxy API key in wp-config.php (not in code)
✅ API key authentication with hash_equals() (timing-attack safe)
✅ Separate server isolates sensitive operations
Rate Limiting (Optional):
// Add to mailerlite-proxy.php in check_permission method
$user_id = get_current_user_id();
$transient_key = 'mailerlite_proxy_rate_limit_' . $user_id;
$request_count = get_transient( $transient_key );
if ( false === $request_count ) {
set_transient( $transient_key, 1, HOUR_IN_SECONDS );
} elseif ( $request_count >= 10 ) { // Max 10 requests per hour
return new WP_Error(
'rate_limit_exceeded',
__( 'Too many requests. Please try again later.', 'mailerlite-proxy' ),
[ 'status' => 429 ]
);
} else {
set_transient( $transient_key, $request_count + 1, HOUR_IN_SECONDS );
}IP Whitelist (Optional):
// Add to proxy plugin's check_permission() method
$allowed_ips = [ '123.456.789.0', '98.765.432.1' ];
$client_ip = $_SERVER['REMOTE_ADDR'];
if ( ! in_array( $client_ip, $allowed_ips, true ) ) {
return new WP_Error( 'ip_blocked', 'Access denied', [ 'status' => 403 ] );
}- Plugin files created in
wp-content/plugins/mailerlite-proxy/ - Ultimate Dashboard subscribe classes updated
- API key removed from Ultimate Dashboard plugin files
- Permalinks flushed
Steps:
- Navigate to Ultimate Dashboard onboarding wizard
- Fill in name and email fields
- Submit the subscription form
- Expected: Success message appears
Verification:
- Check Mailerlite group
112818510for new subscriber - Check browser console for any errors
- Verify no API key visible in Network tab
Steps:
- Navigate to Ultimate Dashboard plugin onboarding
- Fill in name and email fields
- Submit the subscription form
- Expected: Success message appears
Verification:
- Check Mailerlite group
111311793for new subscriber - Check browser console for any errors
- Verify no API key visible in Network tab
Steps:
- Try subscribing with invalid email (e.g., "notanemail")
- Expected: Error message about invalid email
Verification:
- Error message displayed to user
- No subscription created in Mailerlite
Steps:
- Try subscribing with empty name or email
- Expected: Error message about required fields
Verification:
- Error message displayed to user
- No subscription created in Mailerlite
Steps:
- Log out of WordPress
- Try to access the proxy endpoint directly
- Expected: 403 Forbidden error
Verification:
- Request blocked by permission check
- Error message about authentication
Steps:
- Log in as a user without
manage_optionscapability (e.g., Subscriber) - Try to use the subscription form
- Expected: Permission error
Verification:
- Request blocked by capability check
- Error message about permissions
Request to Proxy:
POST /wp-json/mailerlite-proxy/v1/subscribe
Headers:
Content-Type: application/json
X-WP-Nonce: [nonce-value]
Body:
{
"email": "test@example.com",
"name": "Test User",
"group_id": "112818510"
}
- ❌
X-MailerLite-ApiKeyheader in browser requests - ❌ API key in request/response bodies
- ❌ Direct requests to
api.mailerlite.com
What the Server Does (Hidden from Browser)
Proxy Plugin → Mailerlite API
Headers:
X-MailerLite-ApiKey: [hidden-api-key]
Content-Type: application/json
Expected Response Times:
- Proxy endpoint: < 100ms (local processing)
- Mailerlite API: 200-500ms (external API)
- Total (Local): 300-600ms
- Total (Remote): 400-750ms (includes network latency)
If Slower:
- Check server resources
- Verify Mailerlite API status
- Check network connectivity
- Plugin activated
- API key secured (wp-config.php)
- Test subscription successful
- Subscriber appears in Mailerlite
- No API key in browser network tab
- Error handling works
- Performance acceptable
| Issue | Cause | Solution |
|---|---|---|
| Invalid security token | Nonce verification failed | Log in as admin, clear cache, verify REST API accessible |
| Permission denied | User lacks manage_options |
Log in as Administrator |
| 404 error | Permalinks not flushed | Settings → Permalinks → Save Changes |
| Mailerlite API error | Invalid API key or group ID | Check API key and group ID validity |
| Connection timeout | Remote server unreachable | Verify server is online, check DNS, test endpoint manually |
| Invalid proxy API key | Keys don't match between sites | Verify MAILERLITE_PROXY_API_KEY is identical on both sites |
| Proxy API key not configured | Constant not defined on remote | Add constant to remote server's wp-config.php |
| CORS errors | Cross-origin request blocked | WordPress REST API handles CORS by default, check server config |
- Ensure user is logged in
- Clear browser cache
- Check if REST API is accessible
- Verify nonce is being sent in
X-WP-Nonceheader
- Verify API key is correct
- Check group ID is valid
- Ensure server can reach
api.mailerlite.com - Check Mailerlite API status page
- Go to Settings → Permalinks → Save Changes
- Deactivate and reactivate the plugin
- Check if REST API is enabled
- Add to wp-config.php:
define( 'MAILERLITE_API_KEY', 'your-key' ); - Or dismiss the notice (it will show again on next page load)
For maximum security, deploy this plugin to a separate WordPress installation.
[Ultimate Dashboard Plugin]
↓ (WordPress Nonce)
[Mailerlite Proxy Plugin] (same site)
↓ (Mailerlite API Key)
[Mailerlite API]
[Ultimate Dashboard Plugin] (public site)
↓ (Proxy API Key)
[Mailerlite Proxy Plugin] (private API server)
↓ (Mailerlite API Key)
[Mailerlite API]
-
Create a new WordPress installation
Domain: api.yourdomain.com (or subdomain of your choice) -
Harden the WordPress installation
- Disable XML-RPC
- Disable file editing
- Enable strong passwords
- Install security plugin (e.g., Wordfence)
- Keep WordPress core updated
- Remove unused themes/plugins
-
Upload the Mailerlite Proxy plugin
Upload: wp-content/plugins/mailerlite-proxy/ -
Activate the plugin
WordPress Admin → Plugins → Activate "Mailerlite Proxy"
Add these constants to wp-config.php on the remote API server:
// Mailerlite API key (keep this secret!)
define( 'MAILERLITE_API_KEY', 'your-mailerlite-api-key-here' );
// Proxy API key for authentication (generate a strong random key)
define( 'MAILERLITE_PROXY_API_KEY', 'your-secure-random-key-here' );Generate a secure random key:
# Linux/Mac
openssl rand -base64 32
# Or use online generator
# https://www.random.org/strings/Example:
define( 'MAILERLITE_PROXY_API_KEY', 'K8vN2pQ9mR5tY7wZ3xC6bV4nM1hG0jF8' );Add these constants to wp-config.php on the Ultimate Dashboard site (public site):
// Remote proxy endpoint URL
define( 'MAILERLITE_PROXY_URL', 'https://api.yourdomain.com/wp-json/mailerlite-proxy/v1/subscribe' );
// Proxy API key (must match the key on remote server)
define( 'MAILERLITE_PROXY_API_KEY', 'K8vN2pQ9mR5tY7wZ3xC6bV4nM1hG0jF8' );Important: The MAILERLITE_PROXY_API_KEY must be identical on both sites.
-
Test from Ultimate Dashboard site
- Go to Ultimate Dashboard onboarding wizard
- Fill in name and email
- Submit subscription
-
Check the response
- Should see success message
- Check Mailerlite dashboard for new subscriber
-
Check logs
- Remote server: Check WordPress error logs
- Ultimate Dashboard site: Check browser console
File: wp-config.php
// Mailerlite API credentials
define( 'MAILERLITE_API_KEY', 'your-mailerlite-api-key-here' );
// Proxy authentication key
define( 'MAILERLITE_PROXY_API_KEY', 'K8vN2pQ9mR5tY7wZ3xC6bV4nM1hG0jF8' );Plugins:
- Mailerlite Proxy (active)
- Security plugin (recommended)
File: wp-config.php
// Remote proxy endpoint
define( 'MAILERLITE_PROXY_URL', 'https://api.yourdomain.com/wp-json/mailerlite-proxy/v1/subscribe' );
// Proxy authentication key (same as remote server)
define( 'MAILERLITE_PROXY_API_KEY', 'K8vN2pQ9mR5tY7wZ3xC6bV4nM1hG0jF8' );Plugins:
- Ultimate Dashboard (with updated subscribe classes)
- Plugin activated
-
MAILERLITE_API_KEYdefined in wp-config.php -
MAILERLITE_PROXY_API_KEYdefined in wp-config.php - Endpoint accessible:
/wp-json/mailerlite-proxy/v1/subscribe - SSL certificate valid (HTTPS)
-
MAILERLITE_PROXY_URLdefined in wp-config.php -
MAILERLITE_PROXY_API_KEYdefined in wp-config.php - Subscription form works
- Success message appears
- Subscriber added to Mailerlite
- API key not visible in browser network tab
- Invalid API key rejected
- Request without API key rejected
- HTTPS enforced
-
Subscription Success Rate
- Track successful vs failed subscriptions
- Alert on sudden drops
-
API Response Times
- Monitor remote proxy latency
- Alert on slow responses (>2 seconds)
-
Error Logs
- Check remote server logs daily
- Look for authentication failures
- Monitor for suspicious activity
-
Mailerlite Account
- Verify subscriptions are being added
- Check for duplicate entries
- Monitor API usage limits
Weekly:
- Review error logs
- Check subscription success rate
- Verify API keys still valid
Monthly:
- Update WordPress core on API server
- Update plugins on API server
- Review security logs
- Test failover procedures
Quarterly:
- Rotate proxy API key
- Security audit
- Performance review
- Update documentation
If remote deployment fails:
-
Remove constants from Ultimate Dashboard site
// Comment out or remove these lines // define( 'MAILERLITE_PROXY_URL', '...' ); // define( 'MAILERLITE_PROXY_API_KEY', '...' );
-
Install proxy plugin locally
- Upload to Ultimate Dashboard site
- Activate plugin
- Add
MAILERLITE_API_KEYto wp-config.php
-
Test local deployment
- Subscription should work with WordPress nonce
- No remote API key needed
- Initial release
- Secure proxy endpoint for Mailerlite subscriptions
- WordPress REST API integration
- Nonce and capability verification
- Remote deployment support with API key authentication
For issues or questions, contact MapSteps support.
This plugin is proprietary software developed by MapSteps.
Version: 1.0.0
Last Updated: 2025-10-06
Author: MapSteps