Skip to content

Add Stats API#62

Open
piobeny wants to merge 3 commits intomainfrom
stats-api
Open

Add Stats API#62
piobeny wants to merge 3 commits intomainfrom
stats-api

Conversation

@piobeny
Copy link

@piobeny piobeny commented Mar 6, 2026

Motivation

  • Add support for the Email Sending Stats API (/api/accounts/{account_id}/stats) to the Python SDK, enabling users to retrieve aggregated email sending statistics.

Changes

  • Add SendingStats and SendingStatGroup pydantic dataclasses with delivery, bounce, open, click, and spam counts/rates
  • Add StatsFilterParams dataclass extending RequestParams for filter handling
  • Add StatsApi class with 5 methods: get, by_domains, by_categories, by_email_service_providers, by_date
  • Add api_query_params to RequestParams for automatic [] serialization of list query params
  • Add usage example in examples/general/stats.py
  • Update README with Stats API reference
  • Update CHANGELOG with entry for v2.5.0

How to test

  • stats_api.get(account_id, params) with different parameters (start_date, end_date, sending_domain_ids, sending_streams, categories, email_service_providers)
  • Test grouped endpoints (by_domains, by_categories, by_email_service_providers, by_date) with filters

Examples

import mailtrap as mt                                                                                                                                                                              
from mailtrap.models.stats import StatsFilterParams                                                                                                                                                
                                                                                                                                                                                                   
client = mt.MailtrapClient(token="api_key")                                                                                                                                                        
stats_api = client.general_api.stats                                                                                                                                                               
                                                                                                                                                                                                   
# Get aggregated stats with optional filters                                                                                                                                                       
params = StatsFilterParams(                                                                                                                                                                        
    start_date="2026-01-01",                                                                                                                                                                       
    end_date="2026-01-31",                                                                                                                                                                         
    categories=["Welcome email"],                                                                                                                                                                  
)                                                                                                                                                                                                  
result = stats_api.get(account_id=account_id, params=params)

Summary by CodeRabbit

Release Notes v2.5.0

  • New Features

    • Introduced Statistics API for retrieving and analyzing sending statistics with flexible filtering options.
  • Documentation

    • Updated API documentation URL reference.
    • Added new example code demonstrating statistics retrieval patterns.

piobeny and others added 2 commits March 4, 2026 12:57
…roviders, by_date endpoints

Also adds api_query_params to RequestParams for automatic [] serialization of list query params.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 6, 2026

Warning

Rate limit exceeded

@piobeny has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 3 minutes and 0 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 242e3d63-7668-4110-b9fd-55b160de28c4

📥 Commits

Reviewing files that changed from the base of the PR and between d5c86be and a8a254b.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • mailtrap/api/resources/stats.py
  • mailtrap/models/stats.py
  • pyproject.toml
  • tests/unit/api/general/test_stats.py
📝 Walkthrough

Walkthrough

A feature release introducing comprehensive statistics API support to the Mailtrap SDK. Adds StatsApi with methods to retrieve sending statistics aggregated or grouped by domains, categories, email service providers, and dates, along with supporting data models, package exports, and example usage.

Changes

Cohort / File(s) Summary
Stats API Core
mailtrap/api/resources/stats.py, mailtrap/models/stats.py
Introduces StatsApi class with methods to fetch aggregated and grouped statistics (by domains, categories, email service providers, date). Defines SendingStats, SendingStatGroup, and StatsFilterParams dataclasses for structured response modeling.
API Integration & Exports
mailtrap/api/general.py, mailtrap/__init__.py, mailtrap/models/common.py
Integrates StatsApi into GeneralApi via new stats property. Exports StatsFilterParams at package level. Adds api_query_params property to RequestParams for query parameter serialization with list-type handling.
Documentation & Examples
CHANGELOG.md, examples/general/stats.py, pyproject.toml
Updates changelog with 2.5.0 release notes. Adds comprehensive example file demonstrating stats API usage across multiple retrieval patterns. Bumps version to 2.5.0 and updates documentation URL.
Test Coverage
tests/unit/api/general/test_stats.py
Comprehensive unit tests validating StatsApi functionality including error handling, parameter filtering, and all grouping methods (domains, categories, email service providers, date).

Sequence Diagram

sequenceDiagram
    participant Client as Client Code
    participant GeneralApi as GeneralApi
    participant StatsApi as StatsApi
    participant HttpClient as HttpClient
    participant Server as Server
    participant Parser as Response Parser

    Client->>GeneralApi: call .stats
    GeneralApi->>StatsApi: instantiate with HttpClient
    
    Client->>StatsApi: call get/by_domains/by_categories/etc.<br/>(account_id, StatsFilterParams)
    StatsApi->>StatsApi: build request path & query params
    StatsApi->>HttpClient: GET /api/accounts/{id}/stats[/{group}]<br/>with filters
    HttpClient->>Server: HTTP GET request
    Server-->>HttpClient: JSON response (stats data)
    HttpClient-->>StatsApi: response dict
    StatsApi->>Parser: construct SendingStats/<br/>SendingStatGroup instances
    Parser-->>StatsApi: typed objects
    StatsApi-->>Client: SendingStats or list[SendingStatGroup]
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Suggested reviewers

  • IgorDobryn
  • andrii-porokhnavets
  • yanchuk

Poem

