Registration & Integration Workflows Guide

Complete guide to external subscription methods for your CRM platform

Last Updated: October 27, 2025


Table of Contents

  1. Overview
  2. Public Subscription API
  3. Website Form Integration
  4. Email Signature Links
  5. Social Media Integration
  6. QR Code Registration
  7. LinkedIn Integration (Planned)
  8. Unsubscribe Mechanism
  9. CASL Compliance
  10. Troubleshooting

Overview

This CRM platform provides multiple methods for external users to subscribe to your distribution lists without requiring CRM login credentials. All methods are CASL compliant and include automatic consent tracking.

Available Registration Methods

Method Status Use Case Difficulty
Website Forms ✅ Live Website footer, landing pages Easy
Email Signature Links ✅ Live Professional email signatures Easy
Social Media Links ✅ Live Social media profiles Easy
QR Codes ✅ Live Print materials, business cards Easy
Public API ✅ Live Custom integrations Medium
LinkedIn Integration ⏳ Planned Import connections Medium

Benefits


🔥 NEW: Automatic Integration Code Generator

The easiest way to integrate your distribution lists - no manual coding required!

What Is It?

Every distribution list now has a "🔗 Get Integration Code" button that automatically generates ready-to-use integration code for all the methods described in this guide. All URLs, API endpoints, and list IDs are pre-filled for you.

How to Use

  1. Log into your CRM at https://crm.sagentix.ca
  2. Navigate to Distribution Lists tab
  3. Click "🔗 Get Integration Code" on any list
  4. Choose your integration type from the modal:
  5. 🌐 Website Form Integration
  6. ✉️ Email Signature Links
  7. 📱 Social Media Integration
  8. 💼 LinkedIn Profile/Company Page
  9. Click "📋 Copy" to copy the code
  10. Paste wherever you need it

What You Get

🌐 Website Form Integration - Complete HTML subscription form - Inline CSS styling (no external stylesheets needed) - Full JavaScript implementation for API calls - Success/error message handling - Mobile-responsive design - Ready to paste into any webpage

✉️ Email Signature Links - Plain URL format: https://...subscribe?listId=xxx&source=email - HTML format: <a href="...">Subscribe to List Name</a> - Pre-filled with your list ID - Tracking parameter included

📱 Social Media Integration - Pre-written engaging post text - Subscription link embedded - Relevant hashtags included - Ready for LinkedIn, Twitter, Facebook, Instagram

💼 LinkedIn Profile/Company Page - Professional formatted text - Perfect for LinkedIn "Contact Info" section - Direct subscription link - Company page friendly

Benefits

✅ Zero Configuration - Everything is pre-filled ✅ No Technical Skills Required - Just copy and paste ✅ List-Specific - Unique code for each distribution list ✅ Production-Ready - Professional, tested code ✅ Time-Saving - Seconds instead of hours

Example Workflow

Old Way (Manual): 1. Read this documentation 2. Copy API endpoint from docs 3. Find your list ID 4. Write HTML form code 5. Write JavaScript for API calls 6. Test and debug 7. Style the form ⏱️ Time: 30-60 minutes

New Way (Automated): 1. Click "🔗 Get Integration Code" 2. Click "📋 Copy" 3. Paste into your website/email/social media ⏱️ Time: 30 seconds


Public Subscription API

Endpoint Details

URL: https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe

Method: POST

Authentication: None required (public endpoint)

Content-Type: application/json

Request Format

{
  "email": "user@example.com",
  "listId": "your-distribution-list-id",
  "firstName": "John",
  "lastName": "Doe"
}

Request Parameters

Parameter Type Required Description
email string Yes Valid email address
listId string Yes Distribution list UUID
firstName string No Contact's first name
lastName string No Contact's last name

Response Format

Success (201 Created):

{
  "message": "Successfully subscribed to the list",
  "contactId": "abc123-contact-id",
  "listId": "4f41dfcd-7848-407a-a67d-ef1041f8a1f6"
}

Error (400 Bad Request):

{
  "error": "Missing required field: email"
}

Error (500 Internal Server Error):

{
  "error": "Failed to process subscription"
}

Example API Call

Using JavaScript Fetch:

