curl --request GET \
--url https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times",
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: Bearer <token>"
],
]);
$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://app.onlysocial.io/os/api/{workspace}/analytics/posting-times"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"has_data": true,
"timezone": "Europe/Berlin",
"offset_hours": 1,
"accounts": 123,
"samples": 123,
"days": [
{
"day": 3,
"score": 123,
"samples": 123,
"confidence": "high"
}
],
"day_intervals": [
[
{
"start_hour": 123,
"end_hour": 123,
"best_hour": 123,
"score": 123,
"samples": 123,
"confidence": "high"
}
]
],
"best": [
{
"day": 2,
"hour": 13,
"score": 74,
"samples": 14
}
]
}{
"message": "The date range may span at most 366 days.",
"errors": {
"date_to": [
"The date range may span at most 366 days."
]
}
}Get the best times to post
When posting has worked, per weekday and hour, pooled over the chosen accounts. Each post of the last 180 days that has views counts by its engagement rate against its own account’s average, and every account weighs the same, so a busy account does not drown out the others. A slot scores 50 × that ratio, pulled toward 50 when few posts are behind it, from 0 to 100: 50 is average for these accounts, 100 twice the average or better. Only networks with the insights type take part.
Weekdays run from 0 (Sunday) to 6 (Saturday). best names up to three slots with at least two posts behind them, at most one per weekday, highest first. confidence is high from 5 posts, medium from 2, low with 1 and none without. offset_hours is the timezone’s offset from UTC now.
Read-only. Personal access tokens may call it with any workspace role, viewers included.
Required permission: publishing:analytics:read
curl --request GET \
--url https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times \
--header 'Authorization: Bearer <token>'import requests
url = "https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times",
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: Bearer <token>"
],
]);
$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://app.onlysocial.io/os/api/{workspace}/analytics/posting-times"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.onlysocial.io/os/api/{workspace}/analytics/posting-times")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"has_data": true,
"timezone": "Europe/Berlin",
"offset_hours": 1,
"accounts": 123,
"samples": 123,
"days": [
{
"day": 3,
"score": 123,
"samples": 123,
"confidence": "high"
}
],
"day_intervals": [
[
{
"start_hour": 123,
"end_hour": 123,
"best_hour": 123,
"score": 123,
"samples": 123,
"confidence": "high"
}
]
],
"best": [
{
"day": 2,
"hour": 13,
"score": 74,
"samples": 14
}
]
}{
"message": "The date range may span at most 366 days.",
"errors": {
"date_to": [
"The date range may span at most 366 days."
]
}
}Authorizations
A workspace API key: Authorization: Bearer osk_...
Path Parameters
Your workspace UUID. Must match the API key's workspace.
Query Parameters
Account UUIDs. Defaults to every account in the workspace.
IANA timezone the weekdays, hours and times are in. Defaults to the timezone setting of the key's creator (or the token's user), then UTC.
"Europe/Berlin"
Response
Success
False, with neutral scores and no best, when no account has scored history.
"Europe/Berlin"
1
Accounts with scored history.
Posts behind the scores.
Sunday first.
Show child attributes
Show child attributes
Seven lists, Sunday first, of twelve two-hour intervals. end_hour is exclusive.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
[
{
"day": 2,
"hour": 13,
"score": 74,
"samples": 14
}
]
