Skip to main content

Constant Contact Integration

🌐 Overview​

Constant Contact integration providing access to email marketing lists and contact management through OAuth 2.0 authentication. Supports automatic token refresh and paginated contact export.

Provider: Constant Contact (https://www.constantcontact.com)
API Version: v3
Integration Type: OAuth 2.0 with automatic refresh token management

📚 Documentation Structure​

This integration is organized into the following sections:

  1. Authentication - OAuth 2.0 flow with automatic token refresh
  2. Contact Lists - Contact export with cursor-based pagination

🔧 Features​

  • ✅ OAuth 2.0: Secure authentication with automatic token refresh
  • ✅ Contact Management: Export all contacts with list memberships
  • ✅ Auto Token Refresh: Automatic refresh before each API call
  • ✅ Cursor Pagination: Navigate large datasets efficiently
  • ✅ Sub-account Support: Works with DashClicks sub-accounts
  • ✅ Token Management: Automatic refresh and invalidation handling

📊 Architecture​

Frontend Request
↓
OAuth Flow
↓
Token Storage (MongoDB)
↓
Auto Token Refresh
↓
Constant Contact API v3
↓
Contact Data with List Memberships

🗄️ MongoDB Collections​

📚 Detailed Schema: See Database Collections Documentation

constant_contact.keys​

Purpose: Store OAuth 2.0 tokens with refresh capability

Key Fields:

  • token (Object) - Token information
    • access_token (String) - OAuth access token (expires)
    • refresh_token (String) - Refresh token (long-lived)
    • expires_in (Number) - Token expiration time (seconds)
    • token_type (String) - Token type (Bearer)
    • scope (String) - OAuth scopes granted
  • account_id (String) - DashClicks account ID
  • owner (String) - DashClicks user ID
  • generated_at (Number) - Unix timestamp of token generation
  • token_invalidated (Boolean) - Token invalidation flag

Indexes:

  • { account_id: 1, owner: 1 } (unique) - Primary lookup

Schema: Flexible schema (strict: false) with timestamps

📁 Directory Structure​

Source Code Location:

external/Integrations/ConstantContact/
├── Controllers/
│ ├── authController.js # OAuth handlers
│ └── contactController.js # Contact operations
├── Providers/
│ ├── api.js # OAuth API calls
│ └── contactData.js # Contact API calls
├── Models/
│ └── keys.js # Database operations
├── Routes/
│ ├── authRoutes.js # Auth endpoints
│ └── contactRoutes.js # Contact endpoints
└── index.js # Route registration

Shared Models Used:

  • shared/models/constant-contact-key.js

🚀 Quick Start​

1. Configure Environment Variables​

# OAuth Configuration
CONSTANTCONTACT_CLIENT_ID=bd5e80bb-7317-4b22-8839-031b8a9c8417
CONSTANTCONTACT_SECRET_ID=0MtgSHFWiMix3g4pEaKXvg
CONSTANTCONTACT_REDIRECT_URL=https://api.dashclicks.com/v1/integrations/constantcontact/auth/callback

# OAuth Endpoints
CONSTANTCONTACT_AUTH_ENDPOINT=https://api.cc.email/v3/idfed
CONSTANTCONTACT_ACCESS_TOKEN_ENDPOINT=https://idfed.constantcontact.com/as/token.oauth2
CONSTANTCONTACT_GRANT_TYPE=authorization_code

# API Endpoints
CONSTANTCONTACT_CONTACT_ENDPOINT=https://api.cc.email/v3/contacts?include_count=true&include=list_memberships

# Scopes
CONSTANTCONTACT_AUTH_SCOPE=contact_data

2. Initiate OAuth Flow​

GET /v1/integrations/constantcontact/auth/login?forward_url=https://app.dashclicks.com/integrations
Authorization: Bearer {jwt_token}

3. Export Contacts​

GET /v1/integrations/constantcontact/lists
Authorization: Bearer {jwt_token}

4. Paginated Export​

GET /v1/integrations/constantcontact/lists?limit=100&page={cursor_value}
Authorization: Bearer {jwt_token}

📖 API Endpoints Summary​

MethodEndpointDescription
GET/auth/loginInitiate OAuth 2.0 flow
GET/auth/callbackHandle OAuth callback
DELETE/authDelete stored access token
GET/listsExport contacts with pagination

🔑 OAuth Scopes​

Available Scopes​

ScopeDescription
contact_dataAccess to contact information and list memberships
campaign_dataAccess to email campaigns (not implemented)
account_readRead account information (not implemented)

Current Implementation: Uses only contact_data scope

📊 Token Management​

Token Lifecycle​

  1. Initial Token: Obtained during OAuth callback

    • access_token: Valid for 24 hours
    • refresh_token: Long-lived (no expiration)
  2. Automatic Refresh: Before each API call

    • Check generated_at timestamp
    • If expired, use refresh token to get new access token
    • Update MongoDB with new tokens
  3. Token Storage: Stored with generation timestamp

    {
    token: {
    access_token: "...",
    refresh_token: "...",
    expires_in: 86400, // 24 hours
    token_type: "Bearer",
    scope: "contact_data"
    },
    generated_at: 1696934400 // Unix timestamp
    }

Token Expiration​

Access tokens expire after 24 hours. The integration automatically:

  • Detects expired tokens
  • Uses refresh token to obtain new access token
  • Updates database with new token and timestamp
  • Continues with API request

📊 Pagination​

Constant Contact uses cursor-based pagination:

Query Parameters:

  • limit (Integer) - Records per page (default: 20, max: 500)
  • page (String) - Cursor value for next/previous page

Response Format:

{
"success": true,
"message": "SUCCESS",
"data": [...],
"pagination": {
"next": "cursor_string_for_next_page",
"prev": "cursor_string_for_prev_page"
}
}

Navigation Pattern:

# First page
GET /lists?limit=100

# Next page (use cursor from response)
GET /lists?limit=100&page={next_cursor}

# Previous page (use cursor from response)
GET /lists?limit=100&page={prev_cursor}

⚠️ Important Notes​

  • 🔄 Auto Refresh: Access tokens refreshed automatically before each request
  • ⏱️ Token Lifetime: Access tokens valid for 24 hours
  • 🔁 Refresh Tokens: Never expire, stored securely
  • 📊 Pagination: Cursor-based (not page numbers)
  • 👤 Single Connection: One credential set per user/account pair
  • ⚡ Performance: Automatic token refresh adds minimal latency (~200ms)

🎯 Common Use Cases​

Initial Contact Sync​

GET /v1/integrations/constantcontact/lists?limit=500

Export all contacts in batches of 500 for initial sync to DashClicks.

Incremental Updates​

# First batch
GET /v1/integrations/constantcontact/lists?limit=100

# Next batch using cursor from previous response
GET /v1/integrations/constantcontact/lists?limit=100&page={next_cursor}

Progressive loading for large contact lists.

🐛 Troubleshooting​

"Forward url required"​

Missing forward_url query parameter in login request.

"Access Token Not Found"​

No credentials stored. Initiate OAuth flow first.

"Unauthorized User"​

JWT token missing or invalid. Check authentication.

Token Refresh Failures​

Refresh token may be revoked. User must re-authenticate.

📈 Performance Considerations​

  • Token Refresh: Adds ~200ms latency on first request after expiration
  • Pagination: Use limit=500 for fastest bulk exports
  • Rate Limits: Constant Contact limits vary by plan
  • Caching: Consider caching contact data for frequently accessed accounts
  • Batch Processing: Use queue-based processing for 10,000+ contacts

🔒 Security Features​

JWT State Token​

  • Expiry: 2 hours
  • Secret: process.env.APP_SECRET
  • Claims: Account ID, User ID, Forward URL
  • Purpose: Prevent CSRF attacks

Token Encryption​

  • Tokens stored in MongoDB
  • Should be encrypted at rest (deployment-specific)
  • Access controlled by DashClicks authentication

Single Connection​

Only one active connection per user/account to prevent token proliferation.

💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:30 AM