curl --request GET \
--url https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries \
--header 'Authorization: <authorization>'const options = {method: 'GET', headers: {Authorization: '<authorization>'}};
fetch('https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries"
headers = {"Authorization": "<authorization>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.get("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries")
.header("Authorization", "<authorization>")
.asString();using RestSharp;
var options = new RestClientOptions("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("Authorization", "<authorization>");
var response = await client.GetAsync(request);
Console.WriteLine("{0}", response.Content);
false{
"events": [
{
"date": "2026-08-01T00:00:00.000Z",
"metrics": {
"sent": 100,
"delivered": 95,
"opened": 40,
"clicked": 10,
"unique_opened": 35,
"unique_clicked": 8,
"failed": 5,
"bounced": 3,
"complained": 1
}
}
]
}{
"errors": [
"Invalid app_id format"
]
}{
"errors": [
"<string>"
],
"success": true,
"reference": [
"<string>"
]
}{
"errors": [
"API rate limit exceeded"
]
}{
"errors": [
"<string>"
],
"success": true,
"reference": [
"<string>"
]
}Email provider metrics timeseries
Get email delivery, open, click, bounce, failure, and spam complaint counts for a sending domain over time, bucketed by hour, day, or month and totaled across the requested inbox providers.
curl --request GET \
--url https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries \
--header 'Authorization: <authorization>'const options = {method: 'GET', headers: {Authorization: '<authorization>'}};
fetch('https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries"
headers = {"Authorization": "<authorization>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}require 'uri'
require 'net/http'
url = URI("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_bodyHttpResponse<String> response = Unirest.get("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries")
.header("Authorization", "<authorization>")
.asString();using RestSharp;
var options = new RestClientOptions("https://api.onesignal.com/apps/{app_id}/email_analytics/provider_metrics_timeseries");
var client = new RestClient(options);
var request = new RestRequest("");
request.AddHeader("Authorization", "<authorization>");
var response = await client.GetAsync(request);
Console.WriteLine("{0}", response.Content);
false{
"events": [
{
"date": "2026-08-01T00:00:00.000Z",
"metrics": {
"sent": 100,
"delivered": 95,
"opened": 40,
"clicked": 10,
"unique_opened": 35,
"unique_clicked": 8,
"failed": 5,
"bounced": 3,
"complained": 1
}
}
]
}{
"errors": [
"Invalid app_id format"
]
}{
"errors": [
"<string>"
],
"success": true,
"reference": [
"<string>"
]
}{
"errors": [
"API rate limit exceeded"
]
}{
"errors": [
"<string>"
],
"success": true,
"reference": [
"<string>"
]
}Overview
For customers using OneSignal Email. The Email provider metrics timeseries API allows you to check email delivery, opens, clicks, bounces, failures, and spam complaints for a sending domain over time to pinpoint where deliverability problems are coming from. Metrics are bucketed by hour, day, or month. Use it to find where deliverability is slipping and act before it drags down your whole sender reputation.How to Use this API
Useproviders[] to narrow the totals to specific inbox providers (Gmail, Outlook, Yahoo, Apple, and more) and track how deliverability to them changes. Each event’s metrics are totaled across the requested providers, or across all providers when none are given.
start must be before end and no more than 365 days ago, or 60 days ago for hourly granularity.
events is empty when the domain is not found for the app or is not currently active for sending.
Headers
Your App API key with prefix Key. See Keys & IDs.
Path Parameters
Your OneSignal App ID in UUID v4 format. See Keys & IDs.
Query Parameters
The sending domain to report on. Must be an email domain configured for this app.
"mail.example.com"
Start of the reporting window as an ISO 8601 timestamp, for example 2026-08-01T00:00:00Z. Must be before end and no more than 365 days ago, or 60 days ago when granularity is hourly.
"2026-08-01T00:00:00Z"
End of the reporting window as an ISO 8601 timestamp, for example 2026-08-08T00:00:00Z.
"2026-08-08T00:00:00Z"
The size of each time bucket. hourly is only available for the last 60 days.
hourly, daily, monthly "daily"
Inbox providers to include in the totals. Repeat the parameter for each provider, for example providers[]=gmail&providers[]=yahoo_us. Omit to include all providers. Accepted values: apple, att, canadian, chinese, comcast, free_fr, french, german, gmail, google_workspace, googlers, inbox_lv, italian, japanese, outlook_365, outlook_eu, outlook_us, proton, rackspace, russian, uk, united_online, yahoo_eu, yahoo_us, other_eu, other_us, and other.
Response
200
Email metrics for a sending domain over time.
One entry for every time bucket in the reporting window, oldest first. Buckets with no email activity are included with all metrics set to 0. Empty when the domain is not found for the app or is not currently active for sending.
Show child attributes
Show child attributes
Was this page helpful?