Skip to content

API Authentication

Learn how to authenticate with the Mailiam API, manage API keys, and implement secure authentication in your applications.

Mailiam uses API key authentication for server-side requests while supporting both authenticated and unauthenticated requests from browsers based on domain configuration.

  1. API Key Authentication - Required for server-side API calls
  2. Domain-Based Authentication - Allows form submissions from verified domains
  3. Collection-Based Authentication - Optional API key requirement for collections

Mailiam API keys follow a standardized format:

mlm_[environment]_[random_string]
Examples:
mlm_sk_live_abc123def456... # Production key
mlm_sk_test_xyz789abc123... # Test/development key
TypePrefixEnvironmentUse Case
Livemlm_sk_live_ProductionProduction applications
Testmlm_sk_test_DevelopmentTesting and development
Restrictedmlm_rk_AnyLimited permissions
Terminal window
# Create account and get API key
mailiam signup
# Check current key
mailiam auth status
  1. Log into Mailiam dashboard
  2. Navigate to API Keys section
  3. Generate new key with appropriate permissions
  4. Store securely in your application

For backend applications, include the API key in the request header:

Terminal window
curl -X POST https://api.mailiam.dev/projects \
-H "Authorization: Bearer mlm_sk_live_abc123..." \
-H "Content-Type: application/json" \
-d '{"name": "My Project"}'

Alternative header formats:

Terminal window
# X-Api-Key header
curl -H "X-Api-Key: mlm_sk_live_abc123..." \
https://api.mailiam.dev/projects
# Mailiam-Api-Key header
curl -H "Mailiam-Api-Key: mlm_sk_live_abc123..." \
https://api.mailiam.dev/projects

For browser form submissions to verified domains, no API key is required:

<!-- Direct form submission (no API key needed) -->
<form action="https://api.mailiam.dev/yourdomain.com/contact" method="POST">
<input name="name" placeholder="Name" required>
<input name="email" type="email" placeholder="Email" required>
<textarea name="message" placeholder="Message" required></textarea>
<button type="submit">Send</button>
</form>

For client-side applications that need API access:

// Note: Only expose API keys for trusted client-side apps
const response = await fetch('https://api.mailiam.dev/instant/forms', {
method: 'POST',
headers: {
'Authorization': 'Bearer mlm_sk_live_abc123...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Contact Form',
email: 'contact@example.com'
})
});

Public Endpoints (No Authentication Required)

Section titled “Public Endpoints (No Authentication Required)”
EndpointMethodDescription
/v1/{domain}/sendPOSTForm submission to verified domain
/c/{collection}/{form}POSTCollection form submission (if configured)
/f/{formId}POSTInstant form submission
EndpointMethodDescription
/projectsGET, POSTProject management
/domainsGET, POSTDomain management
/instant/formsGET, POSTInstant form management
/collectionsGET, POSTCollection management
/analyticsGETUsage analytics

Administrative Endpoints (Elevated Permissions)

Section titled “Administrative Endpoints (Elevated Permissions)”
EndpointMethodDescription
/admin/tenantsGET, POSTTenant management
/admin/usageGETGlobal usage statistics
/admin/billingGET, POSTBilling management
Terminal window
# Via CLI
mailiam auth create-key --name "Production API" --permissions "forms,domains"
# Via API
curl -X POST https://api.mailiam.dev/api-keys \
-H "Authorization: Bearer mlm_sk_live_existing_key..." \
-H "Content-Type: application/json" \
-d '{
"name": "Production API",
"permissions": ["forms", "domains", "analytics"],
"restrictions": {
"ip_whitelist": ["203.0.113.0/24"],
"rate_limit": 1000
}
}'

Configure granular permissions for API keys:

{
"permissions": [
"forms.read",
"forms.write",
"domains.read",
"domains.write",
"collections.read",
"collections.write",
"analytics.read",
"projects.read",
"projects.write"
],
"restrictions": {
"ip_whitelist": ["192.168.1.0/24", "203.0.113.10"],
"domain_restrictions": ["example.com", "api.example.com"],
"rate_limit": 5000,
"expires_at": "2024-12-31T23:59:59Z"
}
}

Regularly rotate API keys for security:

Terminal window
# Create new key
mailiam auth create-key --name "Production API v2"
# Test new key
export MAILIAM_API_KEY="mlm_sk_live_new_key..."
mailiam test config
# Update applications with new key
# Then revoke old key
mailiam auth revoke-key "old_key_id"

Store API keys as environment variables:

Terminal window
# Development
export MAILIAM_API_KEY="mlm_sk_test_abc123..."
# Production
export MAILIAM_API_KEY="mlm_sk_live_xyz789..."

Add to .gitignore:

# Environment files
.env
.env.local
.env.production
# Configuration files with secrets
mailiam.prod.yaml
config/production.yaml

Create keys with minimal required permissions:

Terminal window
# Key only for form submissions
mailiam auth create-key \
--name "Forms Only" \
--permissions "forms.write" \
--rate-limit 100
# Key only for reading analytics
mailiam auth create-key \
--name "Analytics Read" \
--permissions "analytics.read" \
--rate-limit 50

Limit API key usage to specific IP addresses:

{
"name": "Production API",
"restrictions": {
"ip_whitelist": [
"203.0.113.10", // Production server
"192.168.1.0/24", // Internal network
"2001:db8::/32" // IPv6 range
]
}
}

