MisarMisar Docs
MisarMailMisar.BlogMisarReachMisarPostMisar.DevMisarSEOMisar PlatformMisar SSO
API Reference

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

GET/mail/api/preferences

Returns the subscriber's current category preferences and email frequency.

Query parameters

tokenstringqueryrequired

The signed JWT from the preference link.

Response fields

successboolean

true when the request succeeded.

emailstring

The subscriber's email, masked for privacy (u***@example.com).

preferencesobject

Current 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

PUT/mail/api/preferences

Update the subscriber's category preferences and email frequency.

Request body

tokenstringbodyrequired

The signed JWT from the preference link.

preferences.marketingbooleanbody

Marketing and promotional emails.

preferences.productUpdatesbooleanbody

Product news and feature announcements.

preferences.newslettersbooleanbody

Newsletter subscriptions.

preferences.frequencystringbody

immediate | daily | weekly | monthly | never.

Response fields

successboolean

true when preferences were updated.

messagestring

Human-readable confirmation message.

preferencesobject

The updated preferences, including the read-only transactional flag.

{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "preferences": {
    "marketing": false,
    "newsletters": false,
    "frequency": "weekly"
  }
}
{
  "success": true,
  "message": "Preferences updated successfully",
  "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.

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 Unauthorized with 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 } }),
});