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
Your SmartLead API key
Request Body
Number of records to skip for pagination. Must be non-negative.
Number of records to return per page. Must be between 1 and 20.
Advanced filtering options to segment your sent emails
Show filters properties
Show filters properties
Search term to filter emails. Searches across:
- Lead email addresses
- Lead names
- Email content Maximum 30 characters.
Filter by lead category assignment status and specific categories
Show leadCategories properties
Show leadCategories properties
Include leads without category assignment. Set to
true to include uncategorized leads.Include leads with category assignment. Set to
true to include categorized leads.Exclude specific category IDs. Array of numbers, maximum 10 items.
Example:
[3, 4] to exclude “Not Interested” and “Do Not Contact”Include only specific category IDs. Array of numbers, maximum 10 items.
Example:
[1, 2] to show only “Interested” and “Meeting Request”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"]
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)
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)
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)
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)
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)
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"]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
Request successful - sent emails retrieved
Invalid request parameters or malformed request body
Invalid or missing API key. Check your authentication.
Request validation failed. Common issues:
limit> 20- Invalid
emailStatusvalue - Array exceeds maximum length
- Invalid date format in
replyTimeBetween
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
