Campaign Management — Technical Documentation
Last updated: February 2026
Table of Contents
- Overview
- Architecture
- Repository Map
- Core Flows
- Entities & Data Model
- API Endpoints
- Services & Business Logic
- Company Suitability (AI Integration)
- Configuration
- Integration Points
1. Overview
Campaign Management handles the full lifecycle of outbound prospecting campaigns — creation, audience linking, company suitability scoring via AI, email configuration, scheduling, statistics, and status transitions. It spans 5 repositories: sopromasterdata (Data API), data-admin (frontend), sopro-sodastream (legacy CRM), sopro-sodastream-core (queue consumers), and email-template-demo (AIM service for AI scoring).
2. Architecture
3. Repository Map
| Repository | Layer | Key Files |
|---|
| sopromasterdata | Controller | API/SoProMasterDBAPI/Controllers/CampaignController.cs |
| sopromasterdata | Service | CampaignServices/CampaignService.cs |
| sopromasterdata | Suitability | CompanySuitabilityServices/CompanySuitabilityService.cs |
| sopromasterdata | EndpointManager | Shared/EndpointManager/EndpointManagerService.cs |
| sopromasterdata | Entities | CampaignEntities/Campaign.cs, CampaignSender.cs |
| sopromasterdata | Hangfire | HangfireServices/CampaignHangfireService.cs |
| data-admin | Pages | src/pages/campaigns/ |
| data-admin | API Hooks | src/api/campaign.queries.ts |
| sopro-sodastream | Campaign UI | Controllers/CampaignController.cs (MVC) |
| sopro-sodastream-core | Queue Consumer | SoProQueueConsumer/ |
| email-template-demo | Suitability API | Controllers/CompanySuitabilityController.cs |
4. Core Flows
4.1 Campaign Creation
4.2 Company Suitability Scoring
4.3 Campaign Statistics Recalculation
5. Entities & Data Model
Campaign
| Column | Type | Description |
|---|
Id | int (PK) | Campaign identifier |
Name | nvarchar(255) | Campaign display name |
ClientId | int (FK) | Client who owns the campaign |
AudienceId | int (FK) | Linked audience |
Status | int (enum) | Setup, Active, Paused, Completed |
StartDate | datetime? | Campaign start date |
EndDate | datetime? | Campaign end date |
CreatedAt | datetime | Creation timestamp |
CreatedBy | nvarchar(100) | Creator identifier |
CampaignSender
| Column | Type | Description |
|---|
Id | int (PK) | Sender profile identifier |
CampaignId | int (FK) | Parent campaign |
Email | nvarchar(255) | Sender email address |
DisplayName | nvarchar(255) | Sender display name |
TrackingDomain | nvarchar(255) | Domain for open/click tracking |
CompanySuitabilityResult
| Column | Type | Description |
|---|
Id | int (PK) | Result identifier |
CampaignId | int (FK) | Campaign being scored for |
CompanyId | int (FK) | Company being scored |
Score | decimal | Suitability score (0-100) |
Reasoning | nvarchar(max) | AI-generated explanation |
Provider | nvarchar(50) | AI provider used (OpenAI, Anthropic, etc.) |
ScoredAt | datetime | When scoring occurred |
CampaignStatistics
| Column | Type | Description |
|---|
CampaignId | int (FK) | Campaign reference |
TotalProspects | int | Total audience size |
Contacted | int | Number contacted |
Opens | int | Email opens |
Clicks | int | Link clicks |
Replies | int | Responses received |
Bounces | int | Failed deliveries |
CalculatedAt | datetime | Last recalculation |
6. API Endpoints
Data API (/api/Campaign)
| Method | Endpoint | Description |
|---|
GET | /api/Campaign/GetCampaigns | List campaigns with pagination |
GET | /api/Campaign/GetCampaignById/{id} | Campaign detail |
GET | /api/Campaign/GetCampaignStatistics/{id} | Campaign statistics |
POST | /api/Campaign/Create | Create campaign |
Admin API (/api/admin/Campaign)
| Method | Endpoint | Description |
|---|
POST | /api/admin/Campaign/ScoreCompanies/{id} | Trigger company suitability scoring |
POST | /api/admin/Campaign/RecalculateStatistics/{id} | Trigger stats recalculation |
AIM Service (Company Suitability)
| Method | Endpoint | Description |
|---|
POST | /api/v5/company-suitability-v1 | Score a company for campaign fit |
7. Services & Business Logic
CampaignService
Location: CampaignServices/CampaignService.cs
Interface: ICampaignService
DI: AddScoped<ICampaignService, CampaignService>() in ApiServiceExtensions.cs
| Method | Description |
|---|
CreateCampaignAsync() | Creates campaign with sender profiles and audience link |
GetCampaignByIdAsync() | Returns campaign with stats |
GetCampaignStatisticsAsync() | Returns calculated statistics |
RecalculateStatisticsAsync() | Recounts all prospect statuses |
CompanySuitabilityService
Location: CompanySuitabilityServices/CompanySuitabilityService.cs
Interface: ICompanySuitabilityService
| Method | Description |
|---|
ScoreCompanyAsync() | Scores a single company via EndpointManager → AIM |
ScoreCompaniesForCampaignAsync() | Batch-scores all companies for a campaign |
EndpointManager
Location: Shared/EndpointManager/EndpointManagerService.cs
Purpose: Routes HTTP calls to Sopro internal services (AIM, etc.)
The EndpointManager abstracts the HTTP communication with AIM. It handles:
- Endpoint URL resolution
- Authentication headers
- Retry logic and error handling
- Response deserialization
8. Company Suitability (AI Integration)
AIM Service Architecture
The AIM service (email-template-demo repo, hosted at aim.sopro.io) provides the company suitability scoring endpoint.
Request Payload
The suitability request includes:
| Field | Description |
|---|
companyName | Company name |
companyWebsite | Company website URL |
companyIndustry | Company industry classification |
companySize | Employee count range |
campaignBrief | Client's ideal customer description |
valueProposition | What the client's product/service offers |
Response
| Field | Description |
|---|
score | 0-100 suitability score |
reasoning | Natural language explanation of the score |
provider | Which AI model was used |
9. Configuration
DI Registration
DataApi: API/SoProMasterDBAPI/Extensions/ApiServiceExtensions.cs
services.AddScoped<ICampaignService, CampaignService>();
services.AddScoped<ICompanySuitabilityService, CompanySuitabilityService>();
EndpointManager Configuration
Configured via appSettings.Global.json:
{
"EndpointManager": {
"CompanySuitability": {
"Url": "https://aim.sopro.io/api/v5/company-suitability-v1",
"ApiKey": "<configured-per-environment>"
}
}
}
Frontend Configuration
API Hooks: src/api/campaign.queries.ts
Endpoints: src/api/endpoints.ts → endpoints.campaigns
10. Integration Points
Upstream (data flows in)
| Source | Data | Mechanism |
|---|
| Audience Management | Prospect list for campaigns | Audience linked via AudienceId FK |
| AIM Service | Company suitability scores | HTTP via EndpointManager |
| Sodastream | Campaign configuration, scheduling | Direct DB access |
Downstream (data flows out)
| Target | Data | Mechanism |
|---|
| Email Sending | Campaign email schedule | Azure Queue / Hangfire |
| Email Finding | Prospect email requests | Hangfire jobs → email-finder |
| Data Admin UI | Campaign stats, details | REST API → React Query |
| Audience Management | Campaign status (affects deduplication) | Shared DB |
Cross-Feature Dependencies
| Feature | Relationship |
|---|
| Audience Management | Campaigns require linked audiences |
| Email Sending | Campaign scheduling triggers email delivery |
| Generative Messaging | AIM generates email content per campaign |
| Company Suitability | AI scores determine prospect prioritization |
| Email Finding | Campaign prospects need email addresses found |