Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
261 changes: 259 additions & 2 deletions specs/email-sending.openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ info:
title: Email Sending
version: 2.0.0
description: |
Manage domains, suppressions, and email sending logs for your Mailtrap account.
Manage domains, suppressions, tracking opt-outs, and email sending logs for your Mailtrap account.
contact:
name: Mailtrap Support
url: 'https://docs.mailtrap.io'
Expand All @@ -16,7 +16,7 @@ info:

servers:
- description: |
Mailtrap account API (`mailtrap.io`) for domains, suppressions, stats, and email logs.
Mailtrap account API (`mailtrap.io`) for domains, suppressions, tracking opt-outs, stats, and email logs.
Error JSON matches other account endpoints (`error` or string `errors`), not the `send.api` / `bulk.api` sending shape (`success` + `errors` array).
url: 'https://mailtrap.io'

Expand All @@ -37,6 +37,12 @@ tags:
description: |
Control which email addresses should not receive emails from your account.

- name: tracking-opt-outs
x-page-title: Tracking Opt-Outs
x-page-description: Manage tracking opt-outs
description: |
Manage email addresses that have opted out of open and click tracking.

- name: stats
x-page-title: Stats
x-page-description: Email sending stats
Expand Down Expand Up @@ -571,6 +577,7 @@ paths:
"domain": {
"open_tracking_enabled": true,
"click_tracking_enabled": true,
"tracking_opt_out_enabled": true,
"auto_unsubscribe_link_enabled": false
}
}'
Expand All @@ -591,6 +598,7 @@ paths:
domain:
open_tracking_enabled: true
click_tracking_enabled: true
tracking_opt_out_enabled: true
auto_unsubscribe_link_enabled: false
responses:
'200':
Expand Down Expand Up @@ -1291,6 +1299,191 @@ paths:
'404':
$ref: '#/components/responses/NotFound'

/api/tracking_opt_outs:
get:
summary: List tracking opt-outs
description: |
List email addresses that have opted out of open and click tracking. Returns up to 1000 records per request. Use `last_id` for cursor-based pagination through large lists.

Rate limit: 10 requests per minute per account.
operationId: getTrackingOptOuts
tags:
- tracking-opt-outs
x-codeSamples:
- lang: shell
label: 'cURL'
source: |
# Get all tracking opt-outs
curl -X GET https://mailtrap.io/api/tracking_opt_outs \
-H 'Authorization: Bearer YOUR_API_KEY'

# Search for specific email
curl -X GET 'https://mailtrap.io/api/tracking_opt_outs?email=tracked@example.com' \
-H 'Authorization: Bearer YOUR_API_KEY'
- lang: javascript
label: Node.js
source: |
import { MailtrapClient } from "mailtrap";

const client = new MailtrapClient({
token: process.env.MAILTRAP_API_KEY,
accountId: YOUR_ACCOUNT_ID
});
Comment on lines +1328 to +1331

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This example do not use client, so if we want keep it - fetch is enough, but I think we should stick with curl only

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yep, if an SDK doesn't support it yet we just don't give an example here, not even that "does not yet support" comment, leaving only cURL.


async function getTrackingOptOuts() {
const response = await fetch(
"https://mailtrap.io/api/tracking_opt_outs",
{ headers: { Authorization: `Bearer ${process.env.MAILTRAP_API_KEY}` } }
);
const trackingOptOuts = await response.json();
console.log("Tracking opt-outs:", trackingOptOuts);
}

getTrackingOptOuts();
- lang: php
label: PHP
source: |
<?php
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: python
label: Python
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: ruby
label: Ruby
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: csharp
label: .NET
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: java
label: Java
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
Comment on lines +1323 to +1368

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace the Node.js fetch sample with an SDK-limitation note.

The JavaScript block is labeled as a Node.js x-codeSamples entry but does not use the Mailtrap SDK; it constructs a MailtrapClient and then falls back to raw fetch. That contradicts the stated “SDKs are deferred until support exists” approach and will mislead readers into assuming JS SDK support already exists.

Suggested change
         - lang: javascript
           label: Node.js
           source: |
-            import { MailtrapClient } from "mailtrap";
-
-            const client = new MailtrapClient({
-              token: process.env.MAILTRAP_API_KEY,
-              accountId: YOUR_ACCOUNT_ID
-            });
-
-            async function getTrackingOptOuts() {
-              const response = await fetch(
-                "https://mailtrap.io/api/tracking_opt_outs",
-                { headers: { Authorization: `Bearer ${process.env.MAILTRAP_API_KEY}` } }
-              );
-              const trackingOptOuts = await response.json();
-              console.log("Tracking opt-outs:", trackingOptOuts);
-            }
-
-            getTrackingOptOuts();
+            // Mailtrap SDK does not yet support tracking opt-outs.
+            // Use the cURL example above.

