Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt

Use this file to discover all available pages before exploring further.

Version: 1.1.0
Last Updated: 2026-03-11
This guide documents how to configure email and SMS notification services for the Encore Health OS Platform.

Table of Contents

  1. Overview
  2. Email Service (Entra ID & Gmail)
  3. SMS Service (Twilio)
  4. Template Configuration
  5. Rate Limiting & Quotas
  6. Cost Optimization
  7. Error Handling
  8. Testing
  9. Troubleshooting

Overview

Encore Health OS uses external services for email and SMS delivery:
  • Email: Microsoft Entra ID (Graph API) or Gmail (Google Workspace) — org-level sending. Configure per organization in HR Settings and Settings → Integrations.
  • SMS: Twilio (primary provider)
Email is sent via the shared email-provider abstraction used by:
  • send-email-notification - Single notification delivery
  • send-pending-notifications - Batch processing
  • hr-portal-invite, hr-reference-request, hr-send-communication, hr-test-email - HR recruitment
  • automation-executor - Workflow send-email actions
  • Signature flows: send-signature-request, send-signature-reminder, auto-signature-reminders use the shared email-provider (Entra/Gmail) per organization.

Email Service (Entra ID & Gmail)

Org-level email supports two providers. Choose one per organization in HR → Settings → Email Provider (and optionally set a fallback).
  1. Configure the Entra ID integration in Settings → Integrations → Microsoft Entra ID (tenant, app registration, admin consent with Mail.Send).
  2. Set the sender email in the same page (or in pf_organizations.settings.entra_sender_email).
  3. Set ENTRA_CLIENT_SECRET in Supabase secrets (client secret for the app registration).
  4. In HR → Settings → Email, select Microsoft Entra ID and optionally set From Email Address / From Name.
If Entra is selected but fails (e.g. token issue), the system can fall back to Gmail when Gmail is configured for the org.

Gmail (Google Workspace)

  1. Google Cloud: Create a project, enable Gmail API, create a service account.
  2. Domain-wide delegation: In Google Workspace Admin, grant the service account domain-wide delegation for scope https://www.googleapis.com/auth/gmail.send.
  3. Supabase secret: Set the service account JSON as a secret:
    supabase secrets set GMAIL_SERVICE_ACCOUNT_JSON='{"type":"service_account","project_id":"...","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n","client_email":"...@....iam.gserviceaccount.com",...}'
    
  4. Per-organization sender: In Settings → Integrations → Google Workspace (Gmail), set Sender email address to the Gmail/Workspace user to impersonate (e.g. recruiting@yourcompany.com). This is stored in pf_organizations.settings.gmail_sender_email.
  5. In HR → Settings → Email, select Gmail (Google Workspace) and optionally set From Email Address / From Name.
Required secret: GMAIL_SERVICE_ACCOUNT_JSON (full JSON key for the service account). Edge functions: All email senders use supabase/functions/_shared/email-provider.ts; no separate provider-specific integration is required beyond Entra/Gmail configuration.

SMS Service (Twilio)

1. Create Twilio Account

  1. Go to Twilio
  2. Sign up for account
  3. Verify phone number

2. Get Credentials

Account SID:
  1. Go to ConsoleAccountAPI Keys & Tokens
  2. Copy Account SID (starts with AC)
Auth Token:
  1. Same page as Account SID
  2. Click Show next to Auth Token
  3. Copy Auth Token
Phone Number:
  1. Go to Phone NumbersManageActive Numbers
  2. Purchase phone number (or use trial number)
  3. Copy phone number (format: +1234567890)

3. Set Supabase Secrets

# Set Twilio credentials
supabase secrets set TWILIO_ACCOUNT_SID=ACxxxxx
supabase secrets set TWILIO_AUTH_TOKEN=xxxxx
supabase secrets set TWILIO_PHONE_NUMBER=+1234567890

# Verify secrets are set
supabase secrets list

4. Configure Edge Function

Edge Function: send-sms-notification Required Secrets:
  • TWILIO_ACCOUNT_SID
  • TWILIO_AUTH_TOKEN
  • TWILIO_PHONE_NUMBER
Function Location: supabase/functions/send-sms-notification/index.ts

Template Configuration

Email Templates