🐰 Hop, hop, statistics now flow,
Stats by domains, dates in a row,
Grouped and filtered with graceful API,
Two point five hops, we celebrate today!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add Stats API' clearly and concisely summarizes the main change—introducing a new Stats API feature to the SDK.
Description check ✅ Passed The description includes Motivation and Changes sections as required by the template. While it omits the optional 'Images and GIFs' section, it provides comprehensive details including examples and testing guidance.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch stats-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
examples/general/stats.py (1)

1-4: Consider consolidating imports.

The three imports from mailtrap.models.stats can be combined into a single line for brevity.

Proposed fix
 import mailtrap as mt
-from mailtrap.models.stats import SendingStatGroup
-from mailtrap.models.stats import SendingStats
-from mailtrap.models.stats import StatsFilterParams
+from mailtrap.models.stats import SendingStatGroup, SendingStats, StatsFilterParams
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/general/stats.py` around lines 1 - 4, Consolidate the three separate
imports from mailtrap.models.stats into a single statement: replace the three
lines importing SendingStatGroup, SendingStats, and StatsFilterParams with one
combined import that lists those symbols together (keep the existing import
mailtrap as mt intact); ensure the combined import includes SendingStatGroup,
SendingStats, and StatsFilterParams exactly as named.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@examples/general/stats.py`:
- Around line 6-7: The example defines ACCOUNT_ID as a string while helper
functions expect account_id: int; update the example to provide an integer
ACCOUNT_ID (replace "YOUR_ACCOUNT_ID" with a numeric literal) or explicitly
cast/convert it before passing to functions so the value matches the account_id:
int signatures (look for the ACCOUNT_ID constant and any functions/methods that
declare account_id: int).

In `@mailtrap/api/resources/stats.py`:
- Around line 18-39: Reformat the oversized function signatures and long calls
in this file to satisfy Black/E501: wrap long parameter lists and chained calls
for the methods get, by_domains, by_categories, by_email_service_providers, and
by_date so no line exceeds the max width; specifically break the signature and
the return/_grouped_stats call lines that pass StatsFilterParams (e.g., the
by_email_service_providers(...) -> return self._grouped_stats(...)) across
multiple lines consistent with Black's style, then run Black on
mailtrap/api/resources/stats.py to ensure CI passes.

In `@mailtrap/models/stats.py`:
- Around line 31-33: The StatsFilterParams class uses empty-string defaults for
start_date/end_date causing RequestParams.api_data(..., exclude_none=True) to
still serialize them; change both fields in StatsFilterParams to use
Optional[str] with default None (and add the typing import if missing) so when
unset they are omitted from api_data serialization; update any related
validation or consumers that expect empty strings to handle None instead.

In `@tests/unit/api/general/test_stats.py`:
- Line 146: The test function signature for test_get_with_filter_params is too
long and must be wrapped to satisfy line-length rules; edit the def
test_get_with_filter_params(self, client: StatsApi, sample_stats_dict: dict) ->
None: signature to break parameters across multiple lines (e.g., place each
parameter on its own line or use a hanging indent inside the def parentheses) so
the line length is under the configured limit, then re-run/commit Black (or run
the project's formatter) to ensure the file passes CI formatting checks.

---

Nitpick comments:
In `@examples/general/stats.py`:
- Around line 1-4: Consolidate the three separate imports from
mailtrap.models.stats into a single statement: replace the three lines importing
SendingStatGroup, SendingStats, and StatsFilterParams with one combined import
that lists those symbols together (keep the existing import mailtrap as mt
intact); ensure the combined import includes SendingStatGroup, SendingStats, and
StatsFilterParams exactly as named.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: c0ad3c1f-6b85-4473-a950-b27b381aec46

📥 Commits

Reviewing files that changed from the base of the PR and between 8821498 and d5c86be.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • examples/general/stats.py
  • mailtrap/__init__.py
  • mailtrap/api/general.py
  • mailtrap/api/resources/stats.py
  • mailtrap/models/common.py
  • mailtrap/models/stats.py
  • pyproject.toml
  • tests/unit/api/general/test_stats.py

Comment on lines +6 to +7
API_TOKEN = "YOUR_API_TOKEN"
ACCOUNT_ID = "YOUR_ACCOUNT_ID"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Type mismatch between ACCOUNT_ID and function signatures.

ACCOUNT_ID is defined as a string, but all helper functions declare account_id: int. Users copying this example may inadvertently pass a string when an integer is expected.

Proposed fix
 API_TOKEN = "YOUR_API_TOKEN"
-ACCOUNT_ID = "YOUR_ACCOUNT_ID"
+ACCOUNT_ID = 123456  # Replace with your actual account ID
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
API_TOKEN = "YOUR_API_TOKEN"
ACCOUNT_ID = "YOUR_ACCOUNT_ID"
API_TOKEN = "YOUR_API_TOKEN"
ACCOUNT_ID = 123456 # Replace with your actual account ID
🧰 Tools
🪛 Ruff (0.15.4)

[error] 6-6: Possible hardcoded password assigned to: "API_TOKEN"

(S105)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@examples/general/stats.py` around lines 6 - 7, The example defines ACCOUNT_ID
as a string while helper functions expect account_id: int; update the example to
provide an integer ACCOUNT_ID (replace "YOUR_ACCOUNT_ID" with a numeric literal)
or explicitly cast/convert it before passing to functions so the value matches
the account_id: int signatures (look for the ACCOUNT_ID constant and any
functions/methods that declare account_id: int).

@piobeny piobeny force-pushed the stats-api branch 2 times, most recently from eef007b to 5bbca85 Compare March 6, 2026 11:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant