Skip to content

Preference Center

The Preference Center enables subscribers to manage their email preferences through a self-service interface. Each organization has its own preference center with configurable branding and optional custom domain support.

Overview

sequenceDiagram
    participant S as Subscriber
    participant E as Email
    participant PC as Preference Center
    participant API as Subscribe Flow API

    S->>E: Clicks "Manage preferences"
    E->>PC: Magic link with token
    PC->>API: GET /preference-center?token=...
    API->>PC: Subscriber + Tags
    PC->>S: Display preference form
    S->>PC: Save changes
    PC->>API: PUT /preference-center/tags/{tag_id}?token=...
    API->>PC: Confirmation
    PC->>S: Success message

Per-Organization Email Configuration

Each organization can configure its own from address for emails, including preference center links.

Email From Address Resolution

The from address is resolved in the following order:

  1. Custom domain (Professional only): newsletter@custom-domain.com
  2. Default send domain: org-slug@mail.subscribeflow.net
Bash
1
2
3
# View current email settings
curl /api/v1/settings/email \
  -H "X-API-Key: $API_KEY"

Response:

JSON
1
2
3
4
5
6
{
  "from_name": "Acme Corp",
  "from_email": "newsletter@acme.com",
  "send_domain": "acme.com",
  "domain_verified": true
}

Custom Domain Setup (Professional Only)

Professional-tier organizations can configure a custom email domain for branded email sending and preference center links.

Step 1: Register Domain

Bash
1
2
3
4
5
6
curl -X POST /api/v1/settings/domains \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "mail.acme.com"
  }'

Response includes the DNS records to configure:

JSON
{
  "domain": "mail.acme.com",
  "status": "pending",
  "dns_records": [
    {
      "type": "TXT",
      "name": "_resend.mail.acme.com",
      "value": "resend-verify=..."
    },
    {
      "type": "MX",
      "name": "mail.acme.com",
      "value": "..."
    },
    {
      "type": "TXT",
      "name": "mail.acme.com",
      "value": "v=spf1 include:..."
    },
    {
      "type": "CNAME",
      "name": "resend._domainkey.mail.acme.com",
      "value": "..."
    }
  ]
}

Step 2: Configure DNS

Add the returned DNS records to your domain provider.

Step 3: Verify Domain

Bash
curl -X POST /api/v1/settings/domains/verify \
  -H "X-API-Key: $API_KEY"

Domain verification is handled via the Resend API. Once verified, all emails from your organization will use the custom domain.

Professional Plan Required

Custom domain configuration is only available on the Professional plan. Starter and Free organizations use the default send domain (mail.subscribeflow.net).

A temporary magic link can be generated for each subscriber:

Bash
curl -X POST /api/v1/subscribers/:id/preference-link \
  -H "X-API-Key: $API_KEY"

Response:

JSON
1
2
3
4
5
{
  "url": "https://preferences.subscribeflow.net/p/eyJhbGciOi...",
  "token": "eyJhbGciOi...",
  "expires_at": "2024-01-22T10:30:00Z"
}
Property Value Configurable
Validity 24 hours Yes
Reusable Yes -
Scope Own preferences only -

Embedding

Option 1: Hosted Preference Center

Use the hosted preference center under your subdomain:

Text Only
https://preferences.subscribeflow.net/p/:token

Option 2: Custom Domain

Configure a custom domain:

  1. CNAME record: preferences.example.com -> custom.subscribeflow.net
  2. Register the domain in Settings
  3. SSL is configured automatically

Option 3: Embedded Widget

Embed the preference center as a widget:

HTML
<div id="subscribeflow-preferences"></div>
<script src="https://cdn.subscribeflow.net/widget.js"></script>
<script>
  SubscribeFlow.preferences({
    token: 'eyJhbGciOi...',
    container: '#subscribeflow-preferences',
    theme: 'light',  // 'light' | 'dark' | 'auto'
    locale: 'de'
  });
</script>

Option 4: Custom UI

Build your own UI with the API:

JavaScript
1
2
3
4
const response = await fetch(
  'https://api.subscribeflow.net/preference-center?token=' + token
);
const { subscriber, tags, subscribed_tags } = await response.json();
JavaScript
1
2
3
await fetch('https://api.subscribeflow.net/preference-center/tags/' + tagId + '?token=' + token, {
  method: 'PUT'
});

API Endpoints

Retrieving Preferences

Bash
curl /preference-center?token=TOKEN

Response:

JSON
{
  "subscriber": {
    "email": "user@example.com",
    "first_name": "Max"
  },
  "tags": [
    {
      "name": "product-updates",
      "display_name": "Product Updates",
      "description": "New features and improvements",
      "category": "newsletter",
      "is_subscribed": true
    },
    {
      "name": "weekly-digest",
      "display_name": "Weekly Digest",
      "description": "Weekly summary",
      "category": "newsletter",
      "is_subscribed": false
    }
  ],
  "categories": [
    {
      "name": "newsletter",
      "display_name": "Newsletter"
    }
  ]
}

Subscribe to Tag

Bash
curl -X PUT /preference-center/tags/{tag_id}?token=TOKEN

Unsubscribe from Tag

Bash
curl -X DELETE /preference-center/tags/{tag_id}?token=TOKEN

Data Export (DSGVO)

Bash
curl /preference-center/data-export?token=TOKEN

Delete Account (DSGVO)

Bash
curl -X DELETE /preference-center/account?token=TOKEN

Customization

Branding

Customize the preference center to match your brand:

Bash
1
2
3
4
5
6
7
8
9
curl -X PATCH /api/v1/settings/preference-center \
  -H "X-API-Key: $API_KEY" \
  -d '{
    "logo_url": "https://example.com/logo.svg",
    "primary_color": "#4F46E5",
    "company_name": "Example Corp",
    "support_email": "support@example.com",
    "privacy_url": "https://example.com/privacy"
  }'

Text Content

Bash
curl -X PATCH /api/v1/settings/preference-center \
  -H "X-API-Key: $API_KEY" \
  -d '{
    "texts": {
      "title": "Your Email Preferences",
      "subtitle": "Choose which emails you would like to receive",
      "save_button": "Save preferences",
      "unsubscribe_all": "Unsubscribe from all emails"
    }
  }'

Email Integration

HTML
1
2
3
<a href="{{preference_center_url}}">
  Manage email preferences
</a>

With Resend (Per-Org From Address)

Python
import resend

# The from address is resolved per organization:
# - Professional with custom domain: newsletter@custom-domain.com
# - Default: org-slug@mail.subscribeflow.net

resend.Emails.send({
    "from": org.from_address,  # Resolved by Email Utils
    "to": subscriber.email,
    "subject": "Your Newsletter",
    "html": f"""
        <p>Newsletter content...</p>
        <p>
            <a href="{preference_center_url}">
                Manage email preferences
            </a>
        </p>
    """
})

Security

Token Security

  • Tokens are signed (HMAC-SHA256)
  • Validity is time-limited
  • Tokens cannot be tampered with

Rate Limiting

Endpoint Limit
GET /preference-center 100/min
PUT /preference-center/tags/{id} 100/min
DELETE /preference-center/tags/{id} 100/min

Audit Trail

All changes are logged:

JSON
{
  "action": "preference_update",
  "subscriber_id": "uuid",
  "source": "preference_center",
  "changes": {
    "added": ["weekly-digest"],
    "removed": ["marketing"]
  },
  "ip_address": "1.2.3.4",
  "timestamp": "2024-01-15T10:30:00Z"
}