Skip to Content
📚 MyStoryFlow Docs — Your guide to preserving family stories
Email SystemAPI Reference

API Reference

Complete API documentation for the StoryFlow email management system, including endpoints, request/response formats, and code examples.

Authentication

All API endpoints require authentication using session-based auth or API tokens.

Headers

Authorization: Bearer <session_token> Content-Type: application/json ``` --> ### Permissions - **Admin APIs**: Require premium subscription tier (admin access) - **User APIs**: Require valid user session - **Webhook APIs**: Require webhook signature verification ## Admin APIs Admin endpoints for managing the email system (prefix: `/api/admin/email/`) ### Email Templates #### List Templates ```http GET /api/admin/email/templates ``` --> **Query Parameters:** | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `category` | string | Filter by category (`transactional`, `marketing`, etc.) | `all` | | `search` | string | Search in template name and description | - | | `status` | string | Filter by status (`active`, `inactive`, `all`) | `all` | | `limit` | number | Number of templates to return | `20` | | `offset` | number | Pagination offset | `0` | **Response:** ```json { "success": true, "templates": [ { "id": "uuid", "name": "welcome_new_user", "display_name": "Welcome to StoryFlow", "description": "Welcome email for new users", "category": "onboarding", "subject_template": "Welcome to StoryFlow, {{user_name}}!", "html_template": "<!DOCTYPE html>...", "text_template": "Welcome to StoryFlow...", "available_variables": { "user_name": "User's display name", "onboarding_url": "URL to start onboarding" }, "required_variables": ["user_name", "onboarding_url"], "is_active": true, "is_system": true, "total_sent": 1250, "total_opened": 875, "total_clicked": 234, "created_at": "2024-01-15T10:30:00Z", "updated_at": "2024-01-20T15:45:00Z" } ], "pagination": { "total": 15, "limit": 20, "offset": 0, "hasMore": false } } ``` --> #### Create Template ```http POST /api/admin/email/templates ``` --> **Request Body:** ```json { "name": "story_reminder_monthly", "display_name": "Monthly Story Reminder", "description": "Monthly reminder to continue working on stories", "category": "reminder", "subject_template": "Monthly check-in: {{story_title}}", "html_template": "<!DOCTYPE html><html>...</html>", "text_template": "Hi {{user_name}}...", "available_variables": { "user_name": "User's display name", "story_title": "Title of the story", "continue_url": "URL to continue the story" }, "default_variables": { "story_title": "Your Story" }, "required_variables": ["user_name", "continue_url"], "trigger_events": ["story_reminder"], "send_delay_hours": 0, "max_sends_per_user": null, "is_active": true } ``` --> **Response:** ```json { "success": true, "template": { "id": "new-template-uuid", "name": "story_reminder_monthly", // ... full template object }, "message": "Email template created successfully" } ``` --> #### Get Template ```http GET /api/admin/email/templates/{id} ``` --> **Response:** ```json { "success": true, "template": { // Full template object with all fields } } ``` --> #### Update Template ```http PUT /api/admin/email/templates/{id} ``` --> **Request Body:** Same as create template **Response:** ```json { "success": true, "template": { // Updated template object }, "message": "Template updated successfully" } ``` --> #### Delete Template ```http DELETE /api/admin/email/templates/{id} ``` --> **Response:** ```json { "success": true, "message": "Template deleted successfully" } ``` --> ### Email Analytics #### Get Analytics Data ```http GET /api/admin/email/analytics ``` --> **Query Parameters:** | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `period` | number | Number of days to analyze | `30` | | `template_id` | string | Filter by specific template | - | | `category` | string | Filter by email category | - | **Response:** ```json { "success": true, "period": 30, "overall_stats": { "total_sent": 5420, "total_delivered": 5298, "total_opened": 2115, "total_clicked": 423, "total_failed": 122, "delivery_rate": "97.75", "open_rate": "39.93", "click_rate": "20.00", "failure_rate": "2.25" }, "template_performance": [ { "id": "template-uuid", "name": "welcome_new_user", "display_name": "Welcome to StoryFlow", "category": "onboarding", "total_sent": 234, "total_delivered": 230, "total_opened": 145, "total_clicked": 67, "delivery_rate": "98.29", "open_rate": "63.04", "click_rate": "46.21" } ], "daily_trends": [ { "date": "2024-01-20", "sent": 45, "delivered": 44, "opened": 18, "clicked": 5 } ], "category_breakdown": [ { "category": "onboarding", "total_sent": 890, "total_delivered": 875, "total_opened": 523, "total_clicked": 234, "template_count": 3, "delivery_rate": "98.31", "open_rate": "59.77", "click_rate": "44.75" } ], "recent_activity": [ { "id": "email-uuid", "subject": "Welcome to StoryFlow, John!", "to_email": "john@example.com", "status": "sent", "created_at": "2024-01-22T10:30:00Z", "email_templates": { "name": "welcome_new_user", "display_name": "Welcome to StoryFlow", "category": "onboarding" } } ], "queue_status": { "pending": 12, "processing": 3 } } ``` --> ### A/B Testing #### Create A/B Test ```http POST /api/admin/email/ab-test ``` --> **Request Body:** ```json { "base_template_id": "base-template-uuid", "variant_name": "subject_test_1", "variant_display_name": "Subject Line Test Variant", "variant_subject": "🎉 Welcome to StoryFlow, {{user_name}}!", "variant_html": "<!DOCTYPE html>...", "variant_text": "Welcome text...", "test_percentage": 50, "test_duration_days": 7, "success_metric": "open_rate" } ``` --> **Response:** ```json { "success": true, "ab_test": { "id": "test-uuid", "name": "Welcome to StoryFlow - subject_test_1 Test", "base_template_id": "base-template-uuid", "variant_template_id": "variant-template-uuid", "test_percentage": 50, "success_metric": "open_rate", "status": "running", "start_date": "2024-01-22T10:30:00Z", "end_date": "2024-01-29T10:30:00Z" }, "base_template": { // Base template object }, "variant_template": { // Variant template object }, "message": "A/B test created successfully" } ``` --> #### List A/B Tests ```http GET /api/admin/email/ab-test ``` --> **Query Parameters:** | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `status` | string | Filter by status (`running`, `completed`, `paused`) | - | | `limit` | number | Number of tests to return | `20` | | `offset` | number | Pagination offset | `0` | **Response:** ```json { "success": true, "ab_tests": [ { "id": "test-uuid", "name": "Welcome Email Subject Test", "status": "completed", "base_template": { "id": "base-uuid", "name": "welcome_new_user", "display_name": "Welcome to StoryFlow" }, "variant_template": { "id": "variant-uuid", "name": "welcome_new_user_variant_emoji", "display_name": "Welcome to StoryFlow (Variant emoji)" }, "test_percentage": 50, "success_metric": "open_rate", "start_date": "2024-01-15T10:00:00Z", "end_date": "2024-01-22T10:00:00Z", "results": { "base_stats": { "sent": 127, "opened": 78, "clicked": 23, "open_rate": 0.6142, "click_rate": 0.2949 }, "variant_stats": { "sent": 131, "opened": 89, "clicked": 31, "open_rate": 0.6794, "click_rate": 0.3483 }, "winner": "variant", "confidence": 95, "is_significant": true, "improvement": "10.62", "total_samples": 258 } } ], "total": 1 } ``` --> ## User APIs User-facing endpoints for email management (prefix: `/api/user/emails/`) ### Received Emails #### List User's Emails ```http GET /api/user/emails/received ``` --> **Query Parameters:** | Parameter | Type | Description | Default | |-----------|------|-------------|---------| | `limit` | number | Number of emails to return | `50` | | `offset` | number | Pagination offset | `0` | | `unread_only` | boolean | Only return unread emails | `false` | **Response:** ```json { "success": true, "emails": [ { "id": "email-uuid", "subject": "Time to add to your story: Childhood Memories", "html_content": "<!DOCTYPE html>...", "text_content": "Hi John...", "template_variables": { "user_name": "John", "story_title": "Childhood Memories", "continue_url": "/stories/123/continue" }, "status": "sent", "created_at": "2024-01-22T10:30:00Z", "sent_at": "2024-01-22T10:31:00Z", "opened_at": null, "clicked_at": null, "email_templates": { "id": "template-uuid", "name": "story_reminder_weekly", "display_name": "Weekly Story Reminder", "category": "reminder" } } ], "total": 15, "limit": 50, "offset": 0, "has_more": false } ``` --> #### Mark Emails as Read/Clicked ```http POST /api/user/emails/received ``` --> **Request Body:** ```json { "email_ids": ["email-uuid-1", "email-uuid-2"], "action": "mark_opened" } ``` --> **Actions:** - `mark_opened`: Mark emails as opened/read - `mark_clicked`: Mark emails as clicked (also sets opened) **Response:** ```json { "success": true, "message": "2 emails marked as opened" } ``` --> ## Automation Service APIs Internal APIs for triggering email automation (used by other system components) ### Trigger Events #### Generic Event Trigger ```typescript import { emailAutomationService } from '@/lib/email/email-automation-service' await emailAutomationService.triggerEvent({ event: 'story_created', user_id: 'user-uuid', template_variables: { story_title: 'My New Story', story_url: '/stories/123' }, delay_hours: 0, conditions: { user_segment: 'active' } }) ``` --> #### Specific Event Methods **User Signup** ```typescript await emailAutomationService.triggerUserSignup('user-uuid', { user_name: 'John Doe', signup_source: 'web' }) ``` --> **Story Reminder** ```typescript await emailAutomationService.triggerStoryReminder('user-uuid', { story_id: 'story-uuid', story_title: 'Childhood Memories', last_updated: '2024-01-15' }) ``` --> **Family Invitation** ```typescript await emailAutomationService.triggerFamilyInvitation('user-uuid', { family_id: 'family-uuid', family_name: 'Smith Family', inviter_name: 'John Smith', invitation_token: 'abc123xyz' }) ``` --> ### Queue Processing #### Process Email Queue ```typescript // Process up to 50 emails from queue await emailAutomationService.processEmailQueue(50) ``` --> This method is typically called by a cron job or background service. ## Webhook APIs Endpoints for handling external service webhooks (prefix: `/api/webhooks/email/`) ### Resend Webhooks #### Email Events ```http POST /api/webhooks/email/resend ``` --> **Request Body (from Resend):** ```json { "type": "email.delivered", "created_at": "2024-01-22T10:32:00Z", "data": { "email_id": "provider-email-id", "to": "user@example.com", "subject": "Welcome to StoryFlow" } } ``` --> **Webhook Events:** - `email.sent`: Email was sent successfully - `email.delivered`: Email was delivered to inbox - `email.opened`: Recipient opened the email - `email.clicked`: Recipient clicked a link - `email.bounced`: Email bounced (hard or soft) - `email.complained`: Recipient marked as spam **Response:** ```json { "success": true, "message": "Event processed" } ``` --> ## Error Responses All endpoints use consistent error response format: ### Error Format ```json { "error": "Error message describing what went wrong", "code": "ERROR_CODE", "details": { "field": "specific field that caused the error", "value": "invalid value" } } ``` --> ### Common HTTP Status Codes | Status | Description | |--------|-------------| | `400` | Bad Request - Invalid request data | | `401` | Unauthorized - Authentication required | | `403` | Forbidden - Insufficient permissions | | `404` | Not Found - Resource doesn't exist | | `409` | Conflict - Resource already exists | | `422` | Unprocessable Entity - Validation failed | | `429` | Too Many Requests - Rate limit exceeded | | `500` | Internal Server Error - System error | ### Error Examples **Validation Error (400)** ```json { "error": "Missing required fields: name, subject_template, html_template", "code": "VALIDATION_ERROR", "details": { "missing_fields": ["name", "subject_template", "html_template"] } } ``` --> **Permission Error (403)** ```json { "error": "Admin access required", "code": "INSUFFICIENT_PERMISSIONS" } ``` --> **Not Found Error (404)** ```json { "error": "Email template not found", "code": "TEMPLATE_NOT_FOUND", "details": { "template_id": "invalid-uuid" } } ``` --> ## Rate Limits API endpoints have rate limits to prevent abuse: | Endpoint Group | Limit | Window | |----------------|-------|--------| | Admin APIs | 100 requests | 1 minute | | User APIs | 60 requests | 1 minute | | Webhook APIs | 1000 requests | 1 minute | **Rate Limit Headers:** ```http X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1640995200 ``` --> ## SDK Examples ### TypeScript/Node.js ```typescript import { StoryFlowEmailClient } from '@mystoryflow/email-sdk' const client = new StoryFlowEmailClient({ apiKey: process.env.STORYFLOW_API_KEY, baseUrl: 'https://mystoryflow.com/api' }) // List templates const templates = await client.admin.templates.list({ category: 'onboarding', limit: 10 }) // Create template const newTemplate = await client.admin.templates.create({ name: 'welcome_variant', display_name: 'Welcome Email Variant', category: 'onboarding', subject_template: 'Welcome {{user_name}}!', html_template: '<html>...</html>' }) // Get analytics const analytics = await client.admin.analytics.get({ period: 30, category: 'reminder' }) ``` --> ### cURL Examples **Create Template:** ```bash curl -X POST "https://mystoryflow.com/api/admin/email/templates" \ -H "Authorization: Bearer your-session-token" \ -H "Content-Type: application/json" \ -d '{ "name": "test_template", "display_name": "Test Template", "category": "system", "subject_template": "Test: {{user_name}}", "html_template": "<p>Hello {{user_name}}!</p>" }' ``` --> **Get Analytics:** ```bash curl "https://mystoryflow.com/api/admin/email/analytics?period=7" \ -H "Authorization: Bearer your-session-token" ``` --> **List User Emails:** ```bash curl "https://mystoryflow.com/api/user/emails/received?limit=10&unread_only=true" \ -H "Authorization: Bearer your-session-token" ``` --> For implementation details and code examples, see the [Technical Architecture](./technical-architecture) and [Setup Guide](./setup-configuration).