SMTP Ghost API
Lists & Campaigns API Documentation
Overview
The SMTP Ghost API allows you to manage contact lists and schedule emails for your campaigns. Our API is RESTful, returns JSON responses, and uses standard HTTP status codes.
Get Started
Sign up for an account to get your API key and start integrating with our platform.
Authentication
All API requests require authentication using your API key. Include your API key in the request headers:
X-API-KEY: your_api_key_here
You can find your API key in your account's developer settings after signing up.
Base URL
https://smtpghost.com/api/v1
Lists Endpoints
Get All Lists
/api/v1/lists
Retrieve all lists in your organization with campaign and contact information.
Example Response
{
"status": "success",
"data": [
{
"id": 123,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Marketing Leads Q1",
"contacts_count": 1500,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T15:45:00Z",
"has_campaign": true,
"campaign_id": 456,
"campaign_name": "Q1 Outreach"
}
],
"total": 5
}
Get Single List
/api/v1/lists/:uuid
Retrieve details of a specific list by UUID.
Example Response
{
"status": "success",
"data": {
"id": 123,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Marketing Leads Q1",
"contacts_count": 1500,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T15:45:00Z",
"has_campaign": true,
"campaign_id": 456,
"campaign_name": "Q1 Outreach"
}
}
Create New List
/api/v1/lists
Create a new contact list.
Request Body
{
"list": {
"name": "New Customer List"
}
}
Example Response
{
"status": "success",
"message": "List created successfully",
"data": {
"id": 124,
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"name": "New Customer List",
"contacts_count": 0
}
}
Get Contacts from List
/api/v1/lists/:uuid/contacts
Retrieve all contacts from a specific list with their fields and email validation status.
Query Parameters:
page
per_page
Example Response
{
"status": "success",
"data": {
"contacts": [
{
"id": 123456,
"email": "john.doe@example.com",
"email_valid": true,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-20T15:45:00Z",
"fields": {
"first_name": "John",
"last_name": "Doe",
"company": "Acme Corp",
"title": "CEO",
"phone": "+1234567890",
"industry": "Technology",
"website": "acme.com"
}
}
],
"pagination": {
"current_page": 1,
"per_page": 100,
"total_pages": 3,
"total_contacts": 250
}
}
}
Add Contacts to List
/api/v1/lists/:uuid/contacts
Add contacts to an existing list. Supports bulk import up to 1000 contacts per request.
Query Parameters:
remove_duplicates
auto_clean
Contact Data Structure:
Email: Stored directly on the contact record
email
*required - Contact's email addressStandard Fields: Stored as ContactField records with predefined names
first_name
- First namelast_name
- Last namephone
- Phone numbercompany
- Company nametitle
- Job titleCustom Fields: Also stored as ContactField records with any name you choose
custom_fields
- Object with any key-value pairs (industry, budget, lead_source, etc.)
Note: All fields except email
are stored as ContactField records.
The distinction between "standard" and "custom" fields is just for API convenience - they're implemented identically.
Complete Request Example
POST /api/v1/lists/550e8400-e29b-41d4-a716-446655440000/contacts?remove_duplicates=true&auto_clean=true
{
"contacts": [
{
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+1-555-123-4567",
"company": "Acme Corporation",
"title": "CEO",
"custom_fields": {
"industry": "Technology",
"company_size": "50-100",
"location": "San Francisco, CA",
"lead_source": "Website",
"budget": "10k+",
"linkedin": "https://linkedin.com/in/johndoe",
"website": "https://acme.com",
"notes": "Interested in enterprise solution"
}
},
{
"email": "jane.smith@techcorp.com",
"first_name": "Jane",
"last_name": "Smith",
"company": "TechCorp",
"title": "CTO",
"custom_fields": {
"industry": "SaaS",
"company_size": "100-500",
"lead_source": "LinkedIn"
}
}
]
}
Example Response
{
"status": "success",
"message": "Successfully processed contacts",
"data": {
"total_submitted": 2,
"total_added": 2,
"new_contacts": 1,
"existing_contacts_added": 1,
"duplicates_removed": 0,
"invalid_emails": [],
"list_uuid": "550e8400-e29b-41d4-a716-446655440000",
"contacts_count": 1502
}
}
Parameter Usage Examples
?remove_duplicates=true
- Existing contacts in your organization won't be duplicated?auto_clean=true
- Contacts will be queued for email validation?remove_duplicates=true&auto_clean=true
- Recommended for clean dataCampaigns Endpoints
Schedule Contacts for Campaign
/api/v1/campaigns/:uuid/schedule_contacts
Add contacts to an evergreen campaign and schedule them for email delivery. This endpoint combines adding contacts to the campaign's list and scheduling emails in a single operation.
Requirements
- • Campaign must be evergreen (non-evergreen campaigns will return an error)
- • Campaign must have at least one associated list
Behavior by Campaign Status
- • Active campaigns (sending, scheduled): Contacts added and emails scheduled immediately
- • Paused campaigns: Contacts added but emails NOT scheduled until campaign is resumed
- • Non-evergreen campaigns: Returns error regardless of status
Request Parameters:
remove_duplicates
Contact Data Structure:
Uses the same field structure as the Lists API:
email
*required - Stored on contact recordfirst_name
, last_name
, phone
, company
, title
custom_fields
objectRequest Body
{
"contacts": [
{
"email": "john.doe@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+1234567890",
"company": "Acme Corp",
"title": "CEO",
"custom_fields": {
"industry": "Technology",
"source": "Website",
"budget": "10k+"
}
}
],
"remove_duplicates": false
}
Success Response (Active Campaign)
{
"status": "success",
"message": "1 new contacts added and will be scheduled shortly",
"data": {
"campaign": {
"uuid": "91196fbbffcd9580e8982c214b09577e7ddcebc1",
"name": "Q1 Outreach Campaign",
"status": "sending",
"evergreen": true
},
"list": {
"uuid": "9a3e2346",
"name": "Campaign Prospects",
"total_contacts": 150
},
"contacts_processed": {
"total_submitted": 1,
"new_contacts_added": 1,
"duplicates_skipped": 0,
"invalid_emails": []
},
"scheduled": true
}
}
Success Response (Paused Campaign)
{
"status": "success",
"message": "1 new contacts added to paused campaign. Resume campaign to schedule emails.",
"data": {
"campaign": {
"uuid": "b30f0377cb4c977e05ca28163a3add33fbc12695",
"name": "Paused Campaign",
"status": "paused",
"evergreen": true
},
"contacts_processed": {
"total_submitted": 1,
"new_contacts_added": 1,
"duplicates_skipped": 0,
"invalid_emails": []
},
"scheduled": false
}
}
Error Response (Non-Evergreen Campaign)
{
"status": "error",
"message": "Only evergreen campaigns can schedule new contacts. Please create an evergreen campaign.",
"current_state": "complete",
"evergreen": false
}
Interactive Examples
These examples use your actual API key and UUIDs. Select different lists or campaigns to see the examples update automatically.
No lists available - create a list first
No evergreen campaigns available - create an evergreen campaign first
cURL Examples
Create a new list:
curl -X POST https://smtpghost.com/api/v1/lists \
-H "X-API-KEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"list": {
"name": "My New Contact List"
}
}'
Add contacts to a list:
curl -X POST "https://smtpghost.com/api/v1/lists/your-list-uuid/contacts?remove_duplicates=true&auto_clean=true" \
-H "X-API-KEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{
"email": "contact@example.com",
"first_name": "John",
"last_name": "Doe",
"phone": "+1-555-123-4567",
"company": "Acme Corp",
"title": "CEO",
"custom_fields": {
"industry": "Technology",
"company_size": "50-100",
"lead_source": "Website",
"budget": "10k+",
"location": "San Francisco, CA"
}
}
]
}'
Schedule contacts for campaign:
curl -X POST https://smtpghost.com/api/v1/campaigns/your-campaign-uuid/schedule_contacts \
-H "X-API-KEY: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"contacts": [
{
"email": "prospect@example.com",
"first_name": "Jane",
"last_name": "Smith",
"company": "Target Corp",
"custom_fields": {
"industry": "SaaS",
"lead_source": "LinkedIn",
"company_size": "50-100"
}
}
],
"remove_duplicates": false
}'
JavaScript Example
const API_KEY = 'your_api_key_here';
const BASE_URL = 'https://smtpghost.com/api/v1';
async function scheduleContactsForCampaign(campaignUuid, contacts) {
const response = await fetch(`${BASE_URL}/campaigns/${campaignUuid}/schedule_contacts`, {
method: 'POST',
headers: {
'X-API-KEY': API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
contacts: contacts,
remove_duplicates: false
})
});
const result = await response.json();
if (result.status === 'success') {
console.log(`${result.data.contacts_processed.new_contacts_added} contacts scheduled`);
} else {
console.error('Error:', result.message);
}
return result;
}
// Usage with your selected campaign
scheduleContactsForCampaign('your-campaign-uuid', [
{
email: 'prospect@example.com',
first_name: 'John',
last_name: 'Doe',
company: 'Target Corp',
custom_fields: {
industry: 'Technology',
company_size: '50-100'
}
}
]);
Python Example
import requests
API_KEY = 'your_api_key_here'
BASE_URL = 'https://smtpghost.com/api/v1'
headers = {
'X-API-KEY': API_KEY,
'Content-Type': 'application/json'
}
def schedule_contacts_for_campaign(campaign_uuid, contacts):
data = {
'contacts': contacts,
'remove_duplicates': False
}
response = requests.post(
f'{BASE_URL}/campaigns/{campaign_uuid}/schedule_contacts',
headers=headers,
json=data
)
result = response.json()
if result['status'] == 'success':
added = result['data']['contacts_processed']['new_contacts_added']
print(f'{added} contacts scheduled successfully')
else:
print(f'Error: {result["message"]}')
return result
# Usage with your selected campaign
contacts = [
{
'email': 'prospect@example.com',
'first_name': 'John',
'last_name': 'Doe',
'company': 'Target Corp',
'custom_fields': {
'industry': 'Technology',
'lead_source': 'Website'
}
}
]
schedule_contacts_for_campaign('your-campaign-uuid', contacts)
Error Handling
All error responses follow a consistent format with standard HTTP status codes.
Error Response Format
{
"status": "error",
"message": "Error description",
"errors": ["Detailed error messages"]
}
HTTP Status Codes
Common Error Examples
Invalid API Key (401)
{
"status": "error",
"message": "Unauthorized: Invalid API Key or Organization not found"
}
Campaign Not Found (404)
{
"status": "error",
"message": "Campaign not found"
}
Non-Evergreen Campaign (422)
{
"status": "error",
"message": "Only evergreen campaigns can schedule new contacts. Please create an evergreen campaign.",
"current_state": "complete",
"evergreen": false
}
Rate Limits
- • Maximum 1000 contacts per bulk import request
- • API rate limits apply based on your plan
- • Background processing for email scheduling happens asynchronously
Best Practices
- • Always check the response status before processing data
- • Handle errors gracefully and provide meaningful feedback to users
- • Use the
scheduled
field to confirm if emails were scheduled - • Store UUIDs for future API calls rather than internal IDs
- • Validate email addresses before sending to reduce invalid_emails
Ready to Get Started?
Sign up for an account to get your API key and start building with our platform.