Email Preferences
Token-based email preference center — allow subscribers to manage their email preferences without login
The preferences API lets your subscribers update their own email preferences without logging in. Access is controlled by a signed token embedded in every unsubscribe and preference link MisarMail generates.
This is a token-based API — no API key or session cookie is required. The subscriber authenticates via a short-lived signed JWT included in outbound email links.
How the token works
Every email sent through MisarMail includes a unique, subscriber-specific signed JWT in the unsubscribe link:
https://mail.misar.io/preferences?token=eyJhbGciOiJIUzI1NiJ9...
The token encodes the subscriber's contact ID and expires after 7 days. An expired or tampered token returns 401.
Get preferences
/mail/api/preferencesReturns the subscriber's current category preferences and email frequency.
Query parameters
tokenstringqueryrequiredThe signed JWT from the preference link.
Response fields
successbooleantrue when the request succeeded.
emailstringThe subscriber's email, masked for privacy (u***@example.com).
preferencesobjectCurrent category preferences and frequency. If the subscriber has never visited the preference center before, all categories default to true and frequency defaults to "immediate".
{
"success": true,
"email": "u***@example.com",
"preferences": {
"marketing": true,
"productUpdates": true,
"newsletters": false,
"transactional": true,
"frequency": "weekly"
}
}The email field is masked for privacy — subscribers see enough to confirm it is their address.
Update preferences
/mail/api/preferencesUpdate the subscriber's category preferences and email frequency.
Request body
tokenstringbodyrequiredThe signed JWT from the preference link.
preferences.marketingbooleanbodyMarketing and promotional emails.
preferences.productUpdatesbooleanbodyProduct news and feature announcements.
preferences.newslettersbooleanbodyNewsletter subscriptions.
preferences.frequencystringbodyimmediate | daily | weekly | monthly | never.
Response fields
successbooleantrue when preferences were updated.
messagestringHuman-readable confirmation message.
preferencesobjectThe updated preferences, including the read-only transactional flag.
{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"preferences": {
"marketing": false,
"newsletters": false,
"frequency": "weekly"
}
}{
"success": true,
"message": "Preferences updated",
"preferences": {
"marketing": false,
"productUpdates": true,
"newsletters": false,
"transactional": true,
"frequency": "weekly"
}
}transactional emails (password reset, receipts, security alerts) cannot be disabled. The field is read-only and always returned as true.
Generate a preference token
/mail/v1/contacts/:id/preference-tokenIf you are building a custom preference center, generate a token via the contacts API and redirect the user to your own page. Requires an API key. Pass the returned token to your preference center page, then call PUT /api/preferences with it directly.
Path parameters
idstringpathrequiredID of the contact to generate a preference token for.
Response fields
tokenstringThe signed JWT to embed in your custom preference link.
expires_atstringISO-8601 expiry time of the token.
curl -X POST https://api.misar.io/mail/v1/contacts/em_abc123/preference-token \
-H "Authorization: Bearer msk_..."{ "token": "eyJhbGciOiJIUzI1NiJ9...", "expires_at": "2025-06-21T10:00:00Z" }Embedding a preferences link
MisarMail automatically adds unsubscribe and preference links when you send campaigns. For custom HTML emails, inject the link using the {{preferences_url}} merge tag:
<a href="{{preferences_url}}">Manage email preferences</a>
Security
- Email addresses are masked in GET responses (
u***@example.com) to prevent email harvesting via leaked tokens - Tokens are signed with HMAC-SHA256 and include an expiry — they cannot be forged or extended
- The endpoint is rate limited by IP to prevent token enumeration attacks
- Invalid or expired tokens return
401 Unauthorizedwith no further detail
Example
# Get preferences
curl "https://api.misar.io/mail/api/preferences?token=eyJhbGciOiJIUzI1NiJ9..."
# Update preferences
curl -X PUT https://api.misar.io/mail/api/preferences \
-H "Content-Type: application/json" \
-d '{
"token": "eyJhbGciOiJIUzI1NiJ9...",
"preferences": { "marketing": false, "frequency": "weekly" }
}'// Typically called from your preference center page
const token = new URLSearchParams(window.location.search).get('token');
// Fetch current preferences
const res = await fetch(`/api/preferences?token=${token}`);
const { preferences } = await res.json();
// Save changes
await fetch('/api/preferences', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, preferences: { marketing: false } }),
});