Real user monitoring

Core Web Vitals measured in your visitors' browsers, LCP, INP, CLS, FCP and TTFB, by page, country, device and more.

On this page

Real user monitoring (RUM) measures Core Web Vitals in the visitors' browsers. It is off by default; enable it in the zone's edge settings (rum). All endpoints share the same filters and use the 75th percentile (p75).

OperationEndpoint
Get RUM summaryGET /v1/orgs/{org}/zones/{zone}/rum/summary
Get RUM time seriesGET /v1/orgs/{org}/zones/{zone}/rum/timeseries
Get RUM breakdownGET /v1/orgs/{org}/zones/{zone}/rum/breakdown
Get LCP partsGET /v1/orgs/{org}/zones/{zone}/rum/lcp-parts
Get RUM offendersGET /v1/orgs/{org}/zones/{zone}/rum/offenders
Get RUM reportGET /v1/orgs/{org}/zones/{zone}/rum/report

Get RUM summary

GET /v1/orgs/{org}/zones/{zone}/rum/summary

Returns the p75 of LCP, INP, CLS, FCP and TTFB with their rating, against the previous period of the same length, and what the edge did with the measurement script (injection). Percentiles are per page view; visits are estimated from the sample rate.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.

Response

FieldTypeDescription
sincestring (date-time)
untilstring (date-time)
prev_sincestring (date-time)
prev_untilstring (date-time)
visitsnumberEstimated page views: Σ 1/sample_rate, rounded.
prev_visitsnumber
metricsobject
metrics.lcpRumSummaryAgg
metrics.inpRumSummaryAgg
metrics.clsRumSummaryAgg
metrics.fcpRumSummaryAgg
metrics.ttfbRumSummaryAgg
injectionobject
injection.injectedinteger
injection.csp_nonceinteger
injection.csp_blockedinteger
injection.no_headinteger
injection.sampled_outinteger

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/summary" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "since": "2026-10-27T09:30:00Z",
  "until": "2026-10-27T09:30:00Z",
  "prev_since": "2026-10-27T09:30:00Z",
  "prev_until": "2026-10-27T09:30:00Z",
  "visits": 128.0,
  "prev_visits": 128.0,
  "metrics": {
    "lcp": {
      "p50": 0.5,
      "p75": 0.5,
      "p90": 0.5,
      "count": 128,
      "good": 0,
      "needs_improvement": 0,
      "poor": 0,
      "prev_p75": 0.5,
      "prev_count": 128
    },
    "inp": {
      "p50": 0.5,
      "p75": 0.5,
      "p90": 0.5,
      "count": 128,
      "good": 0,
      "needs_improvement": 0,
      "poor": 0,
      "prev_p75": 0.5,
      "prev_count": 128
    },
    "cls": {
      "p50": 0.5,
      "p75": 0.5,
      "p90": 0.5,
      "count": 128,
      "good": 0,
      "needs_improvement": 0,
      "poor": 0,
      "prev_p75": 0.5,
      "prev_count": 128
    },
    "fcp": {
      "p50": 0.5,
      "p75": 0.5,
      "p90": 0.5,
      "count": 128,
      "good": 0,
      "needs_improvement": 0,
      "poor": 0,
      "prev_p75": 0.5,
      "prev_count": 128
    },
    "ttfb": {
      "p50": 0.5,
      "p75": 0.5,
      "p90": 0.5,
      "count": 128,
      "good": 0,
      "needs_improvement": 0,
      "poor": 0,
      "prev_p75": 0.5,
      "prev_count": 128
    }
  },
  "injection": {
    "injected": 0,
    "csp_nonce": 0,
    "csp_blocked": 0,
    "no_head": 0,
    "sampled_out": 0
  }
}

Get RUM time series

GET /v1/orgs/{org}/zones/{zone}/rum/timeseries

Returns the p75 of each metric and the visits per interval, including empty intervals (with null and 0).

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.
stepqueryintegerNoSeconds per point, a multiple of 60, at most 1000 points. By default the smallest of 300, 900, 1800, 3600, 10800, 21600, 43200 and 86400 that gives at most 60 points. Buckets aligned to the Unix epoch (UTC). Minimum 60.

Response

FieldTypeDescription
stepinteger
pointsarray of object
points[].tsstring (date-time)Time of the request.
points[].visitsnumber
points[].lcpnumber or nullp75.
points[].inpnumber or null
points[].clsnumber or null
points[].fcpnumber or null
points[].ttfbnumber or null

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/timeseries" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "step": 0,
  "points": [
    {
      "ts": "2026-10-27T09:30:00Z",
      "visits": 128.0,
      "lcp": 0.5,
      "inp": 0.5,
      "cls": 0.5,
      "fcp": 0.5,
      "ttfb": 0.5
    }
  ]
}

