curl -X POST "https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": ["Replied", "Opened"],
"campaignId": [12345, 12346],
"leadCategories": {
"categoryIdsIn": [1]
},
"replyTimeBetween": ["2025-01-01T00:00:00Z", "2025-01-31T23:59:59Z"]
},
"sortBy": "REPLY_TIME_DESC"
}'
import requests
from datetime import datetime, timedelta
API_KEY = "YOUR_API_KEY"
# Example 1: Get replied emails from last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + 'Z'
now = datetime.now().isoformat() + 'Z'
payload = {
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": "Replied",
"replyTimeBetween": [seven_days_ago, now],
"leadCategories": {
"categoryIdsIn": [1] # Interested leads only
}
},
"sortBy": "REPLY_TIME_DESC"
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
result = response.json()
print(f"Found {result.get('total_count', 0)} interested replies in last 7 days")
for msg in result.get('messages', []):
print(f"- {msg['lead']['email']}: {msg['email_status']}")
const API_KEY = 'YOUR_API_KEY';
// Example 2: Get opened but not replied emails from specific campaign
const payload = {
offset: 0,
limit: 20,
filters: {
emailStatus: ['Opened', 'Clicked'], // Engaged but not replied
campaignId: 12345,
leadCategories: {
unassigned: true // Not yet categorized
}
},
sortBy: 'SENT_TIME_DESC'
};
const response = await fetch(
`https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=${API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}
);
const result = await response.json();
console.log(`${result.total_count} engaged leads need follow-up`);
# Example 3: Multi-campaign performance comparison
payload = {
"filters": {
"campaignId": [12345, 12346, 12347], # Multiple campaigns
"emailStatus": ["Replied", "Opened", "Clicked"],
"campaignTeamMemberId": 456, # Specific team member
"campaignTagId": 5 # VIP tag
},
"limit": 20
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
# Group by campaign for comparison
results_by_campaign = {}
for msg in response.json().get('messages', []):
campaign_id = msg['campaign']['id']
if campaign_id not in results_by_campaign:
results_by_campaign[campaign_id] = []
results_by_campaign[campaign_id].append(msg)
for campaign_id, messages in results_by_campaign.items():
print(f"Campaign {campaign_id}: {len(messages)} engaged leads")
{
"messages": [
{
"id": "msg_abc123",
"campaign_lead_map_id": "2433664091",
"lead": {
"email": "john@company.com",
"first_name": "John",
"last_name": "Doe",
"company": "ACME Corp"
},
"campaign": {
"id": 12345,
"name": "Q1 2025 Outreach"
},
"email_account": {
"id": 789,
"email": "sales@yourcompany.com"
},
"last_message": {
"subject": "Partnership Opportunity",
"sent_at": "2025-01-15T10:00:00Z",
"opened_at": "2025-01-15T10:30:00Z",
"replied_at": "2025-01-15T14:00:00Z"
},
"email_status": "Replied",
"category": {
"id": 1,
"name": "Interested"
},
"assigned_to": {
"id": 456,
"name": "Jane Smith"
},
"stats": {
"opens": 2,
"clicks": 1,
"replies": 1
}
}
],
"total_count": 1,
"offset": 0,
"limit": 20
}
{
"message": "Invalid API Key"
}
{
"error": "limit must be between 1 and 20",
"field": "limit",
"provided_value": 50
}
Master Inbox
Get Sent Emails
Retrieve all sent emails across campaigns with comprehensive filtering and pagination
POST
/
api
/
v1
/
master-inbox
/
sent
curl -X POST "https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": ["Replied", "Opened"],
"campaignId": [12345, 12346],
"leadCategories": {
"categoryIdsIn": [1]
},
"replyTimeBetween": ["2025-01-01T00:00:00Z", "2025-01-31T23:59:59Z"]
},
"sortBy": "REPLY_TIME_DESC"
}'
import requests
from datetime import datetime, timedelta
API_KEY = "YOUR_API_KEY"
# Example 1: Get replied emails from last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + 'Z'
now = datetime.now().isoformat() + 'Z'
payload = {
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": "Replied",
"replyTimeBetween": [seven_days_ago, now],
"leadCategories": {
"categoryIdsIn": [1] # Interested leads only
}
},
"sortBy": "REPLY_TIME_DESC"
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
result = response.json()
print(f"Found {result.get('total_count', 0)} interested replies in last 7 days")
for msg in result.get('messages', []):
print(f"- {msg['lead']['email']}: {msg['email_status']}")
const API_KEY = 'YOUR_API_KEY';
// Example 2: Get opened but not replied emails from specific campaign
const payload = {
offset: 0,
limit: 20,
filters: {
emailStatus: ['Opened', 'Clicked'], // Engaged but not replied
campaignId: 12345,
leadCategories: {
unassigned: true // Not yet categorized
}
},
sortBy: 'SENT_TIME_DESC'
};
const response = await fetch(
`https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=${API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}
);
const result = await response.json();
console.log(`${result.total_count} engaged leads need follow-up`);
# Example 3: Multi-campaign performance comparison
payload = {
"filters": {
"campaignId": [12345, 12346, 12347], # Multiple campaigns
"emailStatus": ["Replied", "Opened", "Clicked"],
"campaignTeamMemberId": 456, # Specific team member
"campaignTagId": 5 # VIP tag
},
"limit": 20
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
# Group by campaign for comparison
results_by_campaign = {}
for msg in response.json().get('messages', []):
campaign_id = msg['campaign']['id']
if campaign_id not in results_by_campaign:
results_by_campaign[campaign_id] = []
results_by_campaign[campaign_id].append(msg)
for campaign_id, messages in results_by_campaign.items():
print(f"Campaign {campaign_id}: {len(messages)} engaged leads")
{
"messages": [
{
"id": "msg_abc123",
"campaign_lead_map_id": "2433664091",
"lead": {
"email": "john@company.com",
"first_name": "John",
"last_name": "Doe",
"company": "ACME Corp"
},
"campaign": {
"id": 12345,
"name": "Q1 2025 Outreach"
},
"email_account": {
"id": 789,
"email": "sales@yourcompany.com"
},
"last_message": {
"subject": "Partnership Opportunity",
"sent_at": "2025-01-15T10:00:00Z",
"opened_at": "2025-01-15T10:30:00Z",
"replied_at": "2025-01-15T14:00:00Z"
},
"email_status": "Replied",
"category": {
"id": 1,
"name": "Interested"
},
"assigned_to": {
"id": 456,
"name": "Jane Smith"
},
"stats": {
"opens": 2,
"clicks": 1,
"replies": 1
}
}
],
"total_count": 1,
"offset": 0,
"limit": 20
}
{
"message": "Invalid API Key"
}
{
"error": "limit must be between 1 and 20",
"field": "limit",
"provided_value": 50
}
Track all sent emails across your campaigns. Monitor delivery, opens, clicks, and replies. Essential for campaign performance tracking and follow-up management.
Overview
Retrieves all sent emails from your account with comprehensive filtering options. This endpoint provides a unified view of all outreach activity across campaigns. Key Features:- Unified view of all sent emails across campaigns
- Track email engagement (opens, clicks, replies)
- Filter by campaign, email account, team member, tags, clients
- Advanced lead category filtering
- Date range filtering for reply tracking
- Pagination and custom sorting
- Performance monitoring: Track which emails receive replies
- Follow-up management: Find emails that haven’t received responses
- Campaign analysis: Compare performance across campaigns
- Team reporting: Filter by team member to track individual activity
- Client reporting: Segment by client for account-specific insights
Query Parameters
string
required
Your SmartLead API key
Request Body
number
default:"0"
Number of records to skip for pagination. Must be non-negative.
number
default:"20"
Number of records to return per page. Must be between 1 and 20.
object
Advanced filtering options to segment your sent emails
Show filters properties
Show filters properties
string
Search term to filter emails. Searches across:
- Lead email addresses
- Lead names
- Email content Maximum 30 characters.
object
Filter by lead category assignment status and specific categories
Show leadCategories properties
Show leadCategories properties
boolean
Include leads without category assignment. Set to
true to include uncategorized leads.boolean
Include leads with category assignment. Set to
true to include categorized leads.array
Exclude specific category IDs. Array of numbers, maximum 10 items.
Example:
[3, 4] to exclude “Not Interested” and “Do Not Contact”array
Include only specific category IDs. Array of numbers, maximum 10 items.
Example:
[1, 2] to show only “Interested” and “Meeting Request”string or array
Filter by email engagement status. Can be a single status or array of statuses.Valid statuses:
Opened: Email was opened by recipientClicked: Recipient clicked a link in the emailReplied: Recipient sent a replyUnsubscribed: Recipient unsubscribedBounced: Email bounced (hard or soft)Accepted: Email was accepted by serverNot Replied: Email was opened but no reply received
- Single:
"Replied" - Multiple:
["Opened", "Clicked", "Replied"]
number or array
Filter by campaign ID(s). Can be a single campaign or array of campaigns.
- Single campaign:
12345 - Multiple campaigns:
[12345, 12346, 12347](max 15 campaigns)
number or array
Filter by email account ID(s). Can be a single account or array of accounts.
- Single account:
789 - Multiple accounts:
[789, 790, 791](no limit on array size)
number or array
Filter by team member assignment. Can be a single member or array of members.
- Single member:
456 - Multiple members:
[456, 457, 458](no limit on array size)
number or array
Filter by campaign tag. Can be a single tag or array of tags.
- Single tag:
5 - Multiple tags:
[5, 6, 7](no limit on array size)
number or array
Filter by client ID. Can be a single client or array of clients.
- Single client:
100 - Multiple clients:
[100, 101, 102](no limit on array size)
array
Filter by reply time date range. Array of 2 ISO 8601 datetime strings.Format:
["start_datetime", "end_datetime"]Example: ["2025-01-01T00:00:00Z", "2025-01-31T23:59:59Z"]string
default:"REPLY_TIME_DESC"
Sort order for results
REPLY_TIME_DESC: Most recent replies first (default, best for active conversations)SENT_TIME_DESC: Most recently sent emails first (best for tracking recent outreach)
curl -X POST "https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": ["Replied", "Opened"],
"campaignId": [12345, 12346],
"leadCategories": {
"categoryIdsIn": [1]
},
"replyTimeBetween": ["2025-01-01T00:00:00Z", "2025-01-31T23:59:59Z"]
},
"sortBy": "REPLY_TIME_DESC"
}'
import requests
from datetime import datetime, timedelta
API_KEY = "YOUR_API_KEY"
# Example 1: Get replied emails from last 7 days
seven_days_ago = (datetime.now() - timedelta(days=7)).isoformat() + 'Z'
now = datetime.now().isoformat() + 'Z'
payload = {
"offset": 0,
"limit": 20,
"filters": {
"emailStatus": "Replied",
"replyTimeBetween": [seven_days_ago, now],
"leadCategories": {
"categoryIdsIn": [1] # Interested leads only
}
},
"sortBy": "REPLY_TIME_DESC"
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
result = response.json()
print(f"Found {result.get('total_count', 0)} interested replies in last 7 days")
for msg in result.get('messages', []):
print(f"- {msg['lead']['email']}: {msg['email_status']}")
const API_KEY = 'YOUR_API_KEY';
// Example 2: Get opened but not replied emails from specific campaign
const payload = {
offset: 0,
limit: 20,
filters: {
emailStatus: ['Opened', 'Clicked'], // Engaged but not replied
campaignId: 12345,
leadCategories: {
unassigned: true // Not yet categorized
}
},
sortBy: 'SENT_TIME_DESC'
};
const response = await fetch(
`https://server.smartlead.ai/api/v1/master-inbox/sent?api_key=${API_KEY}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
}
);
const result = await response.json();
console.log(`${result.total_count} engaged leads need follow-up`);
# Example 3: Multi-campaign performance comparison
payload = {
"filters": {
"campaignId": [12345, 12346, 12347], # Multiple campaigns
"emailStatus": ["Replied", "Opened", "Clicked"],
"campaignTeamMemberId": 456, # Specific team member
"campaignTagId": 5 # VIP tag
},
"limit": 20
}
response = requests.post(
"https://server.smartlead.ai/api/v1/master-inbox/sent",
params={"api_key": API_KEY},
json=payload
)
# Group by campaign for comparison
results_by_campaign = {}
for msg in response.json().get('messages', []):
campaign_id = msg['campaign']['id']
if campaign_id not in results_by_campaign:
results_by_campaign[campaign_id] = []
results_by_campaign[campaign_id].append(msg)
for campaign_id, messages in results_by_campaign.items():
print(f"Campaign {campaign_id}: {len(messages)} engaged leads")
Response Codes
Success
Request successful - sent emails retrieved
Bad Request
Invalid request parameters or malformed request body
Unauthorized
Invalid or missing API key. Check your authentication.
Validation Error
Request validation failed. Common issues:
limit> 20- Invalid
emailStatusvalue - Array exceeds maximum length
- Invalid date format in
replyTimeBetween
Internal Server Error
Server error occurred. Please try again or contact support if the issue persists.
{
"messages": [
{
"id": "msg_abc123",
"campaign_lead_map_id": "2433664091",
"lead": {
"email": "john@company.com",
"first_name": "John",
"last_name": "Doe",
"company": "ACME Corp"
},
"campaign": {
"id": 12345,
"name": "Q1 2025 Outreach"
},
"email_account": {
"id": 789,
"email": "sales@yourcompany.com"
},
"last_message": {
"subject": "Partnership Opportunity",
"sent_at": "2025-01-15T10:00:00Z",
"opened_at": "2025-01-15T10:30:00Z",
"replied_at": "2025-01-15T14:00:00Z"
},
"email_status": "Replied",
"category": {
"id": 1,
"name": "Interested"
},
"assigned_to": {
"id": 456,
"name": "Jane Smith"
},
"stats": {
"opens": 2,
"clicks": 1,
"replies": 1
}
}
],
"total_count": 1,
"offset": 0,
"limit": 20
}
{
"message": "Invalid API Key"
}
{
"error": "limit must be between 1 and 20",
"field": "limit",
"provided_value": 50
}
Common Workflows
Daily Reply Check
# Get all replies received today
from datetime import datetime
today_start = datetime.now().replace(hour=0, minute=0, second=0).isoformat() + 'Z'
now = datetime.now().isoformat() + 'Z'
payload = {
"filters": {
"emailStatus": "Replied",
"replyTimeBetween": [today_start, now]
},
"sortBy": "REPLY_TIME_DESC"
}
Find Follow-up Opportunities
# Emails opened but not replied in last 3 days
three_days_ago = (datetime.now() - timedelta(days=3)).isoformat() + 'Z'
payload = {
"filters": {
"emailStatus": ["Opened", "Clicked"],
"replyTimeBetween": [three_days_ago, now],
"leadCategories": {
"unassigned": True # Not yet categorized
}
}
}
Campaign Performance Audit
# Get all campaign activity with engagement metrics
payload = {
"filters": {
"campaignId": [12345, 12346],
"emailStatus": ["Replied", "Opened", "Clicked"]
},
"limit": 20
}
response = get_sent_emails(payload)
# Calculate metrics
total = response['total_count']
replied = len([m for m in response['messages']
if m['email_status'] == 'Replied'])
reply_rate = (replied / total * 100) if total > 0 else 0
print(f"Reply rate: {reply_rate:.2f}%")
Team Member Activity
# Track individual team member performance
def get_member_sent_stats(member_id, start_date, end_date):
payload = {
"filters": {
"campaignTeamMemberId": member_id,
"replyTimeBetween": [start_date, end_date]
},
"limit": 20
}
response = get_sent_emails(payload)
messages = response.get('messages', [])
return {
'total_sent': len(messages),
'replied': len([m for m in messages if m['email_status'] == 'Replied']),
'opened': len([m for m in messages if m['email_status'] in ['Opened', 'Clicked']])
}
Filtering Best Practices
1. Start Broad, Then Narrow
# Step 1: Get all sent emails in campaign
basic_filter = {"campaignId": 12345}
# Step 2: Add engagement filter
engagement_filter = {
"campaignId": 12345,
"emailStatus": ["Replied", "Opened"]
}
# Step 3: Add category filter
interested_filter = {
"campaignId": 12345,
"emailStatus": ["Replied", "Opened"],
"leadCategories": {"categoryIdsIn": [1]}
}
2. Combine Inclusion and Exclusion
# Get engaged leads, excluding "Do Not Contact"
filters = {
"emailStatus": ["Replied", "Opened", "Clicked"],
"leadCategories": {
"categoryIdsNotIn": [4] # Exclude Do Not Contact
}
}
3. Use Date Ranges Effectively
# Rolling 30-day window
end_date = datetime.now()
start_date = end_date - timedelta(days=30)
filters = {
"replyTimeBetween": [
start_date.isoformat() + 'Z',
end_date.isoformat() + 'Z'
]
}
4. Paginate Large Results
def get_all_sent_emails(filters):
"""Fetch all results across multiple pages"""
all_messages = []
offset = 0
limit = 20
while True:
payload = {
"filters": filters,
"offset": offset,
"limit": limit
}
response = get_sent_emails(payload)
messages = response.get('messages', [])
if not messages:
break
all_messages.extend(messages)
offset += limit
# Stop if we've fetched all records
if offset >= response.get('total_count', 0):
break
return all_messages
Performance Optimization
- Use appropriate limits: Default of 20 balances speed and data volume
- Filter strategically: More specific filters = faster queries
- Avoid very large date ranges: Break into smaller chunks
- Cache results: Store frequently accessed data client-side
- Use specific campaign/account filters: Reduces query scope
Email Status Reference
| Status | Meaning | Follow-up Action |
|---|---|---|
Accepted | Email accepted by server | Wait for open/reply |
Opened | Recipient opened email | Consider follow-up |
Clicked | Clicked link in email | High engagement - prioritize |
Replied | Sent a response | Take action immediately |
Not Replied | Opened but no reply | Schedule follow-up |
Bounced | Email failed to deliver | Verify/remove address |
Unsubscribed | Opted out | Do not contact |
Related Endpoints
- Get Inbox Messages - All replies across campaigns
- Get Unread Replies - Unread responses
- Update Lead Category - Categorize leads
- Create Task - Create follow-up tasks
- Get Campaign Statistics - Aggregate metrics
⌘I
