setEmailPreferences
Update a guest's email preferences via the same HMAC token (CAN-SPAM / CASL / GDPR Art. 7(3) compliant).
POST /setEmailPreferences The opt-out write-side of the unsubscribe flow. Accepts the same token used by getEmailPreferences plus a `preferences` patch of booleans. Merges into users/{uid}.emailPreferences. Transactional emails are legally required and cannot be turned off — any client-submitted `transactional: false` is silently ignored. Two rate limits stack: 20 calls/IP/hour AND 10 writes/token/24h, both fail-open.
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
| Field | Type | Required | Description |
|---|---|---|---|
token | string | yes | Same HMAC token format as getEmailPreferences. |
preferences.lifecycle | boolean | no | Lifecycle drip subscription. |
preferences.recap | boolean | no | Event-recap email subscription. |
preferences.marketing | boolean | no | Product / marketing subscription. |
EXAMPLE BODY
{
"token": "eyJ1c2VySWQiOiJ1XzAxSFY5WFQiLCJleHAiOjE3MTk1MDA4NjAwMDAsInNjb3BlIjoiZW1haWwtcHJlZnMifQ.x7Hk9aBcDeFgHiJkLmNoPqRsTu0",
"preferences": {
"lifecycle": false,
"marketing": false
}
} Response
| Field | Type | Always present | Description |
|---|---|---|---|
ok | boolean | yes | Always true on successful write. |
updated | string | yes | ISO 8601 UTC timestamp of the write. |
EXAMPLE BODY
{
"ok": true,
"updated": "2026-05-21T14:22:08.000Z"
} curl
curl -X POST https://us-central1-freedomgrc-photowall.cloudfunctions.net/setEmailPreferences \
-H "Content-Type: application/json" \
-d '{
"data": {
"token": "<your-prefs-token>",
"preferences": { "lifecycle": false, "marketing": false }
}
}' 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/setEmailPreferences',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
data: {
token: prefsToken,
preferences: { lifecycle: false, marketing: false },
},
}),
},
);
const { result } = await response.json();
// result === { ok: true, updated: '...' } Error cases
| Code | When |
|---|---|
invalid-argument | Token missing/malformed, or preferences is not an object of booleans, or a non-toggleable key was sent. |
permission-denied | Token signature invalid, expired, or wrong scope. |
internal | Firestore write failed. |
Need a different shape?
The API surface is small. Tell us what you need and we'll work backward from your integration.