Get RUM breakdown

GET /v1/orgs/{org}/zones/{zone}/rum/breakdown

Returns the metrics per value of one dimension (by), sorted by visits (ties by key).

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.
byquerystringNoDimension to group by. One of path, country, node, device, connection, nav_type, host, viewport. Default path.
limitqueryintegerNoMaximum number of items. Default 10. From 1 to 100.

Response

FieldTypeDescription
bystring
rowsarray of object
rows[].keystringValue of the dimension ("" = unknown).
rows[].visitsnumber
rows[].metricsRumMetrics

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/breakdown?by=country" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "by": "path",
  "rows": [
    {
      "key": "/pricing",
      "visits": 128.0,
      "metrics": {
        "lcp": {},
        "inp": {},
        "cls": {},
        "fcp": {},
        "ttfb": {}
      }
    }
  ]
}

Get LCP parts

GET /v1/orgs/{org}/zones/{zone}/rum/lcp-parts

Splits LCP into its parts (TTFB, resource load delay, resource load time and render delay) for the slow views (LCP at or above p75) and for all views. by adds rows for the 10 devices or paths with most views.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.
byquerystringNoAdds rows (the 10 with most views). One of device, path.

Response

FieldTypeDescription
lcp_p75number or null
countinteger
partsRumLcpPartsValuesViews with LCP ≥ p75.
allRumLcpPartsValues
rowsarray of object
rows[].keystring
rows[].lcp_p75number or null
rows[].countinteger
rows[].partsRumLcpPartsValues

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/lcp-parts" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "lcp_p75": 0.5,
  "count": 128,
  "parts": {
    "ttfb": 0.5,
    "load_delay": 0.5,
    "load_duration": 0.5,
    "render_delay": 0.5
  },
  "all": {
    "ttfb": 0.5,
    "load_delay": 0.5,
    "load_duration": 0.5,
    "render_delay": 0.5
  },
  "rows": [
    {
      "key": "/pricing",
      "lcp_p75": 0.5,
      "count": 128,
      "parts": {
        "ttfb": 0.5,
        "load_delay": 0.5,
        "load_duration": 0.5,
        "render_delay": 0.5
      }
    }
  ]
}

Get RUM offenders

GET /v1/orgs/{org}/zones/{zone}/rum/offenders

Ranks the elements, resources and scripts with most poor views of their metric (then most views), without the empty key. The keys (selectors, URLs) come from the visitors' pages.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.
kindquerystringYesWhat to rank. One of lcp_element, lcp_url, inp_target, inp_script, cls_target.
limitqueryintegerNoMaximum number of items. Default 10. From 1 to 100.

Response

  • 200: Returns an object with the fields below.
FieldTypeDescription
kindstring
rowsarray of RumOffender

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/offenders?kind=lcp_element" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "kind": "example",
  "rows": [
    {
      "key": "/pricing",
      "count": 128,
      "p75": 0.5,
      "poor": 0,
      "top_path": "/docs/"
    }
  ]
}

Get RUM report

GET /v1/orgs/{org}/zones/{zone}/rum/report

Returns in one call everything the dashboard's real user monitoring page shows, with the zone's RUM settings, the summary, a time series with automatic step, breakdowns by path (25 rows), country, node, device and connection (10 rows), LCP parts by device and the top offenders. breakdowns.device ignores the device filter.

Required role: readonly or higher.

Parameters

NameInTypeRequiredDescription
orgpathstring (uuid)YesOrganization id. Every route checks that it is the token's organization (otherwise 404).
zonepathstring (uuid)YesZone id (see List zones).
sincequerystring (date-time)NoRFC 3339; until minus 7 days by default.
untilquerystring (date-time)NoRFC 3339, exclusive; now by default. At most 31 days of range.
hostquerystringNoOnly that name. At most 253 characters.
pathquerystringNoOnly that exact path. At most 512 characters. Pattern ^/.
countryquerystringNoISO 3166-1 alpha-2 (lowercase accepted). Pattern ^[A-Za-z]{2}$.
nodequerystringNoOnly the views measured through that edge node. At most 128 characters.
devicequerystringNoOnly that device type. One of mobile, tablet, desktop.
connectionquerystringNoOnly that effective connection type. One of 4g, 3g, 2g, slow-2g.
nav_typequerystringNoOnly that navigation type. One of navigate, reload, back-forward, back-forward-cache, prerender, restore.

Response

FieldTypeDescription
summaryRumSummary
timeseriesRumTimeseries
breakdownsobject
breakdowns.pathRumBreakdown
breakdowns.countryRumBreakdown
breakdowns.nodeRumBreakdown
breakdowns.deviceRumBreakdown
breakdowns.connectionRumBreakdown
lcp_partsRumLcpParts
offendersobject
offenders.lcp_elementarray of RumOffender
offenders.inp_targetarray of RumOffender
offenders.inp_scriptarray of RumOffender
offenders.cls_targetarray of RumOffender
settingsZoneEdgeRUM