Set appropriate rate limits for each key:

{
"name": "High Volume API",
"restrictions": {
"rate_limit": 10000, // 10k requests per hour
"burst_limit": 100 // 100 requests per minute
}
}
pages/api/contact.js
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method not allowed' });
}
try {
const formData = new FormData();
Object.entries(req.body).forEach(([key, value]) => {
formData.append(key, value);
});
const response = await fetch('https://api.mailiam.dev/yourdomain.com/contact', {
method: 'POST',
headers: {
'X-Api-Key': process.env.MAILIAM_API_KEY
},
body: formData
});
if (response.ok) {
res.status(200).json({ message: 'Message sent successfully' });
} else {
const error = await response.json();
res.status(400).json({ error: error.message });
}
} catch (error) {
res.status(500).json({ error: 'Internal server error' });
}
}
const express = require('express');
const app = express();
// Middleware to add Mailiam API key
app.use('/api/mailiam', (req, res, next) => {
req.headers['x-api-key'] = process.env.MAILIAM_API_KEY;
next();
});
// Contact form endpoint
app.post('/api/contact', async (req, res) => {
const formData = new FormData();
Object.entries(req.body).forEach(([key, value]) => {
formData.append(key, value);
});
try {
const response = await fetch('https://api.mailiam.dev/yourdomain.com/contact', {
method: 'POST',
headers: {
'X-Api-Key': process.env.MAILIAM_API_KEY
},
body: formData
});
const result = await response.json();
res.json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
config/services.php
'mailiam' => [
'api_key' => env('MAILIAM_API_KEY'),
'base_url' => 'https://api.mailiam.dev',
],
// app/Services/MailiamService.php
<?php
namespace App\Services;
use Illuminate\Support\Facades\Http;
class MailiamService
{
protected $apiKey;
protected $baseUrl;
public function __construct()
{
$this->apiKey = config('services.mailiam.api_key');
$this->baseUrl = config('services.mailiam.base_url');
}
public function submitForm($domain, $form, $data)
{
$response = Http::withHeaders([
'X-Api-Key' => $this->apiKey,
])->post("{$this->baseUrl}/{$domain}/{$form}", $data);
return $response->json();
}
}

Handle authentication errors gracefully:

const submitForm = async (formData) => {
try {
const response = await fetch('https://api.mailiam.dev/yourdomain.com/contact', {
method: 'POST',
headers: {
'X-Api-Key': process.env.MAILIAM_API_KEY
},
body: formData
});
if (response.status === 401) {
throw new Error('Invalid API key');
}
if (response.status === 403) {
throw new Error('Insufficient permissions');
}
if (response.status === 429) {
throw new Error('Rate limit exceeded');
}
if (!response.ok) {
throw new Error('Request failed');
}
return await response.json();
} catch (error) {
console.error('Form submission error:', error);
throw error;
}
};
CodeMeaningResolution
200SuccessRequest processed successfully
400Bad RequestCheck request format and required fields
401UnauthorizedVerify API key is correct and active
403ForbiddenCheck API key permissions
404Not FoundVerify endpoint URL and domain
429Too Many RequestsImplement rate limiting and backoff
500Server ErrorContact support if persistent
Terminal window
# Test API key
curl -H "Authorization: Bearer mlm_sk_live_your_key..." \
https://api.mailiam.dev/projects
# Expected response for valid key:
{
"projects": [...],
"count": 5
}
# Expected response for invalid key:
{
"error": "Invalid API key",
"code": "AUTH_INVALID_KEY"
}
Terminal window
# Test specific permission
curl -H "Authorization: Bearer mlm_sk_live_your_key..." \
https://api.mailiam.dev/analytics
# Test form submission
curl -X POST https://api.mailiam.dev/yourdomain.com/contact \
-H "X-Api-Key: mlm_sk_live_your_key..." \
-F "name=Test User" \
-F "email=test@example.com" \
-F "message=Test message"
Terminal window
# Check API key status
mailiam auth status --debug
# Test API connectivity
mailiam test config --check-api
# Validate permissions
mailiam auth permissions --key-id "key_abc123"

Monitor API key usage:

Terminal window
# View API usage
mailiam analytics api-usage --last-30d
# View by API key
mailiam analytics api-usage --key "mlm_sk_live_abc123" --last-7d
# Export usage data
mailiam analytics export --type api-usage --format csv

Track rate limit usage:

Terminal window
# Check current rate limits
curl -H "Authorization: Bearer mlm_sk_live_your_key..." \
https://api.mailiam.dev/rate-limits
# Response includes current usage
{
"rate_limits": {
"requests_per_hour": {
"limit": 5000,
"remaining": 4847,
"reset_time": "2024-01-01T15:00:00Z"
},
"requests_per_minute": {
"limit": 100,
"remaining": 92,
"reset_time": "2024-01-01T14:31:00Z"
}
}
}

Q: Can I use API keys in frontend JavaScript? A: Only for trusted environments. Use domain-based authentication for public websites.

Q: How do I rotate API keys without downtime? A: Create a new key, test it, update your applications, then revoke the old key.

Q: What happens if I exceed rate limits? A: You’ll receive a 429 Too Many Requests response. Implement exponential backoff.

Q: Can I restrict API keys to specific domains? A: Yes, use domain restrictions when creating keys.

Proper API authentication ensures secure access to Mailiam’s services while maintaining the flexibility needed for various application architectures.