unsent
unsent.dev
API Reference

Campaigns

The Campaigns API allows you to create, manage, and monitor email campaigns at scale.

Base URL

https://api.unsent.dev/v1/campaigns

Features

Campaign creation

Create email campaigns with rich content

Scheduling

Schedule campaigns for optimal delivery times

Batch processing

Send to large contact lists efficiently

Campaign control

Pause, resume, and monitor active campaigns

Performance tracking

Real-time delivery and engagement metrics

Personalization

Use contact data for dynamic content

Endpoints

List Campaigns

Retrieve a list of all email campaigns for your team, ordered by creation date (newest first).

Endpoint: GET /v1/campaigns

Response Schema

Each campaign object in the array includes:

FieldTypeDescription
idstringUnique campaign identifier
namestringInternal campaign name
subjectstringEmail subject line
statusstring | nullCampaign status (DRAFT, SCHEDULED, SENDING, PAUSED, COMPLETED)
created_atstringISO 8601 timestamp of campaign creation
sentnumberNumber of emails sent
deliverednumberNumber of emails delivered
openednumberNumber of unique opens
clickednumberNumber of unique clicks

Response Example

[
  {
    "id": "cmp_abc123",
    "name": "Welcome Series - January 2024",
    "subject": "Welcome aboard! Let's get started",
    "status": "COMPLETED",
    "created_at": "2024-01-15T12:00:00.000Z",
    "sent": 1250,
    "delivered": 1240,
    "opened": 890,
    "clicked": 320
  },
  {
    "id": "cmp_xyz789",
    "name": "Holiday Promotion",
    "subject": "Special Holiday Offers Inside ๐ŸŽ",
    "status": "SENDING",
    "created_at": "2024-01-10T09:30:00.000Z",
    "sent": 5420,
    "delivered": 5380,
    "opened": 2150,
    "clicked": 640
  }
]

Create Campaign

Create a new email campaign. You can save it as a draft, send it immediately, or schedule it for later delivery.

Endpoint: POST /v1/campaigns

[!IMPORTANT] The campaign content MUST include an unsubscribe link placeholder {{unsent_unsubscribe_url}}. Campaigns without this placeholder will be rejected.

Request Body

FieldTypeRequiredDescription
namestringYesInternal name for the campaign (not visible to recipients)
fromstringYesSender email address (must be from a verified domain)
subjectstringYesEmail subject line
contactBookIdstringYesID of the contact book to send to
htmlstringNo*HTML content of the email
contentstringNo*Plain text or markdown content
previewTextstringNoPreview text shown in email client (recommended for better engagement)
replyTostring | string[]NoReply-to email address(es)
ccstring | string[]NoCC email address(es)
bccstring | string[]NoBCC email address(es)
sendNowbooleanNoIf true, sends the campaign immediately
scheduledAtstringNoSchedule time (ISO 8601 format or natural language)
batchSizenumberNoNumber of emails per batch (1-100,000). Helps control sending rate

*Either html or content must be provided

Natural Language Scheduling

The scheduledAt field supports both ISO 8601 timestamps and natural language:

  • ISO 8601: "2024-01-20T10:00:00Z"
  • Natural language: "tomorrow 10am", "next monday 9:30", "in 2 hours"

Request Example

{
  "name": "Weekly Newsletter - Week 3",
  "from": "newsletter@yourdomain.com",
  "subject": "This Week's Top Stories",
  "previewText": "Discover what happened this week in tech...",
  "contactBookId": "cb_123456",
  "html": "<html><body><h1>Hello {{firstName}}!</h1><p>Here are this week's highlights...</p><p><a href=\"{{unsent_unsubscribe_url}}\">Unsubscribe</a></p></body></html>",
  "replyTo": "support@yourdomain.com",
  "batchSize": 1000,
  "scheduledAt": "tomorrow 9am"
}

Response Schema

FieldTypeDescription
idstringUnique campaign identifier
namestringCampaign name
fromstringSender email address
subjectstringEmail subject line
previewTextstring | nullEmail preview text
contactBookIdstring | nullAssociated contact book ID
htmlstring | nullHTML content
contentstring | nullPlain text content
statusstringCurrent campaign status
scheduledAtstring | nullISO 8601 datetime when campaign is scheduled
batchSizenumberNumber of emails per batch
batchWindowMinutesnumberMinutes between batches
totalnumberTotal emails to send
sentnumberNumber of emails sent
deliverednumberNumber of emails delivered
openednumberNumber of unique opens
clickednumberNumber of unique clicks
unsubscribednumberNumber of unsubscribes
bouncednumberTotal bounces
hardBouncednumberNumber of hard bounces
complainednumberNumber of spam complaints
replyTostring[]Reply-to addresses
ccstring[]CC addresses
bccstring[]BCC addresses
createdAtstringISO 8601 timestamp of creation
updatedAtstringISO 8601 timestamp of last update

Response Example

