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