Skip to content

Messages ↔ Calendars Integration

Calendars communicates with Messages through a server-to-server API channel. This enables:

  • Calendar creation with "Sending identity" from Messages mailboxes
  • Event invitations sent from mailbox email addresses
  • RSVP reply emails processed through Messages

Architecture

Calendars Backend
       ├── GET /api/v1.0/provisioning/mailboxes/  (fetch user mailboxes)
       └── POST /api/v1.0/submit/                  (send invitation emails)
       Messages API
         Headers: X-API-Key + X-Channel-Id
       Messages Backend → Brevo SMTP

Configuration Flow

1. Server-to-Server API Token

Add a token to Messages .env:

DJANGO_SERVER_TO_SERVER_API_TOKENS=<token>

Important: Use DJANGO_ prefix (django-configurations convention). The env var name is DJANGO_SERVER_TO_SERVER_API_TOKENS, not SERVER_TO_SERVER_API_TOKENS.

2. Create API Channel in Messages

Create a channel that Calendars will use to authenticate:

from core.models import Channel
import hashlib

api_key = "<same-token>"
key_hash = hashlib.sha256(api_key.encode('utf-8')).hexdigest()

channel = Channel(
    name='calendars',
    type='api_key',
    scope_level='global'
)
channel.save()

# Store the API key hash
channel.encrypted_settings = {'api_key_hashes': [key_hash]}
channel.settings = {'scopes': ['messages:send', 'mailboxes:read']}
channel.save()

print(f"Channel ID: {channel.id}")

3. Configure Calendars .env

FEATURE_MESSAGES_INTEGRATION=True
MESSAGES_API_URL=https://api.messages.<domain>
MESSAGES_API_KEY=<same-token>
MESSAGES_CHANNEL_ID=<channel-id-from-step-2>

Note: MESSAGES_API_URL must NOT end with /api/v1.0/. The MessagesService appends it internally.

Required Scopes

Scope Required For
mailboxes:read Fetching user mailboxes for "Sending identity"
messages:send Sending invitation emails via Messages API submit

Authentication Headers

Calendars sends two headers with every Messages API request:

X-API-Key: <token>
X-Channel-Id: <channel-uuid>

Messages' ChannelApiKeyAuthentication hashes the provided API key and compares it against stored hashes in channel.encrypted_settings.api_key_hashes.

Post-Integration

After configuring integration, when a user creates a calendar:

  1. If they have a Messages mailbox matching their email → "Sending identity" shows the mailbox
  2. Event invitations are sent from that mailbox via Messages → Brevo
  3. Attendee RSVP links point to calendars.<domain>/rsvp/