Data API Reference
Pull Core Web Vitals, page load time, and traffic for your website out of Request Metrics as JSON.
The Request Metrics API returns the real user monitoring data for a website as JSON. One endpoint gives totals for the whole website. The other breaks the same numbers down by URL. The API only reads data, so no request can change your account.
Every metric is the 75th percentile across the page views in your date range. That’s the number the Request Metrics dashboard shows, and it’s the number Google uses to judge Core Web Vitals.
What you need
Every request needs three values.
| Value | Parameter | What it is |
|---|---|---|
| Account ID | customerId |
7 characters, one per account |
| Website ID | applicationId |
7 characters, one per website in the account |
| API key | key |
one per account, and it works for every website in the account |
Account administrators find all three on the Account Settings page. That page also has example links with your IDs and key filled in. Open one to confirm everything works before you write any code.
Warning: Your API key lets anyone read the performance data for every website in your account. The key travels in the URL, so any copy of a request URL carries a live key. Keep those URLs out of shared documents, tickets, screenshots, and logs.
Authentication
Pass your API key as the key query parameter on every request. There’s no header authentication. Request Metrics checks the key against the account in customerId and returns HTTP 401 when the key is missing or belongs to a different account.
Endpoints
Both endpoints live under https://app.requestmetrics.com/api/v1/{customerId}/{applicationId}.
Overall website performance
GET /api/v1/{customerId}/{applicationId}/performance
Returns one object with totals for the website over the date range. It takes the key, p, and device_filter parameters.
curl "https://app.requestmetrics.com/api/v1/{customerId}/{applicationId}/performance?p=7d&key={apiKey}"
{
"data": {
"pageLoads": 48213,
"userCount": 12050,
"loadP75": 1840,
"fcp": 1120,
"lcp": 2240,
"cls": 0.04,
"inp": 160,
"ttfb": 410,
"rmUrl": "https://app.requestmetrics.com/app/{applicationId}"
},
"metadata": {
"startDate": "2026-10-20T17:04:12.441+00:00",
"deviceFilter": "overall"
}
}
metadata field |
Meaning |
|---|---|
startDate |
start of the date range, ISO 8601 in UTC |
deviceFilter |
overall, desktop, or mobile |
Performance by URL
GET /api/v1/{customerId}/{applicationId}/performance/pages
Returns an array with one object per URL or URL group, sorted by page views from most to fewest. It takes every parameter in the next section.
curl "https://app.requestmetrics.com/api/v1/{customerId}/{applicationId}/performance/pages?p=30d&device_filter=mobile&key={apiKey}"
{
"data": [
{
"pageUrl": "https://example.com/pricing",
"pageLoads": 8120,
"userCount": 5230,
"loadP75": 1600,
"fcp": 980,
"lcp": 2010,
"cls": 0.02,
"inp": 140,
"ttfb": 360,
"rmUrl": "https://app.requestmetrics.com/app/{applicationId}/ux/explore/load/{filter}"
}
],
"metadata": {
"startDate": "2026-09-27T17:04:12.441+00:00",
"deviceFilter": "mobile",
"urlGroupingMode": "ungrouped",
"currentPage": 1,
"pageSize": 50,
"totalPages": 7,
"totalItems": 312
}
}
metadata field |
Meaning |
|---|---|
startDate |
start of the date range, ISO 8601 in UTC |
deviceFilter |
overall, desktop, or mobile |
urlGroupingMode |
ungrouped, grouped, or custom |
currentPage |
the page of results returned |
pageSize |
results per page |
totalPages |
number of pages at this pageSize |
totalItems |
number of URLs or groups in the date range |
Parameters
| Parameter | Endpoints | Values | Default |
|---|---|---|---|
key |
both | your API key | required |
p |
both | a date range | 24h |
device_filter |
both | mobile or desktop |
all devices |
urlGrouping |
by URL | ungrouped, grouped, or custom |
ungrouped |
page |
by URL | page number, starting at 1 | 1 |
size |
by URL | results per page | 50 |
Date range
p takes a named range or a custom one.
| Value | Range |
|---|---|
60m |
last 60 minutes |
24h |
last 24 hours |
72h |
last 72 hours |
7d |
last 7 days |
30d |
last 30 days |
60d |
last 60 days |
90d |
last 90 days |
For a custom range, pass p=c_{start}_{end} with the start and end in Unix epoch seconds. p=c_1730498400_1730584800 is one day. The start has to come before the end. The range can’t reach back more than 90 days or end in the future.
Warning: The API doesn’t reject a date range it can’t use. A misspelled range, or a custom range that breaks one of those rules, returns the last 24 hours with no error. Check metadata.startDate in the response to confirm you got the range you asked for.
Your plan’s data retention limits how far back data goes. A 90d request on a plan that keeps 30 days returns those 30 days.
Device filter
Leave device_filter off to include every device. Set it to mobile or desktop to narrow the results. Any other value counts as all devices.
URL grouping
urlGrouping sets what pageUrl holds on the performance by URL endpoint.
| Value | pageUrl holds |
|---|---|
ungrouped |
the page URL without its query string or hash, so /search?q=shoes and /search?q=hats both count as /search |
grouped |
the URL after automatic grouping and any grouping rules you set in the app. IDs, UUIDs, and long slugs become placeholders, so /orders/4821 and /orders/5102 share one row. |
custom |
the group name your website sets with the urlGroup install option or RM.setUrlGroup. Page views without a group name share one row with an empty pageUrl. |
URL Grouping explains how to send custom group names from your website.
Paging
The performance by URL endpoint returns 50 rows at a time unless you set size. Read metadata.totalItems and request each page in turn until you have that many rows. Drive paging from totalItems, because totalPages can count one extra, empty page.
Response fields
Both endpoints return data and metadata. On the overall endpoint, data is one object. On the performance by URL endpoint, data is an array of the same objects, each with a pageUrl.
| Field | Meaning | Unit |
|---|---|---|
pageUrl |
the URL or group, performance by URL only | Â |
pageLoads |
page views in the date range | count |
userCount |
unique users in the date range | count |
loadP75 |
page load time | ms |
lcp |
Largest Contentful Paint | ms |
cls |
Cumulative Layout Shift | none |
inp |
Interaction to Next Paint | ms |
fcp |
First Contentful Paint | ms |
ttfb |
Time to First Byte | ms |
rmUrl |
a link to the same view in the Request Metrics app | Â |
A metric of -1 means there was no data for it in the date range. Leave it out of averages and charts.
userCount counts the IDs your website passes to RM.identify, or anonymous browser IDs if it doesn’t call it. It’s an estimate, so small changes between date ranges don’t mean much.
Rating the numbers
Request Metrics rates each metric against Google’s thresholds. LCP, INP, and CLS are the three Core Web Vitals.
| Metric | Good | Needs improvement | Poor |
|---|---|---|---|
| LCP | under 2500 ms | 2500 to 4000 ms | 4000 ms and up |
| INP | under 200 ms | 200 to 500 ms | 500 ms and up |
| CLS | under 0.1 | 0.1 to 0.25 | 0.25 and up |
| FCP | under 1800 ms | 1800 to 3000 ms | 3000 ms and up |
| TTFB | under 800 ms | 800 to 1800 ms | 1800 ms and up |
Errors and rate limits
| Status | When |
|---|---|
| 200 | success |
| 401 | the key is missing or doesn’t match the account |
| 429 | more than 100 requests in one minute for this website |
The rate limit counts requests per website, by customerId and applicationId, and resets every minute. A 429 has an empty body. Wait for the next minute and try again. For a large export, raise size so you need fewer requests.
A valid key with a website ID that has no data returns 200, with pageLoads of 0 and every metric at -1. If every number is empty, check your IDs before you decide the website had no traffic.
Examples
The last week for the whole website
curl "https://app.requestmetrics.com/api/v1/{customerId}/{applicationId}/performance?p=7d&key={apiKey}"
The slowest pages on mobile
Request performance by URL for 30 days with the mobile filter. Then sort the array by lcp or loadP75, skipping any -1 values.
curl "https://app.requestmetrics.com/api/v1/{customerId}/{applicationId}/performance/pages?p=30d&device_filter=mobile&key={apiKey}"
Mobile against desktop
Make the same request twice, once with device_filter=mobile and once with device_filter=desktop, and compare the results.
Every URL for the last 30 days
This JavaScript reads every page of results. It keeps the API key in an environment variable so the key stays out of your source code.
const customerId = "abcdefg";
const applicationId = "1234567";
const key = process.env.RM_API_KEY;
async function getAllPages() {
const rows = [];
let page = 1;
let totalItems = 1;
while (rows.length < totalItems) {
const params = new URLSearchParams({ p: "30d", page, size: 100, key });
const url = `https://app.requestmetrics.com/api/v1/${customerId}/${applicationId}/performance/pages?${params}`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Request Metrics returned ${response.status}`);
}
const body = await response.json();
totalItems = body.metadata.totalItems;
if (body.data.length === 0) break;
rows.push(...body.data);
page++;
}
return rows;
}
Ask Claude instead
The Request Metrics Claude Skill teaches Claude to make these requests for you. Ask a question in plain language, and Claude pulls the numbers, pages through long lists of URLs, and rates the results.
What the API doesn’t include
The API covers real user performance for your websites. Analytics, errors, API monitoring, sessions, funnels, Lighthouse results, and Chrome UX Report data are only in the Request Metrics app. If you need more in the API, tell us at hello@requestmetrics.com.