async function subscribeToList(email, firstName, lastName) {
  try {
    const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        email: email,
        firstName: firstName,
        lastName: lastName,
        listId: '4f41dfcd-7848-407a-a67d-ef1041f8a1f6'
      })
    });

    if (!response.ok) {
      throw new Error('Subscription failed');
    }

    const data = await response.json();
    console.log('Subscribed successfully:', data);
    return data;
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}

Using cURL:

curl -X POST https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "firstName": "John",
    "lastName": "Doe",
    "listId": "4f41dfcd-7848-407a-a67d-ef1041f8a1f6"
  }'

Using Python:

import requests

def subscribe_to_list(email, first_name, last_name, list_id):
    url = "https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe"
    payload = {
        "email": email,
        "firstName": first_name,
        "lastName": last_name,
        "listId": list_id
    }

    response = requests.post(url, json=payload)

    if response.status_code == 201:
        print("Subscription successful:", response.json())
        return response.json()
    else:
        print("Subscription failed:", response.json())
        return None

Website Form Integration

Basic HTML Form

Simple footer signup form:

<!DOCTYPE html>
<html>
<head>
  <title>Newsletter Signup</title>
  <style>
    .subscription-form {
      max-width: 500px;
      margin: 40px auto;
      padding: 30px;
      background: #f9f9f9;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0,0,0,0.1);
    }

    .subscription-form h2 {
      margin-top: 0;
      color: #333;
    }

    .form-group {
      margin-bottom: 15px;
    }

    .form-group label {
      display: block;
      margin-bottom: 5px;
      color: #555;
      font-weight: 500;
    }

    .form-group input {
      width: 100%;
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 4px;
      font-size: 14px;
      box-sizing: border-box;
    }

    .form-group input:focus {
      outline: none;
      border-color: #4CAF50;
    }

    .submit-btn {
      background: #4CAF50;
      color: white;
      padding: 12px 30px;
      border: none;
      border-radius: 4px;
      font-size: 16px;
      cursor: pointer;
      width: 100%;
    }

    .submit-btn:hover {
      background: #45a049;
    }

    .submit-btn:disabled {
      background: #ccc;
      cursor: not-allowed;
    }

    .message {
      margin-top: 15px;
      padding: 10px;
      border-radius: 4px;
      text-align: center;
    }

    .success {
      background: #d4edda;
      color: #155724;
      border: 1px solid #c3e6cb;
    }

    .error {
      background: #f8d7da;
      color: #721c24;
      border: 1px solid #f5c6cb;
    }

    .consent-text {
      font-size: 12px;
      color: #666;
      margin-top: 10px;
      line-height: 1.4;
    }
  </style>
</head>
<body>
  <div class="subscription-form">
    <h2>Subscribe to Our Newsletter</h2>
    <p>Get the latest updates delivered to your inbox.</p>

    <form id="subscribeForm">
      <div class="form-group">
        <label for="firstName">First Name</label>
        <input type="text" id="firstName" name="firstName" placeholder="John">
      </div>

      <div class="form-group">
        <label for="lastName">Last Name</label>
        <input type="text" id="lastName" name="lastName" placeholder="Doe">
      </div>

      <div class="form-group">
        <label for="email">Email Address *</label>
        <input type="email" id="email" name="email" required placeholder="john@example.com">
      </div>

      <button type="submit" class="submit-btn" id="submitBtn">Subscribe</button>

      <p class="consent-text">
        By subscribing, you consent to receive marketing emails from us.
        You can unsubscribe at any time using the link in our emails.
      </p>
    </form>

    <div id="message"></div>
  </div>

  <script>
    // Configuration
    const API_URL = 'https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe';
    const LIST_ID = '4f41dfcd-7848-407a-a67d-ef1041f8a1f6';

    document.getElementById('subscribeForm').addEventListener('submit', async (e) => {
      e.preventDefault();

      const submitBtn = document.getElementById('submitBtn');
      const messageDiv = document.getElementById('message');

      // Disable submit button
      submitBtn.disabled = true;
      submitBtn.textContent = 'Subscribing...';
      messageDiv.innerHTML = '';

      // Get form data
      const formData = {
        email: document.getElementById('email').value.trim(),
        firstName: document.getElementById('firstName').value.trim(),
        lastName: document.getElementById('lastName').value.trim(),
        listId: LIST_ID
      };

      try {
        const response = await fetch(API_URL, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify(formData)
        });

        if (response.ok) {
          messageDiv.innerHTML = '<div class="message success">Thank you for subscribing! Check your inbox for a confirmation email.</div>';
          document.getElementById('subscribeForm').reset();
        } else {
          const error = await response.json();
          messageDiv.innerHTML = `<div class="message error">Subscription failed: ${error.error || 'Please try again.'}</div>`;
        }
      } catch (error) {
        console.error('Subscription error:', error);
        messageDiv.innerHTML = '<div class="message error">Network error. Please check your connection and try again.</div>';
      } finally {
        submitBtn.disabled = false;
        submitBtn.textContent = 'Subscribe';
      }
    });
  </script>
