sendEventRecap
Tenant-admin-triggered post-event recap blast to every guest who uploaded.
POST /sendEventRecap Sends a recap email to every unique guest email captured on approved photos. Two modes: `personal` (each guest sees their own photos) and `all` (each guest sees the event-wide highlight reel). Atomic recap-in-progress lock prevents double-sends. 24h cooldown per event. Honors lifecycle opt-outs (CAN-SPAM / CASL / GDPR). Up to 5000 recipients per call.
AUTH NOTE
Requires a Firebase Auth ID token with role=admin (or superadmin) custom claim. Tenant-scoped unless invoked by a superadmin with an explicit tenantId.
Request
| Field | Type | Required | Description |
|---|---|---|---|
eventId | string | yes | Your Fotowall event ID. |
subject | string | no | Override the templated subject line. Max 200 chars. Newlines are stripped (header injection defense). |
message | string | no | Optional custom paragraph rendered inside the recap email. Max 4000 chars. |
mode | "personal" | "all" | no | Per-guest personalized photos (default) or shared event-wide recap. |
EXAMPLE BODY
{
"eventId": "spring-gala-2026",
"subject": "Your photos from Spring Gala 2026",
"message": "Thank you for being part of an unforgettable night.",
"mode": "personal"
} Response
| Field | Type | Always present | Description |
|---|---|---|---|
sent | number | yes | How many recipients received the email. |
skipped | number | no | Recipients skipped due to opt-out or invalid email. |
message | string | no | Short status note when sent=0 (e.g., "No approved photos found"). |
EXAMPLE BODY
{
"sent": 284,
"skipped": 12
} curl
# Requires a Firebase Auth ID token in the Authorization header.
curl -X POST https://us-central1-freedomgrc-photowall.cloudfunctions.net/sendEventRecap \
-H "Authorization: Bearer <firebase-id-token>" \
-H "Content-Type: application/json" \
-d '{
"data": {
"eventId": "spring-gala-2026",
"subject": "Your photos from Spring Gala 2026",
"mode": "personal"
}
}' 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.
// Use the Firebase JS SDK callable wrapper — it handles token + payload framing.
import { getFunctions, httpsCallable } from 'firebase/functions';
const functions = getFunctions(app, 'us-central1');
const sendRecap = httpsCallable(functions, 'sendEventRecap');
const result = await sendRecap({
eventId: 'spring-gala-2026',
subject: 'Your photos from Spring Gala 2026',
mode: 'personal',
});
// result.data === { sent: 284, skipped: 12 } Error cases
| Code | When |
|---|---|
unauthenticated | No Firebase Auth ID token in the request. |
permission-denied | Caller is not admin/moderator of the event's tenant (and not superadmin). |
invalid-argument | eventId malformed, subject/message exceeds length cap, or mode is not "personal"/"all". |
not-found | No event at events/{eventId}. |
aborted | A recap send is already in progress for this event. |
resource-exhausted | Recap already sent in the last 24 hours. |
internal | Resend dispatch or 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.