From 098ffcdad7fa35e28ab4e2a33032935fff169086 Mon Sep 17 00:00:00 2001 From: dielduarte Date: Fri, 17 Jul 2026 17:43:50 -0300 Subject: [PATCH 1/2] docs: add account metrics endpoint --- resend.yaml | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) diff --git a/resend.yaml b/resend.yaml index 1b75d78..4373b8f 100644 --- a/resend.yaml +++ b/resend.yaml @@ -44,6 +44,8 @@ tags: description: Create and manage Events through the Resend API. - name: OAuth description: List and manage OAuth grants through the Resend API. + - name: Metrics + description: Retrieve account-level email metrics through the Resend API. paths: /emails: post: @@ -2055,6 +2057,90 @@ paths: application/json: schema: $ref: '#/components/schemas/RemoveSuppressionResponseSuccess' + /metrics: + get: + tags: + - Metrics + summary: Retrieve account-level email metrics + description: >- + Aggregate email metrics for a date range, returned in two blocks: + `overview` (volume and delivery counts) and `engagement` (unique + opens/clicks with rates). Per-period `timeseries` and per-domain + `domain_breakdown` are opt-in via `include`. + parameters: + - name: start_date + in: query + required: true + schema: + type: string + format: date-time + description: >- + Start of the range (ISO 8601). Must be on or before end_date and + within your plan's retention window. + - name: end_date + in: query + required: true + schema: + type: string + format: date-time + description: End of the range (ISO 8601). + - name: timezone + in: query + required: false + schema: + type: string + default: UTC + description: IANA timezone used to bucket the time series. Defaults to UTC. + - name: domain_id + in: query + required: false + schema: + type: string + format: uuid + description: Restrict all metrics to a single domain. + - name: event_type + in: query + required: false + description: >- + Project the overview block down to only the listed events. Repeat the + parameter to select multiple (e.g. + event_type=delivered&event_type=bounced). Does not affect engagement. + schema: + type: array + items: + type: string + enum: + - received + - delivered + - bounced + - complained + - opened + - clicked + - delivery_delayed + - failed + - unsubscribed + - suppressed + - name: include + in: query + required: false + description: >- + Add breakdowns to both blocks. Repeat the parameter to select + multiple (e.g. include=timeseries&include=domain_breakdown). Defaults + to totals only. + schema: + type: array + items: + type: string + enum: + - timeseries + - domain_breakdown + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GetMetricsResponseSuccess' webhooks: email.sent: post: @@ -6489,3 +6575,172 @@ components: format: date-time description: Timestamp indicating when the suppression was created. example: "2023-10-06T23:47:56.678Z" + MetricCounts: + type: object + description: >- + Volume and delivery counts. When `event_type` is set, only the requested + event keys are present. + properties: + sent: + type: integer + description: Derived count (delivered + bounced + failed). + example: 12053 + delivered: + type: integer + example: 11800 + delivery_delayed: + type: integer + example: 40 + bounced: + type: integer + example: 210 + complained: + type: integer + example: 5 + opened: + type: integer + description: Total opens. See engagement.opens for unique opens. + example: 5400 + clicked: + type: integer + description: Total clicks. See engagement.clicks for unique clicks. + example: 1200 + unsubscribed: + type: integer + example: 30 + suppressed: + type: integer + example: 900 + received: + type: integer + example: 8300 + failed: + type: integer + example: 43 + MetricsTimeseriesPoint: + allOf: + - type: object + properties: + period: + type: string + description: ISO date (daily buckets) or datetime (hourly buckets). + example: '2026-07-08' + - $ref: '#/components/schemas/MetricCounts' + MetricsDomainBreakdown: + allOf: + - type: object + properties: + domain_id: + type: string + format: uuid + example: 067b3160-d611-491e-943e-c0c4cd497d2d + domain_name: + type: string + example: mail.acme.com + - $ref: '#/components/schemas/MetricCounts' + MetricsOverview: + allOf: + - $ref: '#/components/schemas/MetricCounts' + - type: object + properties: + timeseries: + type: array + description: Per-period counts. Included only when `include=timeseries`. + items: + $ref: '#/components/schemas/MetricsTimeseriesPoint' + domain_breakdown: + type: array + description: Per-domain counts. Included only when `include=domain_breakdown`. + items: + $ref: '#/components/schemas/MetricsDomainBreakdown' + EngagementMetric: + type: object + description: >- + A unique count over its tracking-eligible delivered denominator, with the + derived rate. + properties: + unique: + type: integer + description: Unique recipients (deduplicated). + example: 5400 + delivered: + type: integer + description: >- + Deliveries to tracking-enabled domains — the rate denominator. Not the + same as overview.delivered. + example: 11800 + rate: + type: number + description: >- + unique / delivered as a percentage, capped at 100. 0 when nothing was + trackable. + example: 45.76 + EngagementTimeseriesPoint: + type: object + properties: + period: + type: string + example: '2026-07-08' + opens: + $ref: '#/components/schemas/EngagementMetric' + clicks: + $ref: '#/components/schemas/EngagementMetric' + EngagementDomainBreakdown: + type: object + properties: + domain_id: + type: string + format: uuid + example: 067b3160-d611-491e-943e-c0c4cd497d2d + domain_name: + type: string + example: mail.acme.com + opens: + $ref: '#/components/schemas/EngagementMetric' + clicks: + $ref: '#/components/schemas/EngagementMetric' + MetricsEngagement: + type: object + description: >- + Unique open/click engagement with rates. Not affected by the event_type + filter. + properties: + open_tracking_enabled: + type: boolean + example: true + click_tracking_enabled: + type: boolean + example: true + opens: + $ref: '#/components/schemas/EngagementMetric' + clicks: + $ref: '#/components/schemas/EngagementMetric' + timeseries: + type: array + description: Per-period engagement. Included only when `include=timeseries`. + items: + $ref: '#/components/schemas/EngagementTimeseriesPoint' + domain_breakdown: + type: array + description: Per-domain engagement. Included only when `include=domain_breakdown`. + items: + $ref: '#/components/schemas/EngagementDomainBreakdown' + GetMetricsResponseSuccess: + type: object + properties: + object: + type: string + const: metrics + description: The response object type. + start_date: + type: string + format: date-time + example: '2026-06-17T23:59:59.000Z' + end_date: + type: string + format: date-time + example: '2026-07-17T23:59:59.000Z' + overview: + $ref: '#/components/schemas/MetricsOverview' + engagement: + $ref: '#/components/schemas/MetricsEngagement' From 8c408e9e3237b11961bc7ddd581ffb46272ad262 Mon Sep 17 00:00:00 2001 From: dielduarte Date: Fri, 17 Jul 2026 18:09:04 -0300 Subject: [PATCH 2/2] docs: split account metrics into overview and engagement endpoints --- resend.yaml | 135 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 103 insertions(+), 32 deletions(-) diff --git a/resend.yaml b/resend.yaml index 4373b8f..8d4bda2 100644 --- a/resend.yaml +++ b/resend.yaml @@ -2057,16 +2057,14 @@ paths: application/json: schema: $ref: '#/components/schemas/RemoveSuppressionResponseSuccess' - /metrics: + /metrics/overview: get: tags: - Metrics - summary: Retrieve account-level email metrics + summary: Retrieve account-level delivery metrics description: >- - Aggregate email metrics for a date range, returned in two blocks: - `overview` (volume and delivery counts) and `engagement` (unique - opens/clicks with rates). Per-period `timeseries` and per-domain - `domain_breakdown` are opt-in via `include`. + Volume and delivery counts for a date range. Per-period `timeseries` and + per-domain `domain_breakdown` are opt-in via `include`. parameters: - name: start_date in: query @@ -2097,14 +2095,14 @@ paths: schema: type: string format: uuid - description: Restrict all metrics to a single domain. + description: Restrict metrics to a single domain. - name: event_type in: query required: false description: >- - Project the overview block down to only the listed events. Repeat the + Project the counts down to only the listed events. Repeat the parameter to select multiple (e.g. - event_type=delivered&event_type=bounced). Does not affect engagement. + event_type=delivered&event_type=bounced). schema: type: array items: @@ -2124,9 +2122,8 @@ paths: in: query required: false description: >- - Add breakdowns to both blocks. Repeat the parameter to select - multiple (e.g. include=timeseries&include=domain_breakdown). Defaults - to totals only. + Add breakdowns. Repeat the parameter to select multiple (e.g. + include=timeseries&include=domain_breakdown). Defaults to totals only. schema: type: array items: @@ -2140,7 +2137,66 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/GetMetricsResponseSuccess' + $ref: '#/components/schemas/GetMetricsOverviewResponseSuccess' + /metrics/engagement: + get: + tags: + - Metrics + summary: Retrieve account-level engagement metrics + description: >- + Unique open/click engagement with rates for a date range. Per-period + `timeseries` and per-domain `domain_breakdown` are opt-in via `include`. + parameters: + - name: start_date + in: query + required: true + schema: + type: string + format: date-time + description: >- + Start of the range (ISO 8601). Must be on or before end_date and + within your plan's retention window. + - name: end_date + in: query + required: true + schema: + type: string + format: date-time + description: End of the range (ISO 8601). + - name: timezone + in: query + required: false + schema: + type: string + default: UTC + description: IANA timezone used to bucket the time series. Defaults to UTC. + - name: domain_id + in: query + required: false + schema: + type: string + format: uuid + description: Restrict metrics to a single domain. + - name: include + in: query + required: false + description: >- + Add breakdowns. Repeat the parameter to select multiple (e.g. + include=timeseries&include=domain_breakdown). Defaults to totals only. + schema: + type: array + items: + type: string + enum: + - timeseries + - domain_breakdown + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/GetMetricsEngagementResponseSuccess' webhooks: email.sent: post: @@ -6725,22 +6781,37 @@ components: description: Per-domain engagement. Included only when `include=domain_breakdown`. items: $ref: '#/components/schemas/EngagementDomainBreakdown' - GetMetricsResponseSuccess: - type: object - properties: - object: - type: string - const: metrics - description: The response object type. - start_date: - type: string - format: date-time - example: '2026-06-17T23:59:59.000Z' - end_date: - type: string - format: date-time - example: '2026-07-17T23:59:59.000Z' - overview: - $ref: '#/components/schemas/MetricsOverview' - engagement: - $ref: '#/components/schemas/MetricsEngagement' + GetMetricsOverviewResponseSuccess: + allOf: + - type: object + properties: + object: + type: string + const: metrics_overview + description: The response object type. + start_date: + type: string + format: date-time + example: '2026-06-17T23:59:59.000Z' + end_date: + type: string + format: date-time + example: '2026-07-17T23:59:59.000Z' + - $ref: '#/components/schemas/MetricsOverview' + GetMetricsEngagementResponseSuccess: + allOf: + - type: object + properties: + object: + type: string + const: metrics_engagement + description: The response object type. + start_date: + type: string + format: date-time + example: '2026-06-17T23:59:59.000Z' + end_date: + type: string + format: date-time + example: '2026-07-17T23:59:59.000Z' + - $ref: '#/components/schemas/MetricsEngagement'