</body>
</html>

Minimal Footer Form

Compact version for website footers:

<div class="footer-subscribe">
  <h3>Stay Updated</h3>
  <form id="footerSubscribe" style="display: flex; gap: 10px; max-width: 400px;">
    <input
      type="email"
      id="footerEmail"
      placeholder="Your email"
      required
      style="flex: 1; padding: 10px; border: 1px solid #ddd; border-radius: 4px;"
    >
    <button
      type="submit"
      style="padding: 10px 20px; background: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;"
    >
      Subscribe
    </button>
  </form>
  <div id="footerMessage" style="margin-top: 10px; font-size: 14px;"></div>
</div>

<script>
document.getElementById('footerSubscribe').addEventListener('submit', async (e) => {
  e.preventDefault();

  const email = document.getElementById('footerEmail').value;
  const messageDiv = document.getElementById('footerMessage');

  try {
    const response = await fetch('https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        email: email,
        listId: '4f41dfcd-7848-407a-a67d-ef1041f8a1f6'
      })
    });

    if (response.ok) {
      messageDiv.innerHTML = '<span style="color: green;">✓ Subscribed successfully!</span>';
      document.getElementById('footerEmail').value = '';
    } else {
      messageDiv.innerHTML = '<span style="color: red;">✗ Subscription failed</span>';
    }
  } catch (error) {
    messageDiv.innerHTML = '<span style="color: red;">✗ Network error</span>';
  }
});
</script>

WordPress Integration

Add to your theme's functions.php:

<?php
// Add subscription form shortcode
function crm_subscription_form() {
    ob_start();
    ?>
    <div class="crm-subscribe-form">
        <form id="crmSubscribeForm" method="post">
            <input type="email" name="email" id="crmEmail" placeholder="Enter your email" required>
            <input type="text" name="firstName" id="crmFirstName" placeholder="First Name">
            <input type="text" name="lastName" id="crmLastName" placeholder="Last Name">
            <button type="submit">Subscribe</button>
        </form>
        <div id="crmMessage"></div>
    </div>

    <script>
    jQuery(document).ready(function($) {
        $('#crmSubscribeForm').on('submit', function(e) {
            e.preventDefault();

            $.ajax({
                url: 'https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/subscribe',
                method: 'POST',
                contentType: 'application/json',
                data: JSON.stringify({
                    email: $('#crmEmail').val(),
                    firstName: $('#crmFirstName').val(),
                    lastName: $('#crmLastName').val(),
                    listId: '4f41dfcd-7848-407a-a67d-ef1041f8a1f6'
                }),
                success: function(response) {
                    $('#crmMessage').html('<p style="color: green;">Subscribed successfully!</p>');
                    $('#crmSubscribeForm')[0].reset();
                },
                error: function() {
                    $('#crmMessage').html('<p style="color: red;">Subscription failed. Please try again.</p>');
                }
            });
        });
    });
    </script>
    <?php
    return ob_get_clean();
}
add_shortcode('crm_subscribe', 'crm_subscription_form');
?>

Usage in WordPress:

[crm_subscribe]

Email Signature Links

Basic Subscribe Link

Direct subscription link format:

https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

HTML Email Signature

Professional email signature with subscribe link:

<table style="font-family: Arial, sans-serif; font-size: 14px; color: #333;">
  <tr>
    <td style="padding-right: 20px; border-right: 2px solid #4CAF50;">
      <strong style="font-size: 16px;">John Doe</strong><br>
      Marketing Director<br>
      Company Name Inc.<br>
      <a href="mailto:john@company.com">john@company.com</a><br>
      <a href="tel:+15551234567">+1 (555) 123-4567</a>
    </td>
    <td style="padding-left: 20px;">
      <a href="https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6"
         style="background: #4CAF50; color: white; padding: 8px 16px; text-decoration: none; border-radius: 4px; display: inline-block;">
        📧 Subscribe to Our Newsletter
      </a>
      <br><br>
      <a href="https://company.com" style="color: #4CAF50; text-decoration: none;">
        🌐 Visit Our Website
      </a>
    </td>
  </tr>
</table>

Plain Text Email Signature

For plain text emails:

--
John Doe
Marketing Director
Company Name Inc.
john@company.com | +1 (555) 123-4567

📧 Subscribe to our newsletter:
https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

🌐 Visit us: https://company.com

Gmail Signature Setup

  1. Open Gmail Settings (gear icon > See all settings)
  2. Scroll to "Signature" section
  3. Click "Create new" signature
  4. Paste the HTML signature code
  5. Replace 4f41dfcd-7848-407a-a67d-ef1041f8a1f6 with your actual list ID
  6. Click "Save Changes"

Outlook Signature Setup

  1. Open Outlook > File > Options > Mail
  2. Click "Signatures..."
  3. Click "New" to create a signature
  4. Switch to HTML editor (Format menu)
  5. Paste the HTML signature code
  6. Replace 4f41dfcd-7848-407a-a67d-ef1041f8a1f6 with your actual list ID
  7. Click "OK" to save

Social Media Integration

LinkedIn Profile Link

Add to LinkedIn "Featured" section or About:

📧 Subscribe to my newsletter: https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

Get weekly insights on [your topic] delivered to your inbox.

Twitter/X Bio Link

Add to your bio (character limit friendly):

📧 Newsletter: crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

Tweet for subscribers:

Want to stay updated? Subscribe to our newsletter! 📧

👉 https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

✅ Weekly insights
✅ Industry trends
✅ Exclusive content

#Newsletter #Subscribe

Facebook Page

Add to "About" section:

Subscribe to Our Newsletter
Get the latest updates delivered to your inbox.
https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

Facebook Post:

🚀 Join our newsletter community!

Get exclusive content, tips, and insights delivered weekly.

Subscribe here: https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

✓ No spam, ever
✓ Unsubscribe anytime
✓ CASL compliant

Instagram Bio Link

Use link shortener for cleaner appearance:

📧 Newsletter → bit.ly/your-short-link

Instagram Story with Link Sticker: 1. Create story with subscribe call-to-action 2. Add link sticker 3. Paste: https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6 4. Customize sticker text: "Subscribe"

YouTube Channel

Add to channel description:

📬 SUBSCRIBE TO OUR EMAIL NEWSLETTER
Stay updated with exclusive content not available on YouTube!
👉 https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

Add as end screen element: 1. Upload custom end screen with subscribe CTA 2. Link to external website 3. URL: https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6


QR Code Registration

Generating QR Codes

Option 1: Online QR Code Generator

  1. Visit: https://www.qr-code-generator.com/
  2. Select "URL" type
  3. Enter: https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6
  4. Customize design (optional)
  5. Download high-resolution PNG

Option 2: Using Python

import qrcode

# Generate QR code
qr = qrcode.QRCode(
    version=1,
    error_correction=qrcode.constants.ERROR_CORRECT_H,
    box_size=10,
    border=4,
)

qr.add_data('https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6')
qr.make(fit=True)

# Create image
img = qr.make_image(fill_color="black", back_color="white")
img.save("newsletter_qr.png")

Option 3: Using Node.js

const QRCode = require('qrcode');

const url = 'https://crm.sagentix.ca/subscribe?list=4f41dfcd-7848-407a-a67d-ef1041f8a1f6';

QRCode.toFile('newsletter_qr.png', url, {
  color: {
    dark: '#000000',
    light: '#FFFFFF'
  },
  width: 300
}, function (err) {
  if (err) throw err;
  console.log('QR code saved!');
});

QR Code Use Cases

1. Business Cards - Add QR code to back of card - Caption: "Scan to subscribe to our newsletter" - Size: 1" x 1" (2.5cm x 2.5cm)