As per coding guidelines, "Use official Mailtrap SDKs for language-specific code examples in x-codeSamples; if SDK doesn't support a method, use GitBook generation or add a comment noting SDK limitations."

📝 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
- lang: javascript
label: Node.js
source: |
import { MailtrapClient } from "mailtrap";
const client = new MailtrapClient({
token: process.env.MAILTRAP_API_KEY,
accountId: YOUR_ACCOUNT_ID
});
async function getTrackingOptOuts() {
const response = await fetch(
"https://mailtrap.io/api/tracking_opt_outs",
{ headers: { Authorization: `Bearer ${process.env.MAILTRAP_API_KEY}` } }
);
const trackingOptOuts = await response.json();
console.log("Tracking opt-outs:", trackingOptOuts);
}
getTrackingOptOuts();
- lang: php
label: PHP
source: |
<?php
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: python
label: Python
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: ruby
label: Ruby
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: csharp
label: .NET
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: java
label: Java
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: javascript
label: Node.js
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: php
label: PHP
source: |
<?php
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: python
label: Python
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: ruby
label: Ruby
source: |
# Mailtrap SDK does not yet support tracking opt-outs.
# Use the cURL example above.
- lang: csharp
label: .NET
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
- lang: java
label: Java
source: |
// Mailtrap SDK does not yet support tracking opt-outs.
// Use the cURL example above.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/email-sending.openapi.yml` around lines 1323 - 1368, The Node.js
x-codeSamples entry for tracking opt-outs mixes a MailtrapClient instantiation
with a raw fetch call, which is misleading because it implies SDK support that
does not exist. Update the JavaScript sample to match the other language blocks
by replacing the example in the tracking opt-outs section with an SDK-limitation
note, and remove the MailtrapClient/getTrackingOptOuts sample so readers are
directed to the cURL example until the SDK supports this endpoint.

Source: Coding guidelines

Comment on lines +1343 to +1368

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should we list those at all if we do not implement it? For other endpoints we just leave cURL (example: https://docs.mailtrap.io/developers/email-sending/email-logs)

parameters:
- name: email
in: query
description: Filter tracking opt-outs by exact email address (case-insensitive).
schema:
type: string
format: email
example: tracked@example.com
- name: start_time
in: query
description: Filter tracking opt-outs created at or after this timestamp (ISO 8601 format).
schema:
type: string
format: date-time
example: '2025-01-01T00:00:00Z'
- name: end_time
in: query
description: Filter tracking opt-outs created at or before this timestamp (ISO 8601 format).
schema:
type: string
format: date-time
example: '2025-12-31T23:59:59Z'
- name: last_id
in: query
description: The tracking opt-out UUID from the last record of the previous response. Returns records after this opt-out, enabling cursor-based pagination through large lists.
schema:
type: string
format: uuid
example: 64d71bf3-1276-417b-86e1-8e66f138acfe
responses:
'200':
$ref: '#/components/responses/GetTrackingOptOutsResponse'
'400':
$ref: '#/components/responses/BAD_REQUEST'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'429':
$ref: '#/components/responses/LIMIT_EXCEEDED'
post:
summary: Create tracking opt-out
description: |
Add an email address to the tracking opt-out list. Opted-out addresses are excluded from open and click tracking.

{% hint style="warning" %}
This endpoint requires admin-level access.
{% endhint %}

Rate limit: 10 requests per minute per account.
operationId: createTrackingOptOut
tags:
- tracking-opt-outs
x-codeSamples:
- lang: shell
label: 'cURL'
source: |
curl -X POST https://mailtrap.io/api/tracking_opt_outs \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"email": "tracked@example.com"
}'
Comment on lines +1422 to +1431

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add the missing language sample slots for create/delete tracking opt-outs.

Line 1422 and Line 1469 only provide cURL. For spec files in this repo, x-codeSamples should still keep the standard language order, and unsupported SDK entries should be present with an explicit limitation note. Right now the POST/DELETE docs will lose the usual tabs and won’t communicate why the SDK samples are missing.

Based on learnings, populate x-codeSamples in the exact priority order with cURL first, then Node.js, PHP, Python, Ruby, .NET, and Java, using the same “SDK does not yet support tracking opt-outs” note you already added elsewhere.