Template Variables:
  • Use {{variable_name}} syntax
  • Variables replaced at send time
  • Case-sensitive
Example Template:
Subject: Leave Request {{action}}

Hello {{employee_name}},

Your leave request has been {{action}}.

Details:
- Start Date: {{start_date}}
- End Date: {{end_date}}
- Days: {{days}}

Thank you,
HR Team
Usage in Code:
await sendEmailNotification({
  recipientEmail: 'user@example.com',
  subject: 'Leave Request {{action}}',
  body: 'Your request has been {{action}}.',
  variables: {
    action: 'approved',
    employee_name: 'John Doe',
    start_date: '2025-01-15',
    end_date: '2025-01-20',
    days: '5'
  }
});

SMS Templates

Message Limits:
  • Single SMS: 160 characters
  • Messages > 160 characters are truncated
  • Use concise templates
Example Template:
{{action}}: Your leave request for {{start_date}} has been {{status}}. Days: {{days}}
Usage in Code:
await sendSMSNotification({
  phoneNumber: '+1234567890',
  message: '{{action}}: Your request has been {{status}}.',
  variables: {
    action: 'Leave Request',
    status: 'approved',
    start_date: '2025-01-15',
    days: '5'
  }
});

Rate Limiting & Quotas

Email (Entra / Gmail) Limits

Microsoft Graph (Entra): Throttling and quotas apply per tenant; see Microsoft documentation. Gmail API: Quotas and sending limits apply per Google Cloud project and per user; see Google documentation.

Twilio Limits

Trial Account:
  • Limited to verified phone numbers
  • SMS only to verified numbers
Paid Account:
  • No daily/monthly limits
  • Pay per SMS sent
Rate Limits:
  • No explicit rate limit
  • Throttling may occur at very high volumes

Platform Limits

Encore Health OS Rate Limiting (Planned):
  • Email: Max 100 emails/hour per organization
  • SMS: Max 50 SMS/hour per organization
  • Enforced in edge functions
Current Status: Rate limiting not yet implemented

Cost Optimization

Email Costs (Entra / Gmail)

Entra: Included with Microsoft 365 licensing; Graph API usage subject to tenant limits. Gmail: Subject to Google Workspace and Gmail API quotas; no per-message fee for typical org usage. Optimization Tips:
  1. Batch notifications when possible
  2. Use send-pending-notifications for batch processing
  3. Monitor email volume per organization
  4. Consider email digests for non-urgent notifications

SMS Costs (Twilio)

Pricing:
  • US/Canada: ~$0.0075 per SMS
  • International: Varies by country
  • MMS: Higher cost
Optimization Tips:
  1. Use SMS only for urgent notifications
  2. Prefer email for non-urgent communications
  3. Batch SMS when possible (future feature)
  4. Monitor SMS volume per organization

Cost Monitoring

Email providers (Entra/Gmail):
  • Monitor provider dashboards for delivery volume, throttling, and failures
  • Configure provider-side alerts/notifications for quota and auth issues
Twilio:
  • Console shows usage and costs
  • Set up spending limits

Error Handling

Email Errors

Entra (Graph API): 4xx/5xx from Graph; check tenant, app permissions, and sender identity. Gmail API: 4xx/5xx from Gmail; check service account, domain-wide delegation, and sender email. Error Handling: The shared email-provider returns EmailSendResult with success and errorMessage; callers update notification status and log accordingly.

SMS Errors

Common Error Codes:
  • 400 - Invalid phone number
  • 403 - Account suspended or insufficient credits
  • 500 - Twilio service error
Error Handling in Function:
try {
  const response = await fetch(twilioUrl, { ... });
  if (!response.ok) {
    const errorData = await response.json();
    throw new Error(`Twilio API error: ${errorData.message}`);
  }
  return { success: true, messageSid: data.sid };
} catch (error) {
  // Log error, update notification status
  return { success: false, error: error.message };
}

Retry Logic

Current Implementation:
  • No automatic retries
  • Failed notifications marked as failed in database
  • Manual retry via send-pending-notifications
Future Enhancement:
  • Automatic retry with exponential backoff
  • Max 3 retries
  • Alert on persistent failures

Testing

Test Email Delivery

