Skip to content

Conversation

@yanchuk
Copy link
Contributor

@yanchuk yanchuk commented Dec 23, 2025

Motivation:

  • Add Stats API to gitbook

How to test:

  • Check how to test Gitbook OpenAPI changes guide

Summary by CodeRabbit

  • New Features
    • Added account-level statistics endpoints for aggregated sending metrics and views by domain, category, ESP, and date.
    • Added flexible filters for stats queries: start/end dates, specific sending domains, sending streams, categories, and ESPs.
    • Added standardized validation and rate-limit error responses for stats endpoints to improve feedback on malformed requests and throttling.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 23, 2025

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Adds a new "stats" area to the email API OpenAPI spec: five GET endpoints under /api/accounts/{account_id}/stats for aggregated sending statistics, new filtering query parameters, SendingStats/BadRequest/RateLimitExceeded schemas, and BAD_REQUEST/LIMIT_EXCEEDED response mappings.

Changes

Cohort / File(s) Summary
Stats feature & components
specs/email-api.openapi.yml
Adds stats tag and five GET endpoints: /api/accounts/{account_id}/stats, /.../stats/domains, /.../stats/categories, /.../stats/email_service_providers, /.../stats/date; introduces query parameters StartDateQueryFilter, EndDateQueryFilter, SendingDomainIDsQueryFilter, SendingStreamsQueryFilter, CategoriesQueryFilter, ESPsQueryFilter; adds schemas SendingStats, BadRequest, RateLimitExceededResponse; adds responses BAD_REQUEST, LIMIT_EXCEEDED and integrates standardized error responses into the new paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

"I hopped through specs with nimble paws,
Counting stats and query clause,
New endpoints bloom, a tidy trail,
Schemas snug beneath the mail,
A rabbit cheers — the API hums!" 🐇

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title mentions adding 'Public Stats API docs to Gitbook', but the actual changeset modifies an OpenAPI specification file (specs/email-api.openapi.yml) with new stats API endpoints and schemas, not Gitbook documentation files. Update the title to accurately reflect that this PR adds Stats API specifications to the OpenAPI spec file, e.g., 'Add Stats API endpoints and schemas to OpenAPI specification' or 'MT-20083 Add Public Stats API specifications to OpenAPI spec'.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36f97af and 8c44c4f.

📒 Files selected for processing (1)
  • specs/email-api.openapi.yml

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.

@yanchuk yanchuk requested a review from mklocek December 23, 2025 15:34
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: 2

🧹 Nitpick comments (2)
specs/email-api.openapi.yml (2)

1897-1913: Consider aligning error schema structure with existing ErrorResponse.

The new BadRequest and RateLimitExceededResponse schemas use errors as a single string, while the existing ErrorResponse schema (used by Unauthorized, Forbidden) uses errors as an array of strings. This inconsistency may confuse API consumers.

Option: Align with existing pattern
    BadRequest:
      title: BadRequestResponse
      type: object
      properties:
        errors:
-          type: string
-          description: Error message
-          example: Invalid request parameters
+          type: array
+          items:
+            type: string
+          description: Error messages
+          example:
+            - Invalid request parameters

1960-1972: Inconsistent response naming convention.

The new responses BAD_REQUEST and LIMIT_EXCEEDED use SCREAMING_SNAKE_CASE, while existing responses use PascalCase (Unauthorized, Forbidden, NotFound, UnprocessableEntity). Consider renaming for consistency.

Proposed fix
-    BAD_REQUEST:
+    BadRequest:
      description: Bad request - invalid parameters.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/BadRequest'

-    LIMIT_EXCEEDED:
+    RateLimitExceeded:
      description: Rate limit exceeded for the current account.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/RateLimitExceededResponse'

Then update the endpoint references accordingly:

        '400':
-          $ref: '#/components/responses/BAD_REQUEST'
+          $ref: '#/components/responses/BadRequest'
...
        '429':
-          $ref: '#/components/responses/LIMIT_EXCEEDED'
+          $ref: '#/components/responses/RateLimitExceeded'
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6e80754 and 749cf47.

📒 Files selected for processing (1)
  • specs/email-api.openapi.yml
🧰 Additional context used
📓 Path-based instructions (1)
specs/**/*.openapi.yml

📄 CodeRabbit inference engine (CLAUDE.md)

