curl --request GET \
--url https://api.apsio.io/v1/projects/{projectId}/performance/frames \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.apsio.io/v1/projects/{projectId}/performance/frames"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.apsio.io/v1/projects/{projectId}/performance/frames', 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://api.apsio.io/v1/projects/{projectId}/performance/frames",
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://api.apsio.io/v1/projects/{projectId}/performance/frames"
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://api.apsio.io/v1/projects/{projectId}/performance/frames")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apsio.io/v1/projects/{projectId}/performance/frames")
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{
"from": "2026-10-04T10:15:00.431000000Z",
"to": "2026-10-04T10:15:00.431000000Z",
"totals": {
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
},
"releases": [
{
"app_id": "<string>",
"release": "<string>",
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
}
],
"screens": [
{
"app_id": "<string>",
"screen": "<string>",
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
}
]
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Slow and frozen frames
Slow and frozen frames (spec 8.5) per release and per screen: counts, per minute in the foreground, and the share of slow frames among all frames. Per-minute rates compare across platforms; the frame total and the slow share compare within one platform only, because iOS counts the display’s idle refreshes. A screen’s rates over less than a minute in the foreground are noisy: the rate sorts list such screens last. Default range: the last 7 days, at most 30.
curl --request GET \
--url https://api.apsio.io/v1/projects/{projectId}/performance/frames \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.apsio.io/v1/projects/{projectId}/performance/frames"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.apsio.io/v1/projects/{projectId}/performance/frames', 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://api.apsio.io/v1/projects/{projectId}/performance/frames",
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://api.apsio.io/v1/projects/{projectId}/performance/frames"
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://api.apsio.io/v1/projects/{projectId}/performance/frames")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.apsio.io/v1/projects/{projectId}/performance/frames")
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{
"from": "2026-10-04T10:15:00.431000000Z",
"to": "2026-10-04T10:15:00.431000000Z",
"totals": {
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
},
"releases": [
{
"app_id": "<string>",
"release": "<string>",
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
}
],
"screens": [
{
"app_id": "<string>",
"screen": "<string>",
"sessions": 123,
"foreground_minutes": 123,
"frames": 123,
"slow": 123,
"frozen": 123,
"slow_per_minute": 123,
"frozen_per_minute": 123,
"slow_share": 123
}
]
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}{
"error": {
"code": "invalid_request",
"message": "<string>"
}
}Authorizations
A project token (apsio_pt_v0...), which reads exactly one project, or an OAuth access token issued for the API, which reads what its user can. Access tokens issued for Apsio's MCP server are accepted only from the MCP server itself.
Path Parameters
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"0192f3a4-0000-7000-8000-00000000a101"
Query Parameters
Start of the time range, inclusive (RFC 3339). Defaults to the range end minus the default length.
"2026-10-01T00:00:00Z"
End of the time range, exclusive (RFC 3339). Defaults to now.
"2026-10-08T00:00:00Z"
Only this app.
^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$Only this release.
128Order of the screens.
minutes, slow_per_minute, frozen_per_minute 1 <= x <= 50Response
Slow and frozen frames per release and per screen.
RFC 3339 time in UTC with up to nanosecond precision.
"2026-10-04T10:15:00.431000000Z"
RFC 3339 time in UTC with up to nanosecond precision.
"2026-10-04T10:15:00.431000000Z"
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Show child attributes