Introduction
# Constant Contact
Access the Constant Contact V3 API with managed OAuth authentication. Manage contacts, email campaigns, contact lists, segments, and marketing analytics.
## Quick Start
```bash # List contacts python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/constant-contact/v3/contacts') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
## Base URL
``` https://gateway.maton.ai/constant-contact/v3/{resource} ```
The gateway proxies requests to `api.cc.email/v3` and automatically injects your OAuth token.
## Authentication
All requests require the Maton API key in the Authorization header:
``` Authorization: Bearer $MATON_API_KEY ```
**Environment Variable:** Set your API key as `MATON_API_KEY`:
```bash export MATON_API_KEY="YOUR_API_KEY" ```
### Getting Your API Key
1. Sign in or create an account at [maton.ai](https://maton.ai) 2. Go to [maton.ai/settings](https://maton.ai/settings) 3. Copy your API key
## Connection Management
Manage your Constant Contact OAuth connections at `https://ctrl.maton.ai`.
### List Connections
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections?app=constant-contact&status=ACTIVE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Create Connection
```bash python <<'EOF' import urllib.request, os, json data = json.dumps({'app': 'constant-contact'}).encode() req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Content-Type', 'application/json') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Get Connection
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
**Response:** ```json { "connection": { "connection_id": "4314bd0f-fd56-40ab-8c65-2676dd2c23c4", "status": "ACTIVE", "creation_time": "2026-02-07T07:41:05.859244Z", "last_updated_time": "2026-02-07T07:41:32.658230Z", "url": "https://connect.maton.ai/?session_token=...", "app": "constant-contact", "metadata": {} } } ```
Open the returned `url` in a browser to complete OAuth authorization.
### Delete Connection
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Specifying Connection
If you have multiple Constant Contact connections, specify which one to use with the `Maton-Connection` header:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://gateway.maton.ai/constant-contact/v3/contacts') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') req.add_header('Maton-Connection', '4314bd0f-fd56-40ab-8c65-2676dd2c23c4') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
If omitted, the gateway uses the default (oldest) active connection.
## API Reference
### Account
#### Get Account Summary
```bash GET /constant-contact/v3/account/summary ```
#### Get Account Emails
```bash GET /constant-contact/v3/account/emails ```
#### Get User Privileges
```bash GET /constant-contact/v3/account/user/privileges ```
### Contacts
#### List Contacts
```bash GET /constant-contact/v3/contacts ```
Query parameters: - `status` - Filter by status: `all`, `active`, `deleted`, `not_set`, `pending_confirmation`, `temp_hold`, `unsubscribed` - `email` - Filter by email address - `lists` - Filter by list ID(s) - `segment_id` - Filter by segment ID - `tags` - Filter by tag ID(s) - `updated_after` - ISO-8601 date filter - `include` - Include subresources: `custom_fields`, `list_memberships`, `taggings`, `notes` - `limit` - Results per page (default 50, max 500)
#### Get Contact
```bash GET /constant-contact/v3/contacts/{contact_id} ```
#### Create Contact
```bash POST /constant-contact/v3/contacts Content-Type: application/json
{ "email_address": { "address": "[email protected]", "permission_to_send": "implicit" }, "first_name": "John", "last_name": "Doe", "job_title": "Developer", "company_name": "Acme Inc", "list_memberships": ["list-uuid-here"] } ```
#### Update Contact
```bash PUT /constant-contact/v3/contacts/{contact_id} Content-Type: application/json
{ "email_address": { "address": "[email protected]" }, "first_name": "John", "last_name": "Smith" } ```
#### Delete Contact
```bash DELETE /constant-contact/v3/contacts/{contact_id} ```
#### Create or Update Contact (Sign-Up Form)
Use this endpoint to create a new contact or update an existing one without checking if they exist first:
```bash POST /constant-contact/v3/contacts/sign_up_form Content-Type: application/json
{ "email_address": "[email protected]", "first_name": "John", "last_name": "Doe", "list_memberships": ["list-uuid-here"] } ```
#### Get Contact Counts
```bash GET /constant-contact/v3/contacts/counts ```
### Contact Lists
#### List Contact Lists
```bash GET /constant-contact/v3/contact_lists ```
Query parameters: - `include_count` - Include contact count per list - `include_membership_count` - Include membership count - `limit` - Results per page
#### Get Contact List
```bash GET /constant-contact/v3/contact_lists/{list_id} ```
#### Create Contact List
```bash POST /constant-contact/v3/contact_lists Content-Type: application/json
{ "name": "Newsletter Subscribers", "description": "Main newsletter list", "favorite": false } ```
#### Update Contact List
```bash PUT /constant-contact/v3/contact_lists/{list_id} Content-Type: application/json
{ "name": "Updated List Name", "description": "Updated description", "favorite": true } ```
#### Delete Contact List
```bash DELETE /constant-contact/v3/contact_lists/{list_id} ```
### Tags
#### List Tags
```bash GET /constant-contact/v3/contact_tags ```
#### Create Tag
```bash POST /constant-contact/v3/contact_tags Content-Type: application/json
{ "name": "VIP Customer" } ```
#### Update Tag
```bash PUT /constant-contact/v3/contact_tags/{tag_id} Content-Type: application/json
{ "name": "Premium Customer" } ```
#### Delete Tag
```bash DELETE /constant-contact/v3/contact_tags/{tag_id} ```
### Custom Fields
#### List Custom Fields
```bash GET /constant-contact/v3/contact_custom_fields ```
#### Create Custom Field
```bash POST /constant-contact/v3/contact_custom_fields Content-Type: application/json
{ "label": "Customer ID", "type": "string" } ```
#### Delete Custom Field
```bash DELETE /constant-contact/v3/contact_custom_fields/{custom_field_id} ```
### Email Campaigns
#### List Email Campaigns
```bash GET /constant-contact/v3/emails ```
Query parameters: - `limit` - Results per page (default 50)
#### Get Email Campaign
```bash GET /constant-contact/v3/emails/{campaign_id} ```
#### Create Email Campaign
```bash POST /constant-contact/v3/emails Content-Type: application/json
{ "name": "March Newsletter", "email_campaign_activities": [ { "format_type": 5, "from_name": "Company Name", "from_email": "[email protected]", "reply_to_email": "[email protected]", "subject": "March Newsletter", "html_content": "<html><body><h1>Hello!</h1></body></html>" } ] } ```
#### Update Email Campaign Activity
```bash PUT /constant-contact/v3/emails/activities/{campaign_activity_id} Content-Type: application/json
{ "contact_list_ids": ["list-uuid-here"], "from_name": "Updated Name", "subject": "Updated Subject" } ```
#### Send Test Email
```bash POST /constant-contact/v3/emails/activities/{campaign_activity_id}/tests Content-Type: application/json
{ "email_addresses": ["[email protected]"] } ```
#### Schedule Email Campaign
```bash POST /constant-contact/v3/emails/activities/{campaign_activity_id}/schedules Content-Type: application/json
{ "scheduled_date": "2026-03-01T10:00:00Z" } ```
### Segments
#### List Segments
```bash GET /constant-contact/v3/segments ```
#### Get Segment
```bash GET /constant-contact/v3/segments/{segment_id} ```
#### Create Segment
```bash POST /constant-contact/v3/segments Content-Type: application/json
{ "name": "Engaged Subscribers", "segment_criteria": "..." } ```
#### Delete Segment
```bash DELETE /constant-contact/v3/segments/{segment_id} ```
### Bulk Activities
#### Import Contacts
```bash POST /constant-contact/v3/activities/contacts_file_import Content-Type: multipart/form-data
{file: contacts.csv, list_ids: ["list-uuid"]} ```
#### Add Contacts to Lists
```bash POST /constant-contact/v3/activities/add_list_memberships Content-Type: application/json
{ "source": { "contact_ids": ["contact-uuid-1", "contact-uuid-2"] }, "list_ids": ["list-uuid"] } ```
#### Remove Contacts from Lists
```bash POST /constant-contact/v3/activities/remove_list_memberships Content-Type: application/json
{ "source": { "list_ids": ["source-list-uuid"] }, "list_ids": ["target-list-uuid"] } ```
#### Delete Contacts in Bulk
```bash POST /constant-contact/v3/activities/contact_delete Content-Type: application/json
{ "contact_ids": ["contact-uuid-1", "contact-uuid-2"] } ```
#### Get Activity Status
```bash GET /constant-contact/v3/activities/{activity_id} ```
#### List Activities
```bash GET /constant-contact/v3/activities ```
### Reporting
#### Email Campaign Summaries
```bash GET /constant-contact/v3/reports/summary_reports/email_campaign_summaries ```
Query parameters: - `start` - Start date (ISO-8601) - `end` - End date (ISO-8601)
#### Get Email Campaign Report
```bash GET /constant-contact/v3/reports/email_reports/{campaign_activity_id} ```
#### Contact Activity Summary
```bash GET /constant-contact/v3/reports/contact_reports/{contact_id}/activity_summary ```
## Pagination
The API uses cursor-based pagination with a `limit` parameter:
```bash GET /constant-contact/v3/contacts?limit=50 ```
Response includes pagination links:
```json { "contacts": [...], "_links": { "next": { "href": "/v3/contacts?cursor=abc123" } } } ```
Use the cursor from the `next` link for subsequent pages:
```bash GET /constant-contact/v3/contacts?cursor=abc123 ```
## Code Examples
### JavaScript
```javascript const response = await fetch( 'https://gateway.maton.ai/constant-contact/v3/contacts?limit=50', { headers: { 'Authorization': `Bearer ${process.env.MATON_API_KEY}` } } ); const data = await response.json(); ```
### Python
```python import os import requests
response = requests.get( 'https://gateway.maton.ai/constant-contact/v3/contacts', headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'}, params={'limit': 50} ) data = response.json() ```
## Notes
- Resource IDs use UUID format (36 characters with hyphens) - All dates use ISO-8601 format: `YYYY-MM-DDThh:mm:ss.sZ` - Maximum 1,000 contact lists per account - A contact can belong to up to 50 lists - Bulk operations are asynchronous - check activity status for completion - Email campaigns require verified sender email addresses - `format_type: 5` for custom HTML emails - IMPORTANT: When using curl commands, use `curl -g` when URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to `jq` or other commands, environment variables like `$MATON_API_KEY` may not expand correctly in some shell environments
## Error Handling
| Status | Meaning | |--------|---------| | 400 | Missing Constant Contact connection or invalid request | | 401 | Invalid or missing Maton API key, or OAuth token expired | | 403 | Insufficient permissions for the requested operation | | 404 | Resource not found | | 409 | Conflict (e.g., duplicate email address) | | 429 | Rate limited | | 4xx/5xx | Passthrough error from Constant Contact API |
### Error Response Format
```json { "error_key": "unauthorized", "error_message": "Unauthorized" } ```
### Troubleshooting: API Key Issues
1. Check that the `MATON_API_KEY` environment variable is set:
```bash echo $MATON_API_KEY ```
2. Verify the API key is valid by listing connections:
```bash python <<'EOF' import urllib.request, os, json req = urllib.request.Request('https://ctrl.maton.ai/connections') req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}') print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2)) EOF ```
### Troubleshooting: Invalid App Name
1. Ensure your URL path starts with `constant-contact`. For example:
- Correct: `https://gateway.maton.ai/constant-contact/v3/contacts` - Incorrect: `https://gateway.maton.ai/v3/contacts`
## Resources
- [Constant Contact V3 API Overview](https://developer.constantcontact.com/api_guide/getting_started.html) - [API Reference](https://developer.constantcontact.com/api_reference/index.html) - [Technical Overview](https://developer.constantcontact.com/api_guide/v3_technical_overview.html) - [Contacts Overview](https://developer.constantcontact.com/api_guide/contacts_overview.html) - [Email Campaigns Guide](https://developer.constantcontact.com/api_guide/email_campaigns_get_started.html) - [Contact Lists Overview](https://v3.developer.constantcontact.com/api_guide/lists_overview.html) - [Maton Community](https://discord.com/invite/dBfFAcefs2) - [Maton Support](mailto:[email protected])