Errors

StatusDescription
400Malformed request (bad_request).
404Not found, or not visible to the token (not_found).
503Not available right now (unavailable); retry later.

Example

curl "https://dash.openwaf.dev/v1/orgs/$OPENWAF_ORG/zones/6f1d2c3b-8a4e-4b7d-9c21-5e3f7a8b9c0d/rum/report" \
  -H "Authorization: Bearer $OPENWAF_TOKEN"
200
{
  "summary": {
    "since": "2026-10-27T09:30:00Z",
    "until": "2026-10-27T09:30:00Z",
    "prev_since": "2026-10-27T09:30:00Z",
    "prev_until": "2026-10-27T09:30:00Z",
    "visits": 128.0,
    "prev_visits": 128.0,
    "metrics": {
      "lcp": {
        "p50": 0.5,
        "p75": 0.5,
        "p90": 0.5,
        "count": 128,
        "good": 0,
        "needs_improvement": 0,
        "poor": 0,
        "prev_p75": 0.5,
        "prev_count": 128
      },
      "inp": {
        "p50": 0.5,
        "p75": 0.5,
        "p90": 0.5,
        "count": 128,
        "good": 0,
        "needs_improvement": 0,
        "poor": 0,
        "prev_p75": 0.5,
        "prev_count": 128
      },
      "cls": {
        "p50": 0.5,
        "p75": 0.5,
        "p90": 0.5,
        "count": 128,
        "good": 0,
        "needs_improvement": 0,
        "poor": 0,
        "prev_p75": 0.5,
        "prev_count": 128
      },
      "fcp": {
        "p50": 0.5,
        "p75": 0.5,
        "p90": 0.5,
        "count": 128,
        "good": 0,
        "needs_improvement": 0,
        "poor": 0,
        "prev_p75": 0.5,
        "prev_count": 128
      },
      "ttfb": {
        "p50": 0.5,
        "p75": 0.5,
        "p90": 0.5,
        "count": 128,
        "good": 0,
        "needs_improvement": 0,
        "poor": 0,
        "prev_p75": 0.5,
        "prev_count": 128
      }
    },
    "injection": {
      "injected": 0,
      "csp_nonce": 0,
      "csp_blocked": 0,
      "no_head": 0,
      "sampled_out": 0
    }
  },
  "timeseries": {
    "step": 0,
    "points": [
      {
        "ts": "2026-10-27T09:30:00Z",
        "visits": 128.0,
        "lcp": 0.5,
        "inp": 0.5,
        "cls": 0.5,
        "fcp": 0.5,
        "ttfb": 0.5
      }
    ]
  },
  "breakdowns": {
    "path": {
      "by": "path",
      "rows": [
        {}
      ]
    },
    "country": {
      "by": "path",
      "rows": [
        {}
      ]
    },
    "node": {
      "by": "path",
      "rows": [
        {}
      ]
    },
    "device": {
      "by": "path",
      "rows": [
        {}
      ]
    },
    "connection": {
      "by": "path",
      "rows": [
        {}
      ]
    }
  },
  "lcp_parts": {
    "lcp_p75": 0.5,
    "count": 128,
    "parts": {
      "ttfb": 0.5,
      "load_delay": 0.5,
      "load_duration": 0.5,
      "render_delay": 0.5
    },
    "all": {
      "ttfb": 0.5,
      "load_delay": 0.5,
      "load_duration": 0.5,
      "render_delay": 0.5
    },
    "rows": [
      {
        "key": "/pricing",
        "lcp_p75": 0.5,
        "count": 128,
        "parts": {}
      }
    ]
  },
  "offenders": {
    "lcp_element": [
      {
        "key": "/pricing",
        "count": 128,
        "p75": 0.5,
        "poor": 0,
        "top_path": "/docs/"
      }
    ],
    "inp_target": [
      {
        "key": "/pricing",
        "count": 128,
        "p75": 0.5,
        "poor": 0,
        "top_path": "/docs/"
      }
    ],
    "inp_script": [
      {
        "key": "/pricing",
        "count": 128,
        "p75": 0.5,
        "poor": 0,
        "top_path": "/docs/"
      }
    ],
    "cls_target": [
      {
        "key": "/pricing",
        "count": 128,
        "p75": 0.5,
        "poor": 0,
        "top_path": "/docs/"
      }
    ]
  },
  "settings": {
    "enabled": false,
    "sample_rate": 1,
    "exclude_paths": []
  }
}

Last updated:

↑↓ to navigate↵ to openesc to close