2. Print Flyers - Bottom corner or center - Clear call-to-action - Size: 2" x 2" (5cm x 5cm)

3. Conference Booth - Large poster with QR code - Sign: "Scan to stay in touch!" - Size: 6" x 6" (15cm x 15cm)

4. Product Packaging - Inside lid or on label - "Join our community" - Size: 0.75" x 0.75" (2cm x 2cm)

5. Restaurant Table Tents - Special offers newsletter - "Get exclusive deals" - Size: 3" x 3" (7.5cm x 7.5cm)

6. Event Badge - Conference attendee badges - "Connect with me" - Size: 1" x 1" (2.5cm x 2.5cm)

QR Code Best Practices

✅ Do: - Test QR code before printing - Use high error correction (H level) - Ensure high contrast (dark on light) - Include caption explaining what it does - Make it large enough (minimum 1" / 2.5cm) - Use URL shortener for tracking

❌ Don't: - Use low resolution images - Place on textured/patterned backgrounds - Make it too small to scan - Forget to test from typical scanning distance


LinkedIn Integration (Planned)

Planned Features

The LinkedIn integration feature is planned for future implementation. It will allow:

  1. Connection Import
  2. OAuth authentication with LinkedIn
  3. Import 1st-degree connections
  4. Automatic contact creation
  5. Bulk list assignment

  6. Profile Sync

  7. Sync profile information
  8. Company details
  9. Job titles
  10. Profile photos

  11. InMail Integration

  12. Send campaigns via InMail
  13. Track message engagement
  14. CASL compliance maintained

Current Workaround

Manual LinkedIn Connection Export:

  1. Go to LinkedIn > Settings & Privacy > Data Privacy
  2. Click "Get a copy of your data"
  3. Select "Connections"
  4. Download CSV file
  5. Import via CRM's Excel import feature
  6. Manually add to distribution list

Implementation Timeline

Technical Requirements

When implemented, will require: - LinkedIn API application - OAuth 2.0 implementation - Member permissions - Rate limiting (100 requests per day for free tier)


Unsubscribe Mechanism

Unsubscribe Link Format

Every email campaign automatically includes an unsubscribe link:

https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/unsubscribe?email=user@example.com&listId=4f41dfcd-7848-407a-a67d-ef1041f8a1f6

How It Works

  1. User clicks unsubscribe link in email
  2. GET request to /public/unsubscribe endpoint
  3. Contact status updated to "unsubscribed"
  4. Removed from distribution list
  5. Confirmation page displayed
  6. User receives confirmation email

Manual Unsubscribe Implementation

Frontend unsubscribe page:

<!DOCTYPE html>
<html>
<head>
  <title>Unsubscribe</title>
  <style>
    .container {
      max-width: 500px;
      margin: 100px auto;
      padding: 40px;
      text-align: center;
      background: #f9f9f9;
      border-radius: 8px;
    }

    .success {
      color: #4CAF50;
      font-size: 48px;
      margin-bottom: 20px;
    }

    h1 {
      color: #333;
      margin-bottom: 10px;
    }

    p {
      color: #666;
      line-height: 1.6;
    }

    .btn {
      display: inline-block;
      margin-top: 20px;
      padding: 12px 30px;
      background: #4CAF50;
      color: white;
      text-decoration: none;
      border-radius: 4px;
    }
  </style>
</head>
<body>
  <div class="container">
    <div class="success">✓</div>
    <h1>You've Been Unsubscribed</h1>
    <p>We're sorry to see you go! You have been successfully removed from our mailing list.</p>
    <p>You will no longer receive emails from us.</p>
    <a href="https://yourwebsite.com" class="btn">Back to Website</a>
  </div>

  <script>
    // Parse URL parameters
    const params = new URLSearchParams(window.location.search);
    const email = params.get('email');
    const listId = params.get('listId');

    // Call unsubscribe API
    if (email && listId) {
      fetch(`https://zqkprqp60h.execute-api.ca-central-1.amazonaws.com/Prod/public/unsubscribe?email=${email}&listId=${listId}`)
        .then(response => response.json())
        .then(data => console.log('Unsubscribed:', data))
        .catch(error => console.error('Error:', error));
    }
  </script>
</body>
</html>

CASL Compliance

All unsubscribe mechanisms are CASL compliant:

✅ One-click unsubscribe (no login required) ✅ Processed immediately ✅ Confirmation provided ✅ Persistent (cannot be re-subscribed without consent) ✅ Available in every email ✅ Clear and conspicuous


CASL Compliance

Canadian Anti-Spam Legislation Requirements

All subscription methods comply with CASL:

  1. Express Consent
  2. All subscriptions are opt-in
  3. Clear purpose stated
  4. Consent date tracked
  5. Audit trail maintained

  6. Identification Requirements

  7. Sender name in every email
  8. Valid physical mailing address
  9. Contact information provided

  10. Unsubscribe Mechanism

  11. Available in every message
  12. Free of charge
  13. No login required
  14. One-click process
  15. Processed within 10 business days (we process immediately)

  16. Record Keeping

  17. Consent date stored
  18. Subscription method tracked
  19. Unsubscribe date recorded
  20. Full audit trail

Consent Tracking

Every subscription records: - Email address - Subscription date (ISO 8601 format) - Subscription method (website, email, QR code, etc.) - IP address (optional, for fraud prevention) - List ID - Contact creation timestamp

Legal Requirements Met

✅ Express consent obtained ✅ Clear identification of sender ✅ Subject matter stated ✅ Physical mailing address included ✅ Unsubscribe mechanism provided ✅ Consent records maintained ✅ Unsubscribe honored immediately


Troubleshooting

Common Issues

Issue 1: Subscription Not Working

Symptoms: - Form submission returns error - No contact created in CRM

Solutions: 1. Verify API URL is correct 2. Check list ID is valid 3. Ensure CORS is enabled on API Gateway 4. Verify Lambda function is deployed 5. Check CloudWatch logs for errors

Issue 2: CORS Errors

Symptoms: - Browser console shows CORS error - Request blocked by browser

Solutions: 1. Add CORS headers to Lambda response:

return {
    'statusCode': 201,
    'headers': {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'POST, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type'
    },
    'body': json.dumps(response_body)
}
  1. Enable CORS in API Gateway:
  2. Go to API Gateway console
  3. Select your API
  4. Choose the resource
  5. Enable CORS
  6. Deploy API

Issue 3: Duplicate Contacts

Symptoms: - Same email subscribed multiple times - Multiple contact records with same email

Solutions: - The system automatically prevents duplicates by email - If issue persists, check Lambda function logic - Use duplicate detection tool in CRM

Issue 4: Unsubscribe Not Working

Symptoms: - User still receives emails after unsubscribing - Unsubscribe link returns error

Solutions: 1. Verify unsubscribe endpoint is deployed 2. Check CloudWatch logs for errors 3. Confirm contact status updated to "unsubscribed" 4. Verify campaign send logic excludes unsubscribed contacts

Issue 5: QR Code Not Scanning

Symptoms: - QR code won't scan - Scanner app doesn't recognize it

Solutions: 1. Regenerate QR code at higher resolution 2. Ensure sufficient size (minimum 1" / 2.5cm) 3. Use high error correction level 4. Test on white paper with dark ink 5. Verify URL is correct before generating

Testing Checklist

Before deploying subscription methods:

✅ Test subscription form with valid data ✅ Test with missing required fields ✅ Test with invalid email format ✅ Test with duplicate email ✅ Verify contact created in CRM ✅ Verify list membership created ✅ Test unsubscribe link ✅ Check all CloudWatch logs ✅ Test from mobile device ✅ Test QR code scanning

Support Resources


Summary

This CRM platform provides comprehensive subscription methods suitable for any marketing channel:

All methods are: - ✅ CASL compliant - ✅ No login required - ✅ Duplicate-safe - ✅ Instantly processed - ✅ One-click unsubscribe

Next Steps: 1. Get your distribution list ID from the CRM 2. Choose your preferred subscription method 3. Customize the examples with your API URL and list ID 4. Test thoroughly before deployment 5. Monitor CloudWatch logs for issues

For complete feature documentation, see COMPLETE_FEATURE_GUIDE.md


Document Version: 1.0 Last Updated: October 27, 2025 Maintained By: CRM Platform Team