specs/**/*.openapi.yml: Base URLs must never be changed in OpenAPI specs. Use https://send.api.mailtrap.io for transactional emails, https://bulk.api.mailtrap.io for bulk emails, and https://mailtrap.io for all other APIs
All documentation links in OpenAPI specs must be absolute URLs pointing to docs.mailtrap.io, not relative links or help.mailtrap.io
Update contact URLs in spec info blocks to use https://docs.mailtrap.io, not help.mailtrap.io
Use GitBook markdown syntax in OpenAPI description fields, ensuring all blocks are properly closed: {% hint %}...{% endhint %} and {% tab %}...{% endtab %}
Tabs cannot be nested inside details blocks when using GitBook syntax in OpenAPI descriptions
Include code samples in x-codeSamples in this priority order: Node.js, PHP, Python, Ruby, .NET, Java, cURL
Use official Mailtrap SDKs for language-specific code samples in x-codeSamples, with Node.js (mailtrap/mailtrap-nodejs), PHP (railsware/mailtrap-php), Python (railsware/mailtrap-python), and Ruby (railsware/mailtrap-ruby)
Use environment variables for API keys in code samples (e.g., process.env.MAILTRAP_API_KEY)
Validate YAML syntax, OpenAPI 3.1 compliance, base URLs, contact URLs, GitBook blocks, links, and code samples before committing OpenAPI spec changes
Do not use emojis in specification content
Keep OpenAPI descriptions concise and developer-focused, with technical accuracy prioritized
Use custom OpenAPI extensions for GitBook navigation: x-page-title, x-page-icon, x-page-description, x-parent, x-codeSamples, and x-logo
Structure tags with x-page-title, x-page-description, and x-parent for GitBook nested navigation in OpenAPI specs
Use official product naming: 'Email API/SMTP' (can shorten to 'Email API' or 'API/SMTP'), 'Email Sandbox' (can shorten to 'Sandbox'), 'Email Marketing' (can shorten to 'Marketing')

Files:

  • specs/email-api.openapi.yml
🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: mailtrap/mailtrap-openapi PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-23T11:20:58.562Z
Learning: Applies to specs/**/*.openapi.yml : Update contact URLs in spec `info` blocks to use `https://docs.mailtrap.io`, not help.mailtrap.io
🔇 Additional comments (3)
specs/email-api.openapi.yml (3)

1442-1454: Verify if stats should be an array or single object.

The base /stats endpoint returns a single SendingStats object, but the grouped endpoints (by domains, categories, etc.) return stats as an array. If each group returns aggregated stats, a single object might be more appropriate. If it returns time-series data within each group, the array is correct.


1634-1726: LGTM!

The query filter parameters are well-defined with appropriate types, descriptions, and examples. Required date filters and optional grouping filters are a sensible design for a stats API.


1857-1896: LGTM!

The SendingStats schema is well-structured with clear property names, appropriate types (integer for counts, double for rates), and helpful examples.

Comment on lines 1391 to 1421
'/api/accounts/{account_id}/stats':
get:
operationId: getAccountSendingStats
summary: Get account sending stats
description: Get account sending stats. Use filters to get specific stats.
tags:
- stats
parameters:
- $ref: '#/components/parameters/account_id'
- $ref: '#/components/parameters/StartDateQueryFilter'
- $ref: '#/components/parameters/EndDateQueryFilter'
- $ref: '#/components/parameters/SendingDomainIDsQueryFilter'
- $ref: '#/components/parameters/SendingStreamsQueryFilter'
- $ref: '#/components/parameters/CategoriesQueryFilter'
- $ref: '#/components/parameters/ESPsQueryFilter'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/SendingStats'
'400':
$ref: '#/components/responses/BAD_REQUEST'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/LIMIT_EXCEEDED'
'/api/accounts/{account_id}/stats/domains':
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Missing x-codeSamples for stats endpoints.

Per coding guidelines, all endpoints should include code samples in priority order: Node.js, PHP, Python, Ruby, .NET, Java, cURL. The stats endpoints currently lack these samples, unlike other endpoints in this spec.

Consider adding code samples using the official Mailtrap SDKs (when supported) or cURL examples at minimum.

🤖 Prompt for AI Agents
In specs/email-api.openapi.yml around lines 1391 to 1421, the GET
/api/accounts/{account_id}/stats operation is missing the required x-codeSamples
section; add an x-codeSamples array under the operation (or under the 200
response) containing prioritized examples: Node.js, PHP, Python, Ruby, .NET,
Java, and cURL; each sample should include a short description, language, and a
runnable snippet showing authorization and the request to this endpoint (prefer
official Mailtrap SDK snippet when available, otherwise provide a concise cURL
example) so the stats endpoint matches the rest of the spec.

@yanchuk yanchuk requested a review from IgorDobryn December 23, 2025 15:51
@mklocek
Copy link

mklocek commented Dec 24, 2025

Btw. I also pushed small updates to Suppressions API in https://github.com/railsware/mailtrap-public-docs/pull/139. They are not QA'd and released yet though.

Copy link

@IgorDobryn IgorDobryn left a comment

Choose a reason for hiding this comment

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

Suggestion: ask chatGPT to format title in API style

@yanchuk yanchuk merged commit b131cc8 into main Dec 24, 2025
1 of 2 checks passed
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.

5 participants