A Spring Boot backend that wraps the Mailchimp Marketing API into clean, RESTful endpoints. Manage audiences, subscribers, campaigns, templates, and reports through a single, well-structured Java service.
- Audience Management — Create, update, delete, and fetch stats for Mailchimp lists
- Subscriber Management — Add, upsert, tag, and track subscriber activity
- Campaign Lifecycle — Create → Set content → Schedule / Send → Report
- Template Management — Create and manage reusable HTML email templates
- MD5 Subscriber Hashing — Automatic email normalisation as required by Mailchimp
- Global Exception Handling — Consistent error responses across all endpoints
- Swagger UI — Interactive API documentation at
/swagger-ui.html - Actuator — Health and metrics endpoints out of the box
- Validation — Bean Validation on all request bodies
| Layer | Technology |
|---|---|
| Language | Java 17 |
| Framework | Spring Boot 3.2.4 |
| HTTP Client | Spring RestTemplate (Basic Auth interceptor) |
| API Docs | SpringDoc OpenAPI 3 / Swagger UI |
| Validation | Jakarta Bean Validation |
| Logging | SLF4J + Logback |
| Build Tool | Maven |
| Testing | JUnit 5, Mockito |
mailchimp-marketing/
├── src/
│ ├── main/
│ │ ├── java/com/mailchimp/marketing/
│ │ │ ├── MailchimpMarketingApplication.java
│ │ │ ├── config/
│ │ │ │ ├── MailchimpProperties.java # @ConfigurationProperties binding
│ │ │ │ ├── MailchimpClientConfig.java # RestTemplate + Basic Auth interceptor
│ │ │ │ └── OpenApiConfig.java # Swagger / OpenAPI bean
│ │ │ ├── controller/
│ │ │ │ ├── AudienceController.java # GET/POST/PATCH/DELETE /audiences
│ │ │ │ ├── SubscriberController.java # Nested under /audiences/{id}/subscribers
│ │ │ │ ├── CampaignController.java # Full campaign lifecycle
│ │ │ │ ├── TemplateController.java # HTML template CRUD
│ │ │ │ └── HealthController.java # /ping, /info
│ │ │ ├── dto/
│ │ │ │ ├── request/
│ │ │ │ │ ├── CreateAudienceRequest.java
│ │ │ │ │ ├── SubscriberRequest.java
│ │ │ │ │ ├── CampaignRequest.java
│ │ │ │ │ ├── CampaignContentRequest.java
│ │ │ │ │ └── TagRequest.java
│ │ │ │ └── response/
│ │ │ │ └── ApiResponse.java # Generic wrapper {success, message, data}
│ │ │ ├── exception/
│ │ │ │ ├── MailchimpApiException.java
│ │ │ │ └── GlobalExceptionHandler.java # @RestControllerAdvice
│ │ │ └── service/
│ │ │ ├── AudienceService.java
│ │ │ ├── SubscriberService.java
│ │ │ ├── CampaignService.java
│ │ │ ├── TemplateService.java
│ │ │ └── impl/
│ │ │ ├── AudienceServiceImpl.java
│ │ │ ├── SubscriberServiceImpl.java
│ │ │ ├── CampaignServiceImpl.java
│ │ │ └── TemplateServiceImpl.java
│ │ └── resources/
│ │ └── application.yml
│ └── test/
│ └── java/com/mailchimp/marketing/
│ ├── MailchimpMarketingApplicationTest.java
│ └── SubscriberServiceImplTest.java
├── .env.example
├── .gitignore
└── pom.xml
- Log in to Mailchimp
- Go to Account → Extras → API Keys
- Click Create A Key
- Copy the key — it ends with your server prefix, e.g.
abc123def456...xyz-us14
cp .env.example .envEdit .env:
MAILCHIMP_API_KEY=your-api-key-here-us14
MAILCHIMP_SERVER_PREFIX=us14Tip: The server prefix is the part after the dash at the end of your API key.
mailchimp:
api:
key: ${MAILCHIMP_API_KEY}
server-prefix: ${MAILCHIMP_SERVER_PREFIX:us1}
base-url: https://${mailchimp.api.server-prefix}.api.mailchimp.com/3.0- Java 17+
- Maven 3.8+
# Clone the repository
git clone https://github.com/gajendra-ingle/mailchimp-marketing.git
cd mailchimp-marketing
# Set environment variables (Linux/macOS)
export MAILCHIMP_API_KEY=your-api-key
export MAILCHIMP_SERVER_PREFIX=us1
# Build and run
mvn spring-boot:runThe app starts on http://localhost:8080
curl http://localhost:8080/api/v1/pingExpected response:
{
"success": true,
"message": "Mailchimp API connected successfully",
"data": { "health_status": "Everything's Chimpy!" },
"timestamp": "2025-01-01T10:00:00"
}Once running, open: http://localhost:8080/swagger-ui.html
All endpoints are fully documented with request/response schemas.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/audiences |
List all audiences |
GET |
/api/v1/audiences/{listId} |
Get audience by ID |
GET |
/api/v1/audiences/{listId}/stats |
Get audience statistics |
POST |
/api/v1/audiences |
Create a new audience |
PATCH |
/api/v1/audiences/{listId} |
Update an audience |
DELETE |
/api/v1/audiences/{listId} |
Delete an audience |
Create Audience — Request Body:
{
"name": "My Newsletter",
"permission_reminder": "You signed up on our website",
"email_type_option": false,
"contact": {
"company": "Acme Corp",
"address1": "123 Main St",
"city": "Chicago",
"state": "IL",
"zip": "60601",
"country": "US"
},
"campaign_defaults": {
"from_name": "Acme Team",
"from_email": "news@acme.com",
"subject": "Our Latest News",
"language": "EN_US"
}
}| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/audiences/{listId}/subscribers |
List all subscribers |
GET |
/api/v1/audiences/{listId}/subscribers/{email} |
Get subscriber by email |
POST |
/api/v1/audiences/{listId}/subscribers |
Add new subscriber |
PUT |
/api/v1/audiences/{listId}/subscribers/{email} |
Upsert subscriber |
PATCH |
/api/v1/audiences/{listId}/subscribers/{email}/status |
Update status |
POST |
/api/v1/audiences/{listId}/subscribers/{email}/tags |
Add/remove tags |
GET |
/api/v1/audiences/{listId}/subscribers/{email}/activity |
Get activity history |
DELETE |
/api/v1/audiences/{listId}/subscribers/{email} |
Delete subscriber |
Add Subscriber — Request Body:
{
"email_address": "jane@example.com",
"status": "subscribed",
"merge_fields": {
"FNAME": "Jane",
"LNAME": "Doe"
},
"tags": ["vip", "newsletter"]
}Note: Email addresses are automatically MD5-hashed when used in path variables, as required by Mailchimp.
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/campaigns |
List all campaigns |
GET |
/api/v1/campaigns/{campaignId} |
Get campaign by ID |
POST |
/api/v1/campaigns |
Create campaign |
PATCH |
/api/v1/campaigns/{campaignId} |
Update campaign |
GET |
/api/v1/campaigns/{campaignId}/content |
Get campaign content |
PUT |
/api/v1/campaigns/{campaignId}/content |
Set campaign HTML/content |
POST |
/api/v1/campaigns/{campaignId}/actions/send |
Send immediately |
POST |
/api/v1/campaigns/{campaignId}/actions/schedule |
Schedule send |
POST |
/api/v1/campaigns/{campaignId}/actions/unschedule |
Unschedule |
POST |
/api/v1/campaigns/{campaignId}/actions/test |
Send test email |
GET |
/api/v1/campaigns/{campaignId}/report |
Get performance report |
DELETE |
/api/v1/campaigns/{campaignId} |
Delete campaign |
Create Campaign — Request Body:
{
"type": "regular",
"recipients": {
"list_id": "abc123def"
},
"settings": {
"subject_line": "Your monthly update 🎉",
"preview_text": "See what's new this month",
"title": "March Newsletter",
"from_name": "Acme Team",
"reply_to": "news@acme.com"
}
}Set Campaign Content:
{
"html": "<html><body><h1>Hello *|FNAME|*!</h1></body></html>"
}Schedule Campaign:
POST /api/v1/campaigns/{id}/actions/schedule?scheduleTime=2025-12-01T10:00:00+00:00
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/templates |
List all templates |
GET |
/api/v1/templates/{templateId} |
Get template by ID |
GET |
/api/v1/templates/{templateId}/default-content |
Get default content |
POST |
/api/v1/templates |
Create HTML template |
PATCH |
/api/v1/templates/{templateId} |
Update template |
DELETE |
/api/v1/templates/{templateId} |
Delete template |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/ping |
Verify Mailchimp API connection |
GET |
/api/v1/info |
Get Mailchimp account info |
GET |
/actuator/health |
Spring Boot health check |
All endpoints return a consistent wrapper:
{
"success": true,
"message": "Operation completed successfully",
"data": { ... },
"timestamp": "2025-03-28T10:30:00"
}Error responses:
{
"success": false,
"message": "Audience not found: abc123",
"timestamp": "2025-03-28T10:30:00"
}Validation errors:
{
"success": false,
"message": "Validation failed",
"data": {
"emailAddress": "Valid email address is required",
"name": "Audience name is required"
}
}mvn testTests cover MD5 hashing logic and Spring context loading.
- Batch subscriber operations (bulk add/remove)
- Webhook receiver for subscribe/unsubscribe events
- Segment management endpoints
- Redis caching for audience and template metadata
- Docker Compose setup
- Spring Security for API key authentication on own endpoints