Appearance
Authentication
MailShield API uses Bearer token authentication combined with optional IP allowlisting.
Creating an API Token
Organization owners and admins can create tokens:
- Navigate to Settings > API in your MailShield dashboard
- Click Create Token
- Enter a descriptive name (e.g., "Production Monitoring")
- Optionally set an expiration date
- Optionally make the token read-only
- Optionally add allowed IP addresses or CIDR ranges
- Click Create Token
Important
Your API token will only be displayed once. Copy it immediately and store it securely.
Using Your Token
Include your token in the Authorization header of every request:
bash
curl -H "Authorization: Bearer ms_your_token_here" \
https://app.mailshield.app/api/v1/domainsPython Example
python
import requests
headers = {
"Authorization": "Bearer ms_your_token_here"
}
response = requests.get(
"https://app.mailshield.app/api/v1/domains",
headers=headers
)
data = response.json()
print(data["data"])Node.js Example
javascript
const response = await fetch('https://app.mailshield.app/api/v1/domains', {
headers: {
'Authorization': 'Bearer ms_your_token_here'
}
});
const { data } = await response.json();
console.log(data);Token Format
MailShield tokens follow this format:
- Prefix:
ms_ - Body: 32 bytes of cryptographically random data (base64url encoded)
- Example:
ms_Abc123XyzDefGhi456JklMnoP789QrsT
The ms_ prefix helps identify MailShield tokens and prevents accidentally using tokens from other services.
Read-only Tokens
A read-only token can only make GET requests. Anything else (POST, PATCH, DELETE) returns 403 Forbidden:
json
{
"error": {
"code": "forbidden",
"message": "This token is read-only."
}
}Use read-only tokens for dashboards and reporting. The setting is chosen when the token is created and can't be changed afterwards.
IP Allowlisting
For enhanced security, you can restrict token usage to specific IP addresses:
- Single IP:
192.168.1.100or2001:db8::1 - CIDR range:
10.0.0.0/8or2001:db8::/32 - Multiple entries: One per line in the settings UI
Entries that aren't a valid IP address or CIDR range are rejected when you save. IPv6 entries match however the address is written (case and abbreviation don't matter), and an IPv4 entry also matches the same address in IPv4-mapped IPv6 form.
When an IP allowlist is configured:
- Requests from allowed IPs proceed normally
- Requests from other IPs receive a
403 Forbiddenresponse that names the IP the request came from
Best Practice
For production integrations, always configure an IP allowlist to limit the blast radius if a token is compromised.
Token Expiration
Tokens can be configured to expire on a specific date:
- Never (default): the token remains valid until revoked
- Custom date: the token works until 23:59 UTC on that date
After expiration, the token returns 401 Unauthorized on all requests.
Revoking Tokens
To revoke a token:
- Go to Settings > API
- Find the token in the list
- Click the revoke button
- Confirm the action
Revoked tokens:
- Cannot be restored
- Return
401 Unauthorizedon subsequent requests - Keep their activity log (the last 100 requests from the past 30 days) and audit trail
Security Best Practices
- Never commit tokens to version control: use environment variables
- Use read-only tokens for anything that only reads data
- Rotate tokens periodically: create new tokens and revoke old ones
- Use IP allowlisting: restrict where tokens can be used from
- Set expiration dates, especially for temporary integrations
- Use descriptive names so you know which token is used where
- Monitor usage: check "Last Used" and the token's activity to detect anomalies
Authentication Errors
| Code | Status | Description |
|---|---|---|
unauthorized | 401 | Missing or invalid Authorization header |
unauthorized | 401 | Invalid, revoked or expired API token |
forbidden | 403 | Request from an IP address outside the token's allowlist |
forbidden | 403 | Read-only token used for a request other than GET |
forbidden | 403 | The plan doesn't include API access (upgrade required) |
forbidden | 403 | API access is paused because a payment is overdue |