{
  "id": "cmp_new789",
  "name": "Weekly Newsletter - Week 3",
  "from": "newsletter@yourdomain.com",
  "subject": "This Week's Top Stories",
  "previewText": "Discover what happened this week in tech...",
  "contactBookId": "cb_123456",
  "html": "<html><body><h1>Hello {{firstName}}!</h1><p>Here are this week's highlights...</p><p><a href=\"{{unsent_unsubscribe_url}}\">Unsubscribe</a></p></body></html>",
  "content": null,
  "status": "SCHEDULED",
  "scheduledAt": "2024-01-16T09:00:00.000Z",
  "batchSize": 1000,
  "batchWindowMinutes": 5,
  "total": 0,
  "sent": 0,
  "delivered": 0,
  "opened": 0,
  "clicked": 0,
  "unsubscribed": 0,
  "bounced": 0,
  "hardBounced": 0,
  "complained": 0,
  "replyTo": ["support@yourdomain.com"],
  "cc": [],
  "bcc": [],
  "createdAt": "2024-01-15T14:30:00.000Z",
  "updatedAt": "2024-01-15T14:30:00.000Z"
}

Get Campaign

Retrieve detailed information and statistics for a specific campaign.

Endpoint: GET /v1/campaigns/{campaignId}

Path Parameters

ParameterTypeDescription
campaignIdstringThe campaign ID (e.g., cmp_123)

Response Schema

Same as the Create Campaign response schema (see above).

Response Example

{
  "id": "cmp_abc123",
  "name": "Product Launch Campaign",
  "from": "launches@yourdomain.com",
  "subject": "Introducing Our Latest Product!",
  "previewText": "Be the first to experience our revolutionary new feature",
  "contactBookId": "cb_456789",
  "html": "<html><body>...</body></html>",
  "content": null,
  "status": "COMPLETED",
  "scheduledAt": null,
  "batchSize": 500,
  "batchWindowMinutes": 5,
  "total": 10000,
  "sent": 10000,
  "delivered": 9850,
  "opened": 6200,
  "clicked": 2100,
  "unsubscribed": 45,
  "bounced": 150,
  "hardBounced": 80,
  "complained": 3,
  "replyTo": ["support@yourdomain.com"],
  "cc": [],
  "bcc": ["archive@yourdomain.com"],
  "createdAt": "2024-01-10T08:00:00.000Z",
  "updatedAt": "2024-01-10T16:45:00.000Z"
}

Schedule Campaign

Schedule or reschedule an existing campaign for future delivery.

Endpoint: POST /v1/campaigns/{campaignId}/schedule

Path Parameters

ParameterTypeDescription
campaignIdstringThe campaign ID (e.g., cmp_123)

Request Body

FieldTypeRequiredDescription
scheduledAtstringNoDate/time to send (ISO 8601 or natural language like "tomorrow 10am", "next monday 9:30")
batchSizenumberNoMax emails per batch (1-100,000)

Request Example

{
  "scheduledAt": "tomorrow 10am",
  "batchSize": 2000
}

Response Example

{
  "success": true
}

Pause Campaign

Pause a currently running campaign. The campaign will stop sending and can be resumed later.

Endpoint: POST /v1/campaigns/{campaignId}/pause

Path Parameters

ParameterTypeDescription
campaignIdstringThe campaign ID (e.g., cmp_123)

Response Example

{
  "success": true
}

Resume Campaign

Resume a paused campaign. Sending will continue from where it left off.

Endpoint: POST /v1/campaigns/{campaignId}/resume

Path Parameters

ParameterTypeDescription
campaignIdstringThe campaign ID (e.g., cmp_123)

Response Example

{
  "success": true
}

Best Practices

[!WARNING] All campaigns MUST include the {{unsent_unsubscribe_url}} placeholder in your HTML or content. This ensures compliance with email regulations (CAN-SPAM, GDPR) and provides recipients with an easy way to opt out.

<!-- Required: Include this in every campaign -->
<p style="text-align: center; margin-top: 40px;">
  <a href="{{unsent_unsubscribe_url}}" style="color: #666; text-decoration: underline;">
    Unsubscribe from these emails
  </a>
</p>

Batch Sending

For large campaigns, use batch sending to control your sending rate and improve deliverability:

  • Small campaigns (< 1,000): No batching needed
  • Medium campaigns (1,000 - 10,000): Use batchSize: 500-1000
  • Large campaigns (> 10,000): Use batchSize: 1000-2000

Scheduling Tips

  • Schedule campaigns during optimal engagement times (typically weekday mornings)
  • Use natural language for convenience: "tomorrow 9am", "next tuesday 10:30"
  • Avoid scheduling during weekends unless your audience engages then
  • Consider time zones of your recipients

Campaign Personalization

Use contact properties to personalize your campaigns with dynamic content:

<html>
  <body>
    <h1>Hi {{firstName}} {{lastName}}!</h1>
    <p>Dear {{firstName}},</p>
    <p>As a valued {{properties.tier}} member since {{properties.joinDate}}, 
       you have access to exclusive benefits.</p>
    
    <p>Your account email: {{email}}</p>
    
    <!-- Required unsubscribe link -->
    <p><a href="{{unsent_unsubscribe_url}}">Unsubscribe</a></p>
  </body>
</html>

Available Template Variables

  • {{firstName}} - Contact's first name
  • {{lastName}} - Contact's last name
  • {{email}} - Contact's email address
  • {{properties.KEY}} - Any custom contact property
  • {{unsent_unsubscribe_url}} - Unsubscribe link (required)

API Reference