getEmailPreferences

Public token (HMAC) callable

Read a guest's email-preference flags by HMAC token (unauthenticated, CAN-SPAM compliant).

METHOD POST
PATH /getEmailPreferences
AUTH Public token (HMAC)

Anonymous endpoint backing the unsubscribe link in every lifecycle email. Gated on a short-lived HMAC-SHA256 token bound to a userId + 30-day expiry + scope="email-prefs", signed with EMAIL_PREFS_SECRET. Rate-limited to 20 calls per IP per hour, fail-open to never block a legitimate opt-out.

AUTH NOTE

No Firebase Auth required. Gated on a short-lived HMAC-signed token that the platform embeds in the relevant link (unsubscribe email, etc.).

Request

FieldTypeRequiredDescription
token string yes HMAC-SHA256 signed token in `payload.sig` format. Max 4096 chars.

EXAMPLE BODY

{
  "token": "eyJ1c2VySWQiOiJ1XzAxSFY5WFQiLCJleHAiOjE3MTk1MDA4NjAwMDAsInNjb3BlIjoiZW1haWwtcHJlZnMifQ.x7Hk9aBcDeFgHiJkLmNoPqRsTu0"
}

Response

FieldTypeAlways presentDescription
email string yes The user's email address. Returns empty string if user doc not found.
preferences.lifecycle boolean yes Lifecycle drips (welcome, first event, pre-event nudges, dormant tenant).
preferences.transactional boolean yes Always true — receipts, password resets, security alerts are legally required.
preferences.recap boolean yes Post-event recap emails sent by event organizers.
preferences.marketing boolean yes Product news, releases, and announcements.

EXAMPLE BODY

{
  "email": "[email protected]",
  "preferences": {
    "lifecycle": true,
    "transactional": true,
    "recap": true,
    "marketing": false
  }
}

curl

curl -X POST https://us-central1-freedomgrc-photowall.cloudfunctions.net/getEmailPreferences \
  -H "Content-Type: application/json" \
  -d '{"data":{"token":"<your-prefs-token>"}}'

JavaScript

We don't ship a first-party JS SDK yet (it's on the roadmap). For callable endpoints, the Firebase Functions SDK is the recommended path — it handles ID-token attachment and payload framing. Plain fetch works too.

const response = await fetch(
  'https://us-central1-freedomgrc-photowall.cloudfunctions.net/getEmailPreferences',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ data: { token: prefsToken } }),
  },
);
const { result } = await response.json();
// result === { email: '...', preferences: { ... } }

Error cases

CodeWhen
invalid-argument Token missing or longer than 4096 chars.
permission-denied Token signature invalid, expired, or wrong scope. Single message — does not leak which check failed.
internal Firestore user lookup failed. Sentry-reported.

Need a different shape?

The API surface is small. Tell us what you need and we'll work backward from your integration.

Request an endpoint Back to API index