Development:
// Test email function
const response = await fetch(
  'http://localhost:54321/functions/v1/send-email-notification',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      notificationId: 'test-uuid',
      recipientEmail: 'test@example.com',
      subject: 'Test Email',
      body: 'This is a test email.',
    }),
  }
);
Production:
  • Send to verified email addresses
  • Check Supabase function logs and provider dashboards (Entra/Gmail) for delivery status

Test SMS Delivery

Development:
// Test SMS function
const response = await fetch(
  'http://localhost:54321/functions/v1/send-sms-notification',
  {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      notificationId: 'test-uuid',
      phoneNumber: '+1234567890',  // Verified number in trial
      message: 'Test SMS',
    }),
  }
);
Production:
  • Use Twilio’s test credentials
  • Send to verified phone numbers (trial)
  • Check Twilio console for delivery status

Test Templates

Test Template Variables:
const testVariables = {
  name: 'John Doe',
  action: 'approved',
  date: '2025-01-07',
  amount: '100.00',
};

// Verify all variables are replaced
const result = template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
  return testVariables[key] || match;
});

Troubleshooting

Issue: Email Not Sending

Symptoms:
  • No email received
  • Function returns success but no email
Solutions:
  1. Entra: Verify ENTRA_CLIENT_SECRET and org Entra config (tenant, app, sender email). Check Graph consent includes Mail.Send.
  2. Gmail: Verify GMAIL_SERVICE_ACCOUNT_JSON and org gmail_sender_email in Settings → Integrations → Gmail. Confirm domain-wide delegation for gmail.send.
  3. Verify recipient email address is valid.
  4. Check spam folder.
  5. Review function logs in Supabase dashboard.

Issue: SMS Not Sending

Symptoms:
  • No SMS received
  • Function returns error
Solutions:
  1. Check Twilio credentials are set correctly
  2. Verify phone number format: +1234567890
  3. Check Twilio account has credits
  4. Verify phone number is verified (trial account)
  5. Check Twilio console for delivery status
  6. Review function logs in Supabase dashboard

Issue: Template Variables Not Replaced

Symptoms:
  • Email/SMS contains {{variable}} literally
Solutions:
  1. Verify variables object includes all template variables
  2. Check variable names match exactly (case-sensitive)
  3. Verify template syntax: {{variable_name}}
  4. Check function logs for variable replacement

Issue: Rate Limit Exceeded

Symptoms:
  • 429 errors from email provider or Twilio
  • Notifications fail
Solutions:
  1. Implement rate limiting in application
  2. Batch notifications when possible
  3. For Entra/Gmail, check tenant or Google project quotas
  4. Use send-pending-notifications for batch processing
  5. Add retry logic with backoff

Issue: High Costs

Symptoms:
  • Unexpected charges from Twilio (or cloud provider)
Solutions:
  1. Monitor usage in provider dashboards
  2. Implement rate limiting per organization
  3. Use email digests for non-urgent notifications
  4. Prefer email over SMS when possible
  5. Set spending limits in Twilio console

Best Practices

1. Email Best Practices

  • Use verified domains (Entra: org mailbox; Gmail: Workspace domain)
  • Set up SPF/DKIM/DMARC per your domain
  • Monitor bounce rates and handle bounces
  • Use templates for consistency
  • Test templates before production use
  • Monitor delivery via Supabase logs and provider dashboards (Graph / Gmail)

2. SMS Best Practices

  • Use SMS only for urgent notifications
  • Keep messages concise (< 160 characters)
  • Include opt-out instructions (if required)
  • Verify phone numbers before sending
  • Monitor delivery rates in Twilio console
  • Handle failed deliveries gracefully

3. Security

  • Never log full email addresses or phone numbers
  • Sanitize user input in templates
  • Validate email/phone formats before sending
  • Use HTTPS for all API calls
  • Rotate API keys regularly
  • Monitor for abuse (unusual sending patterns)

  • Edge Functions: docs/integrations/EDGE_FUNCTIONS.md
  • Environment Variables: docs/development/ENVIRONMENT_VARIABLES.md
  • Secrets Management: docs/security/SECRETS_MANAGEMENT.md
  • Notifications: specs/pf/specs/PF-10-notification-system.md

Document Owner: Platform Team
Review Frequency: Quarterly
Last Updated: 2025-01-07