> ## Documentation Index
> Fetch the complete documentation index at: https://api.smartlead.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Sent Emails

> Retrieve all sent emails across campaigns with comprehensive filtering and pagination

<Note>
  Track all sent emails across your campaigns. Monitor delivery, opens, clicks, and replies. Essential for campaign performance tracking and follow-up management.
</Note>

## 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

**Common Use Cases**:

* **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

<ParamField query="api_key" type="string" required>
  Your SmartLead API key
</ParamField>

## Request Body

<ParamField body="offset" type="number" default="0">
  Number of records to skip for pagination. Must be non-negative.
</ParamField>

<ParamField body="limit" type="number" default="20">
  Number of records to return per page. Must be between 1 and 20.
</ParamField>

<ParamField body="filters" type="object">
  Advanced filtering options to segment your sent emails

  <Expandable title="filters properties">
    <ParamField body="filters.search" type="string">
      Search term to filter emails. Searches across:

      * Lead email addresses
      * Lead names
      * Email content
        Maximum 30 characters.
    </ParamField>

    <ParamField body="filters.leadCategories" type="object">
      Filter by lead category assignment status and specific categories

      <Expandable title="leadCategories properties">
        <ParamField body="leadCategories.unassigned" type="boolean">
          Include leads without category assignment. Set to `true` to include uncategorized leads.
        </ParamField>

        <ParamField body="leadCategories.isAssigned" type="boolean">
          Include leads with category assignment. Set to `true` to include categorized leads.
        </ParamField>

        <ParamField body="leadCategories.categoryIdsNotIn" type="array">
          Exclude specific category IDs. Array of numbers, maximum 10 items.
          Example: `[3, 4]` to exclude "Not Interested" and "Do Not Contact"
        </ParamField>

        <ParamField body="leadCategories.categoryIdsIn" type="array">
          Include only specific category IDs. Array of numbers, maximum 10 items.
          Example: `[1, 2]` to show only "Interested" and "Meeting Request"
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField body="filters.emailStatus" type="string or array">
      Filter by email engagement status. Can be a single status or array of statuses.

      **Valid statuses**:

      * `Opened`: Email was opened by recipient
      * `Clicked`: Recipient clicked a link in the email
      * `Replied`: Recipient sent a reply
      * `Unsubscribed`: Recipient unsubscribed
      * `Bounced`: Email bounced (hard or soft)
      * `Accepted`: Email was accepted by server
      * `Not Replied`: Email was opened but no reply received

      **Examples**:

      * Single: `"Replied"`
      * Multiple: `["Opened", "Clicked", "Replied"]`
    </ParamField>

    <ParamField body="filters.campaignId" type="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)
    </ParamField>

    <ParamField body="filters.emailAccountId" type="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)
    </ParamField>

    <ParamField body="filters.campaignTeamMemberId" type="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)
    </ParamField>

    <ParamField body="filters.campaignTagId" type="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)
    </ParamField>

    <ParamField body="filters.campaignClientId" type="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)
    </ParamField>

    <ParamField body="filters.replyTimeBetween" type="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"]`
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="sortBy" type="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)
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  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"
    }'
  ```

  ```python Python theme={null}
  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']}")
  ```

  ```javascript JavaScript theme={null}
  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`);
  ```

  ```python Advanced Filtering Example theme={null}
  # 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")
  ```
</RequestExample>

## Response Codes

<ResponseField name="200" type="Success">
  Request successful - sent emails retrieved
</ResponseField>

<ResponseField name="400" type="Bad Request">
  Invalid request parameters or malformed request body
</ResponseField>

<ResponseField name="401" type="Unauthorized">
  Invalid or missing API key. Check your authentication.
</ResponseField>

<ResponseField name="422" type="Validation Error">
  Request validation failed. Common issues:

  * `limit` > 20
  * Invalid `emailStatus` value
  * Array exceeds maximum length
  * Invalid date format in `replyTimeBetween`
</ResponseField>

<ResponseField name="500" type="Internal Server Error">
  Server error occurred. Please try again or contact support if the issue persists.
</ResponseField>

<ResponseExample>
  ```json 200 - Success theme={null}
  {
    "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
  }
  ```

  ```json 401 - Unauthorized theme={null}
  {
    "message": "Invalid API Key"
  }
  ```

  ```json 422 - Validation Error theme={null}
  {
    "error": "limit must be between 1 and 20",
    "field": "limit",
    "provided_value": 50
  }
  ```
</ResponseExample>

## Common Workflows

### Daily Reply Check

```python theme={null}
# 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

```python theme={null}
# 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

```python theme={null}
# 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

```python theme={null}
# 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

```python theme={null}
# 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

```python theme={null}
# Get engaged leads, excluding "Do Not Contact"
filters = {
    "emailStatus": ["Replied", "Opened", "Clicked"],
    "leadCategories": {
        "categoryIdsNotIn": [4]  # Exclude Do Not Contact
    }
}
```

### 3. Use Date Ranges Effectively

```python theme={null}
# 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

```python theme={null}
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

1. **Use appropriate limits**: Default of 20 balances speed and data volume
2. **Filter strategically**: More specific filters = faster queries
3. **Avoid very large date ranges**: Break into smaller chunks
4. **Cache results**: Store frequently accessed data client-side
5. **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](/api-reference/inbox/get-messages) - All replies across campaigns
* [Get Unread Replies](/api-reference/inbox/get-unread) - Unread responses
* [Update Lead Category](/api-reference/inbox/update-category) - Categorize leads
* [Create Task](/api-reference/inbox/create-task) - Create follow-up tasks
* [Get Campaign Statistics](/api-reference/campaigns/statistics) - Aggregate metrics