Also applies to: 1469-1474

🧰 Tools
🪛 Betterleaks (1.5.0)

[high] 1426-1427: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.

(curl-auth-header)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@specs/email-sending.openapi.yml` around lines 1422 - 1431, The create/delete
tracking opt-outs docs only include cURL, so the standard code sample tabs are
missing for these operations. Update the x-codeSamples blocks in the
tracking_opt_outs POST/DELETE sections to follow the repo’s usual priority
order: cURL, Node.js, PHP, Python, Ruby, .NET, and Java, and include the same
explicit “SDK does not yet support tracking opt-outs” limitation note for the
unsupported SDK entries. Use the existing tracking opt-outs sample patterns in
this spec to keep the language ordering and messaging consistent.

Sources: Coding guidelines, Learnings

requestBody:
required: true
content:
application/json:
schema:
type: object
required: [email]
properties:
email:
type: string
format: email
description: Email address to opt out of tracking
example: tracked@example.com
responses:
'201':
$ref: '#/components/responses/CreateTrackingOptOutResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/LIMIT_EXCEEDED'

/api/tracking_opt_outs/{tracking_opt_out_id}:
delete:
summary: Delete tracking opt-out
description: |
Remove an email address from the tracking opt-out list so open and click tracking can apply again.

{% hint style="warning" %}
This endpoint requires admin-level access.
{% endhint %}
operationId: deleteTrackingOptOut
tags:
- tracking-opt-outs
x-codeSamples:
- lang: shell
label: 'cURL'
source: |
curl -X DELETE https://mailtrap.io/api/tracking_opt_outs/{tracking_opt_out_id} \
-H 'Authorization: Bearer YOUR_API_KEY'
parameters:
- $ref: '#/components/parameters/tracking_opt_out_id'
responses:
'200':
$ref: '#/components/responses/DeleteTrackingOptOutResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'

'/api/stats':
get:
operationId: getAccountSendingStats
Expand Down Expand Up @@ -2034,6 +2227,16 @@ components:
format: uuid
example: 64d71bf3-1276-417b-86e1-8e66f138acfe

tracking_opt_out_id:
name: tracking_opt_out_id
in: path
required: true
description: The tracking opt-out UUID
schema:
type: string
format: uuid
example: 64d71bf3-1276-417b-86e1-8e66f138acfe

sending_message_id:
name: sending_message_id
in: path
Expand Down Expand Up @@ -2219,6 +2422,11 @@ components:
type: boolean
click_tracking_enabled:
type: boolean
tracking_opt_out_enabled:
type: boolean
description: |
When enabled, recipients can opt out of open and click tracking via a link in tracked emails.
Requires open or click tracking to be enabled.
auto_unsubscribe_link_enabled:
type: boolean
custom_domain_tracking_enabled:
Expand Down Expand Up @@ -2286,6 +2494,7 @@ components:
name: mt-link
open_tracking_enabled: true
click_tracking_enabled: true
tracking_opt_out_enabled: false
auto_unsubscribe_link_enabled: true
custom_domain_tracking_enabled: true
health_alerts_enabled: true
Expand All @@ -2305,6 +2514,11 @@ components:
click_tracking_enabled:
type: boolean
description: Enable click tracking for links in emails sent from this domain
tracking_opt_out_enabled:
type: boolean
description: |
Enable the tracking opt-out link in tracked emails sent from this domain.
Requires open or click tracking to be enabled.
auto_unsubscribe_link_enabled:
type: boolean
description: Automatically add an unsubscribe link to emails sent from this domain
Expand Down Expand Up @@ -2537,6 +2751,23 @@ components:
message_subject:
type: [string, 'null']

TrackingOptOut:
type: object
properties:
id:
type: string
format: uuid
description: The tracking opt-out UUID
example: 64d71bf3-1276-417b-86e1-8e66f138acfe
email:
type: string
format: email
example: tracked@example.com
created_at:
type: string
format: date-time
example: '2025-01-15T10:30:00Z'

Webhook:
type: object
properties:
Expand Down Expand Up @@ -3605,3 +3836,29 @@ components:
properties:
data:
$ref: '#/components/schemas/Suppression'

GetTrackingOptOutsResponse:
description: List of tracking opt-outs
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/TrackingOptOut'

DeleteTrackingOptOutResponse:
description: Tracking opt-out deleted
content:
application/json:
schema:
$ref: '#/components/schemas/TrackingOptOut'

CreateTrackingOptOutResponse:
description: Tracking opt-out created
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/TrackingOptOut'
Loading