APM API

Read where request time goes, which endpoints and operations consume it, what regressed after a deploy, slow examples, dependencies and distributed traces.

This page as Markdown

These operations answer the questions on the app’s APM pages: where request time goes, which endpoints use the most of it, what got slower, and which requests belong to one distributed trace. The first four are computed from the per-request APM totals, so they stay fast at any traffic volume. The APM analytics operations go deeper: span operations and endpoints ranked on the server, trends, heatmaps, before-and-after comparisons, slow examples and dependencies. For individual operations, see also the Spans API.

Plan: needs a plan that includes APM; otherwise every operation answers 403 with code 2221. Permissions: any member, or a user or administrator API token.

All times are ISO 8601 in UTC, for example 2026-10-19T00:00:00.000Z. Durations are in milliseconds.

Time breakdown

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/breakdown

Splits request time into database, cache, outbound HTTP, queue and RPC, and application time, as a total for the range and as a time series. Application time is what remains after the instrumented operations, never below 0.

Path parameters

  • accountSid (path, string, required): The account identifier.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range.

  • environmentSid (query, string): Only this environment.

  • bucketSid (query, string): Only this bucket.

  • endpoint (query, string): Only this endpoint, for example /v1/orders/{order_id}.

Response

  • summary (object, required): The whole range.

summary

  • requestCount (number): Requests.

  • errorCount (number): Requests that failed.

  • totalMs (number): Wall-clock time of the requests.

  • dbMs (number): Time in database queries.

  • cacheMs (number): Time in Redis and other caches.

  • httpOutMs (number): Time in outbound HTTP calls.

  • queueMs (number): Time in queue and RPC calls.

  • appMs (number): Remaining in-process time.

  • spanCount (number): Spans recorded.

  • p50Ms (number): Median request duration.

  • p95Ms (number): 95th percentile duration.

  • p99Ms (number): 99th percentile duration.

  • timeseries (object[], required): The same fields per period (without p50Ms and p99Ms), plus bucket: the start of the period. The period width follows the length of the range.

  • rollup (boolean, required): true when the answer came from pre-aggregated metrics.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/breakdown \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z' \
  --data-urlencode 'bucketSid=k3m9p2x'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  startTime: '2026-10-19T00:00:00.000Z',
  endTime: '2026-10-20T00:00:00.000Z',
  bucketSid: 'k3m9p2x',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/breakdown?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { summary } = await response.json();
console.log(`database share: ${Math.round((summary.dbMs / summary.totalMs) * 100)}%`);
json
{
  "summary": {
    "requestCount": 10412,
    "errorCount": 538,
    "totalMs": 1484700,
    "dbMs": 612300,
    "cacheMs": 21400,
    "httpOutMs": 498100,
    "queueMs": 0,
    "appMs": 352900,
    "spanCount": 88210,
    "p50Ms": 61,
    "p95Ms": 410,
    "p99Ms": 1240
  },
  "timeseries": [
    {
      "bucket": "2026-10-19T14:00:00.000Z",
      "requestCount": 702,
      "errorCount": 61,
      "totalMs": 272400,
      "dbMs": 41800,
      "cacheMs": 1500,
      "httpOutMs": 201300,
      "queueMs": 0,
      "appMs": 27800,
      "spanCount": 5960,
      "p95Ms": 3980
    }
  ],
  "rollup": true
}

Endpoints by time consumed

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/endpoints

Ranks endpoints by the total time they consume, with the same split as Time breakdown. Total time, not average latency, shows where your capacity goes: a fast endpoint called constantly can cost more than a slow one called rarely.

Path parameters

  • accountSid (path, string, required): The account identifier.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range.

  • environmentSid (query, string): Only this environment.

  • bucketSid (query, string): Only this bucket.

  • limit (query, integer, default 50): Endpoints to return, 1 to 1000.

Response

  • points (object[], required): One entry per endpoint, most time first: endpoint, requestCount, errorCount, averageDurationMs, p95Ms, p99Ms, lastSeen, and the time split totalMs, dbMs, cacheMs, httpOutMs, queueMs, appMs and spanCount.
bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/endpoints \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z' \
  --data-urlencode 'limit=10'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  startTime: '2026-10-19T00:00:00.000Z',
  endTime: '2026-10-20T00:00:00.000Z',
  limit: '10',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/endpoints?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "points": [
    {
      "endpoint": "/v1/checkout",
      "requestCount": 612,
      "errorCount": 9,
      "averageDurationMs": 684,
      "p95Ms": 1420,
      "p99Ms": 2310,
      "lastSeen": "2026-10-19T23:58:41.000Z",
      "totalMs": 418600,
      "dbMs": 96300,
      "cacheMs": 2100,
      "httpOutMs": 287400,
      "queueMs": 0,
      "appMs": 32800,
      "spanCount": 9180
    },
    {
      "endpoint": "/v1/orders/{order_id}",
      "requestCount": 1830,
      "errorCount": 22,
      "averageDurationMs": 171,
      "p95Ms": 512,
      "p99Ms": 940,
      "lastSeen": "2026-10-19T23:59:12.000Z",
      "totalMs": 312900,
      "dbMs": 261700,
      "cacheMs": 4100,
      "httpOutMs": 0,
      "queueMs": 0,
      "appMs": 47100,
      "spanCount": 42090
    }
  ]
}

Regressions

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/regressions

Finds endpoints whose latency or error rate moved against a baseline window, ranked by how much the change matters given their traffic.

Path parameters

  • accountSid (path, string, required): The account identifier.

Query parameters

  • startTime (query, string, required): Start of the window to examine.

  • endTime (query, string, required): End of the window to examine.

  • environmentSid (query, string): Only this environment.

  • bucketSid (query, string): Only this bucket.

  • baseline (query, string, default previous): previous compares with the window just before, of the same length. weekAgo compares with the same window seven days earlier, which suits traffic with a weekly shape.

  • minRequests (query, integer, default 20): Ignore endpoints with fewer requests than this in either window, 1 to 1,000,000.

  • limit (query, integer, default 20): Endpoints to return, 1 to 1000.

Response

  • baseline (string, required): The baseline used.

  • points (object[], required): One entry per endpoint, most significant first.

point

  • endpoint (string): The endpoint.

  • requestCount (number): Requests in the window.

  • baselineRequestCount (number): Requests in the baseline.

  • p95Ms (number): 95th percentile now.

  • baselineP95Ms (number): 95th percentile in the baseline.

  • p95DeltaPct (number): Change in the 95th percentile, in percent.

  • errorRate (number): Share of requests that failed now, from 0 to 1.

  • baselineErrorRate (number): The same in the baseline.

  • errorRateDelta (number): The difference.

  • totalMs (number): Time consumed now.

  • baselineTotalMs (number): Time consumed in the baseline.

  • score (number): The ranking score: latency and error movement weighted by traffic.

  • baseline (string): The baseline used.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/regressions \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'startTime=2026-10-19T14:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-19T14:40:00.000Z' \
  --data-urlencode 'baseline=weekAgo'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  startTime: '2026-10-19T14:00:00.000Z',
  endTime: '2026-10-19T14:40:00.000Z',
  baseline: 'weekAgo',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/regressions?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "baseline": "weekAgo",
  "points": [
    {
      "endpoint": "/v1/payments/{payment_id}/capture",
      "baseline": "weekAgo",
      "requestCount": 96,
      "baselineRequestCount": 91,
      "p95Ms": 3980,
      "baselineP95Ms": 310,
      "p95DeltaPct": 1183.9,
      "errorRate": 0.44,
      "baselineErrorRate": 0.01,
      "errorRateDelta": 0.43,
      "totalMs": 241200,
      "baselineTotalMs": 21800,
      "score": 912.4
    }
  ]
}

Distributed trace

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/trace

Returns every captured request that belongs to one distributed trace, in time order, across buckets and services. Each request is stamped with its trace id when it is captured: from the incoming traceparent header when there is one.

Path parameters

  • accountSid (path, string, required): The account identifier.

Query parameters

  • traceId (query, string, required): The trace id.

  • startTime (query, string, required): Start of the range to search.

  • endTime (query, string, required): End of the range to search.

  • environmentSid (query, string): Only this environment.

  • bucketSid (query, string): Only this bucket.

  • limit (query, integer, default 100): Requests to return, 1 to 1000.

Response

  • traceId (string, required): The trace id.

  • points (object[], required): The requests, oldest first: dt (when it started), sid, endpoint, method, host, path, direction, bucketSid, environmentSid, statusCode, durationMs and spanCount. Use sid with Get request for the detail.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/trace \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'traceId=4bf92f3577b34da6a3ce929d0e0e4736' \
  --data-urlencode 'startTime=2026-10-19T14:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-19T15:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  traceId: '4bf92f3577b34da6a3ce929d0e0e4736',
  startTime: '2026-10-19T14:00:00.000Z',
  endTime: '2026-10-19T15:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/trace?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
  "points": [
    {
      "dt": "2026-10-19T14:21:07.412Z",
      "sid": "req_2nA8fK3pQ7xV1mZ5tR9wB4cL6hY",
      "endpoint": "/v1/payments/{payment_id}/capture",
      "method": "POST",
      "host": "api.acme-store.example",
      "path": "/v1/payments/pi_3f9a1c7e2b4d6a/capture",
      "direction": "in",
      "bucketSid": "k3m9p2x",
      "environmentSid": "prd7k2",
      "statusCode": 502,
      "durationMs": 4012,
      "spanCount": 3
    },
    {
      "dt": "2026-10-19T14:21:07.418Z",
      "sid": "req_2cV9bN1mK4jH7gF3dS6aP8oI5uY",
      "endpoint": "/v1/payment_intents/{payment_intent_id}/capture",
      "method": "POST",
      "host": "payments.acme-pay.example",
      "path": "/v1/payment_intents/pi_3f9a1c7e2b4d6a/capture",
      "direction": "out",
      "bucketSid": "k3m9p2x",
      "environmentSid": "prd7k2",
      "statusCode": 504,
      "durationMs": 3995,
      "spanCount": 0
    }
  ]
}

APM analytics

The operations below power the app’s APM analytics pages. They rank span operations and endpoints on the server by total time, percentiles, calls, calls per request or regression score, chart one of them over time, compare it before and after a deploy, and return slow examples to open. Unlike the operations above, they report span-level detail and estimated call counts.

Every analytics response starts with the same fields:

  • sourceState (string, required): ready, or absent when the account has no data of this kind yet, so an empty answer is expected.

  • source (string, required): hot_raw (computed from individual spans) or metrics (from pre-aggregated metrics).

  • coverage (object, required): How much of the range was read: status (full, partial or none), source, requested and effective (the range actually read), hotFrom, reason (why it is partial, for example metrics_lag or raw_window_capped) and foldedShare.

  • estimator (string | null, required): How percentiles were computed: tdigest, exact or histogram.

  • unit (string, required): The unit of every duration in the answer: us (microseconds) or ms.

  • window (object, required): The range answered: from, to (rounded inward to minutes) and snapSeconds.

Answers about operations also carry statementText (whether the account stores statement text) and dictionaryAvailable (whether fingerprint details could be read in time).

All of them take startTime and endTime (required; endTime is exclusive), and optional bucketSid and environmentSid.

Rank span operations

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/operations

Ranks span operations (a fingerprint and its algorithm version) on the server, so slow but rare operations are not cut off by limit.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range (exclusive).

  • orderBy (query, string, default total): total, p95, p99, calls, calls_per_request (N+1 queries first), error_rate or regression.

  • limit (query, integer, default 50): Operations to return, 1 to 100.

  • endpoint (query, string): Only operations run by this inbound endpoint.

  • types (query, string): Only these span types, comma-separated: db.query, redis, cache, http.out, queue, rpc, graphql, custom.

  • minCalls (query, number, default 20): For error_rate, calls_per_request and regression ranking, ignore operations with fewer estimated calls (per side, for regression).

  • pivotAt (query, string): For regression ranking, the deploy time that splits before from after. Defaults to the middle of the range.

  • minRelativeIncrease (query, number, default 0.1): For regression ranking, the smallest p95 increase that counts (0.1 is +10%).

  • fpVersion (query, integer): Only this fingerprint algorithm version.

Response

The common fields, orderBy, limit, minCalls, pivotAt, and:

  • points (object[], required): One entry per operation: fingerprint, fpVersion, calls (estimated), rows (spans read), total, avg, p50, p95, p99, max, errors, errorRate, lastSeen, latestVersion (the latest service version seen), sampledRequests, callsPerRequest, type, system, op, target, name, db, host, regression (with regression ranking) and dictionary (fingerprint details, or null).
bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/operations \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z' \
  --data-urlencode 'orderBy=calls_per_request' \
  --data-urlencode 'types=db.query'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  startTime: '2026-10-19T00:00:00.000Z',
  endTime: '2026-10-20T00:00:00.000Z',
  orderBy: 'calls_per_request',
  types: 'db.query',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/operations?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "coverage": { "status": "full", "source": "hot_raw", "requested": {}, "hotFrom": null },
  "source": "hot_raw",
  "estimator": "exact",
  "unit": "us",
  "window": { "from": "2026-10-19T00:00:00.000Z", "to": "2026-10-20T00:00:00.000Z", "snapSeconds": 60 },
  "orderBy": "calls_per_request",
  "limit": 50,
  "minCalls": 20,
  "pivotAt": null,
  "statementText": true,
  "dictionaryAvailable": true,
  "points": [
    {
      "fingerprint": "fpr_5b8e2d7c1a9f4e3b",
      "fpVersion": 1,
      "calls": 21960,
      "rows": 21960,
      "total": 40406400,
      "avg": 1840,
      "p50": 1500,
      "p95": 4200,
      "p99": 7900,
      "max": 12100,
      "errors": 0,
      "errorRate": 0,
      "lastSeen": "2026-10-19T23:59:12.000Z",
      "latestVersion": "v2026.10.19",
      "sampledRequests": 1830,
      "callsPerRequest": 12,
      "type": "db.query",
      "system": "postgresql",
      "op": "SELECT",
      "target": "order_items",
      "name": "SELECT order_items",
      "db": "acme_store",
      "host": "db.acme.internal",
      "dictionary": null
    }
  ]
}

Span operation trend

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/operations/trend

Charts p50, p95, p99, calls and errors over time for one operation.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range (exclusive).

  • fingerprint (query, string, required): The operation’s fingerprint (fpr_…).

  • fpVersion (query, integer, required): Its algorithm version, 1 to 255 (from Rank span operations; 1 when it has none).

  • endpoint (query, string): Only spans run by this inbound endpoint.

  • maxPoints (query, integer, default 120): At most this many periods, 2 to 500.

Response

The common fields, and:

  • step (object | null, required): The period width: stepSeconds, fromSeconds, toSeconds, and whether the first and last periods are partial.

  • points (object[], required): One entry per period: bucket (start, epoch seconds), calls, rows, errors, total, p50, p95 and p99.

  • operation (object | null, required): What the operation is: type, system, db, op, target, name, host, callSite, callSiteFn, firstSeenVersion, firstSeenAt, lastSeenAt, statement and callStack (both null unless statement text is on).

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/operations/trend \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'fingerprint=fpr_5b8e2d7c1a9f4e3b' \
  --data-urlencode 'fpVersion=1' \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  fingerprint: 'fpr_5b8e2d7c1a9f4e3b',
  fpVersion: '1',
  startTime: '2026-10-19T00:00:00.000Z',
  endTime: '2026-10-20T00:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/operations/trend?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "source": "hot_raw",
  "unit": "us",
  "step": { "stepSeconds": 720, "fromSeconds": 1792368000, "toSeconds": 1792454400, "firstBucketPartial": false, "lastBucketPartial": false },
  "points": [
    { "bucket": 1792418400, "calls": 1104, "rows": 1104, "errors": 0, "total": 2030000, "p50": 1500, "p95": 4100, "p99": 7700 }
  ],
  "operation": { "type": "db.query", "system": "postgresql", "db": "acme_store", "op": "SELECT", "target": "order_items", "name": "SELECT order_items", "host": "db.acme.internal", "callSite": "src/repositories/orderRepository.js:48:22", "callSiteFn": "loadLineItems", "firstSeenVersion": "v2026.10.2", "firstSeenAt": "2026-10-02T10:04:51.000Z", "lastSeenAt": "2026-10-19T23:59:12.000Z", "statement": "SELECT * FROM order_items WHERE order_id = $1 AND line = $2", "callStack": null },
  "statementText": true,
  "dictionaryAvailable": true
}

The examples on this page leave out some of the common fields.

Span operation heatmap

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/operations/heatmap

Returns a latency heatmap for one operation: counts of spans per period and fixed latency band.

Query parameters

The same as Span operation trend; maxPoints defaults to 60.

Response

The common fields, step and operation as in Span operation trend, and:

  • bounds (number[], required): The latency band edges, in unit.

  • cells (object[], required): One entry per non-empty cell: bucket (period start, epoch seconds), latencyBucket (the band’s index), lower, upper and count.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/operations/heatmap \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'fingerprint=fpr_2a7e9c4b1d8f6e3a' \
  --data-urlencode 'fpVersion=1' \
  --data-urlencode 'startTime=2026-10-19T13:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-19T16:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  fingerprint: 'fpr_2a7e9c4b1d8f6e3a',
  fpVersion: '1',
  startTime: '2026-10-19T13:00:00.000Z',
  endTime: '2026-10-19T16:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/operations/heatmap?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { cells } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "us",
  "bounds": [1000, 10000, 100000, 1000000, 10000000],
  "cells": [
    { "bucket": 1792418400, "latencyBucket": 3, "lower": 1000000, "upper": 10000000, "count": 19 }
  ]
}

Span operation regression

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/operations/regression

Compares one operation before and after a deploy, split by time or by service version, with both distributions and a verdict.

Query parameters

The fingerprint parameters of Span operation trend, plus:

  • pivotAt (query, string, required): The deploy time that splits before from after, inside the range.

  • version (query, string): Split by version instead: spans from this service version are “after” whenever they ran, other versions “before”.

  • previousVersion (query, string): With version, only this version counts as “before”.

  • unlabelled (query, string, default by_time): Spans without a service version: by_time (split by pivotAt) or exclude.

Response

The common fields, operation, and:

  • mode (string, required): time or version.

  • before (object | null, required): calls, rows, errors, unlabelled, p50, p95, p99 and hist (counts per band in bounds). after has the same fields.

  • verdict (object | null, required): regressed, score (the p95 increase times the calls after; null with too little data), deltaP95, ratioP95 and reason (insufficient_data, below_threshold, improved or null).

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/operations/regression \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'fingerprint=fpr_5b8e2d7c1a9f4e3b' \
  --data-urlencode 'fpVersion=1' \
  --data-urlencode 'pivotAt=2026-10-19T10:00:00.000Z' \
  --data-urlencode 'startTime=2026-10-18T10:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T10:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  fingerprint: 'fpr_5b8e2d7c1a9f4e3b',
  fpVersion: '1',
  pivotAt: '2026-10-19T10:00:00.000Z',
  startTime: '2026-10-18T10:00:00.000Z',
  endTime: '2026-10-20T10:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/operations/regression?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { verdict } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "us",
  "pivotAt": "2026-10-19T10:00:00.000Z",
  "mode": "time",
  "bounds": [1000, 10000, 100000],
  "before": { "calls": 20410, "rows": 20410, "errors": 0, "unlabelled": 0, "p50": 1400, "p95": 3900, "p99": 7100, "hist": [8100, 12200, 110, 0] },
  "after": { "calls": 21960, "rows": 21960, "errors": 0, "unlabelled": 0, "p50": 1500, "p95": 4200, "p99": 7900, "hist": [8300, 13500, 160, 0] },
  "verdict": { "score": 6588000, "deltaP95": 300, "ratioP95": 1.08, "regressed": false, "reason": "below_threshold" }
}

Span operation examples

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/operations/examples

Returns the slowest spans of one operation, and optionally some near a threshold such as its p95, to open in the request detail.

Query parameters

The fingerprint parameters of Span operation trend, plus:

  • limit (query, integer, default 20): Slowest examples, 1 to 100.

  • nearDuration (query, number): Also return examples at or just above this duration (in the answer’s unit), typically the p95 from the trend.

  • nearLimit (query, integer): How many of those, 1 to 50.

Response

The common fields, operation, and:

  • examples (object[], required): One entry per span: kind (slowest or near the threshold), dt, requestDt, requestSid (open it with Get request), spanSid, traceId, duration, ok, errorClass, statusCode, endpoint, method, serviceVersion and instanceSid.
bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/operations/examples \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'fingerprint=fpr_2a7e9c4b1d8f6e3a' \
  --data-urlencode 'fpVersion=1' \
  --data-urlencode 'limit=5' \
  --data-urlencode 'startTime=2026-10-19T13:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-19T16:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  fingerprint: 'fpr_2a7e9c4b1d8f6e3a',
  fpVersion: '1',
  limit: '5',
  startTime: '2026-10-19T13:00:00.000Z',
  endTime: '2026-10-19T16:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/operations/examples?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { examples } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "us",
  "examples": [
    {
      "kind": "slowest",
      "dt": "2026-10-19T14:21:07.418Z",
      "requestDt": "2026-10-19T14:21:07.412Z",
      "requestSid": "req_2nA8fK3pQ7xV1mZ5tR9wB4cL6hY",
      "spanSid": "spn_02",
      "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
      "duration": 3995000,
      "ok": false,
      "errorClass": "timeout",
      "statusCode": 504,
      "endpoint": "/v1/payments/{payment_id}/capture",
      "method": "POST",
      "serviceVersion": "v2026.10.19",
      "instanceSid": "ins_k8f2a1"
    }
  ]
}

Rank endpoints

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/endpoints

Ranks endpoints (template and method) on the server. With direction=out, ranks the outbound calls your API makes.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range (exclusive).

  • orderBy (query, string, default total): total, p95, p99, calls, error_rate or regression.

  • direction (query, string, default in): in (your API’s endpoints) or out (calls it makes).

  • limit (query, integer, default 50): Endpoints to return, 1 to 100.

  • minCalls (query, number, default 20): As for Rank span operations.

  • pivotAt (query, string): As for Rank span operations.

  • minRelativeIncrease (query, number, default 0.1): As for Rank span operations.

Response

The common fields, orderBy, limit, minCalls, pivotAt, and:

  • points (object[], required): One entry per endpoint: endpoint, method, calls, rows, total, avg, p50, p95, p99, max, errors, errorRate, clientErrors, lastSeen, latestVersion and, with regression ranking, regression.
bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/endpoints \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'orderBy=p95' \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({ orderBy: 'p95', startTime: '2026-10-19T00:00:00.000Z', endTime: '2026-10-20T00:00:00.000Z' });
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/endpoints?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "ms",
  "orderBy": "p95",
  "limit": 50,
  "minCalls": 20,
  "pivotAt": null,
  "points": [
    {
      "endpoint": "/v1/payments/{payment_id}/capture",
      "method": "POST",
      "calls": 402,
      "rows": 402,
      "total": 246180,
      "avg": 612.4,
      "p50": 240,
      "p95": 3980,
      "p99": 4060,
      "max": 4120,
      "errors": 61,
      "errorRate": 0.152,
      "clientErrors": 0,
      "lastSeen": "2026-10-19T23:57:40.000Z",
      "latestVersion": "v2026.10.19"
    }
  ]
}

Endpoint trend, heatmap, regression and examples

Four operations do for one endpoint what the operation versions above do for one span operation. Instead of fingerprint and fpVersion, they take:

  • endpoint (query, string, required): The endpoint template, for example /v1/orders/{order_id}.

  • method (query, string, required): The HTTP method.

  • direction (query, string, default in): in or out.

Their other parameters and responses match the operation versions, without operation, statementText and dictionaryAvailable.

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/endpoints/trend

Like Span operation trend: p50, p95, p99, calls and errors over time.

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/endpoints/heatmap

Like Span operation heatmap.

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/endpoints/regression

Like Span operation regression, with pivotAt required.

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/endpoints/examples

Like Span operation examples: the slowest requests to the endpoint.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/endpoints/trend \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'endpoint=/v1/payments/{payment_id}/capture' \
  --data-urlencode 'method=POST' \
  --data-urlencode 'startTime=2026-10-19T13:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-19T16:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  endpoint: '/v1/payments/{payment_id}/capture',
  method: 'POST',
  startTime: '2026-10-19T13:00:00.000Z',
  endTime: '2026-10-19T16:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/endpoints/trend?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "ms",
  "step": { "stepSeconds": 120, "fromSeconds": 1792414800, "toSeconds": 1792425600, "firstBucketPartial": false, "lastBucketPartial": false },
  "points": [
    { "bucket": 1792418520, "calls": 4, "rows": 4, "errors": 3, "total": 15800, "p50": 3990, "p95": 4110, "p99": 4120 }
  ]
}

Rank regressions

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/regressions

Returns the operations or endpoints that got slower after a deploy time, ranked by regression score.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range (exclusive).

  • kind (query, string, default operation): operation or endpoint.

  • pivotAt (query, string): The deploy time. Defaults to the middle of the range.

  • direction (query, string, default in): With kind=endpoint, in or out.

  • endpoint (query, string): With kind=operation, only operations run by this endpoint.

  • types (query, string): With kind=operation, only these span types (comma-separated).

  • limit (query, integer, default 50): Results, 1 to 100.

  • minCalls (query, number, default 20): Ignore results with fewer estimated calls on either side.

  • minRelativeIncrease (query, number, default 0.1): The smallest p95 increase that counts.

Response

The common fields, orderBy, limit, minCalls, pivotAt, and points: entries shaped as in Rank span operations or Rank endpoints, each with regression.

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/regressions \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'kind=endpoint' \
  --data-urlencode 'pivotAt=2026-10-19T10:00:00.000Z' \
  --data-urlencode 'startTime=2026-10-18T10:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T10:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  kind: 'endpoint',
  pivotAt: '2026-10-19T10:00:00.000Z',
  startTime: '2026-10-18T10:00:00.000Z',
  endTime: '2026-10-20T10:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/regressions?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "ms",
  "orderBy": "regression",
  "limit": 50,
  "minCalls": 20,
  "pivotAt": "2026-10-19T10:00:00.000Z",
  "points": [
    {
      "endpoint": "/v1/payments/{payment_id}/capture",
      "method": "POST",
      "calls": 402,
      "p95": 3980,
      "errorRate": 0.152,
      "regression": {}
    }
  ]
}

Rank dependencies

GET https://api.apitraffic.io/v1/accounts/{accountSid}/apm/analytics/dependencies

Ranks what your API depends on (databases, caches, HTTP APIs and queues) by peer or by target, with latency and the mix of error types.

Query parameters

  • startTime (query, string, required): Start of the range.

  • endTime (query, string, required): End of the range (exclusive).

  • granularity (query, string, default peer): peer: one row per type, system, host and database. target: one row per table or outbound endpoint on it.

  • orderBy (query, string, default total): total, p95, calls, calls_per_request or error_rate.

  • endpoint (query, string): Only dependencies of this inbound endpoint.

  • types (query, string): Only these span types (comma-separated).

  • limit (query, integer, default 50): Results, 1 to 100.

  • minCalls (query, number, default 20): For calls_per_request and error_rate ranking, ignore dependencies with fewer estimated calls.

Response

The common fields, and points: type, system, host, db, target, op, calls, rows, total, avg, p50, p95, p99, max, errors, errorRate, lastSeen, latestVersion, sampledRequests, callsPerRequest and errorClasses (errors by class).

bash
curl -G https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/apm/analytics/dependencies \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  --data-urlencode 'types=http.out' \
  --data-urlencode 'orderBy=error_rate' \
  --data-urlencode 'startTime=2026-10-19T00:00:00.000Z' \
  --data-urlencode 'endTime=2026-10-20T00:00:00.000Z'
js
const accountSid = 'acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa';
const params = new URLSearchParams({
  types: 'http.out',
  orderBy: 'error_rate',
  startTime: '2026-10-19T00:00:00.000Z',
  endTime: '2026-10-20T00:00:00.000Z',
});
const response = await fetch(`https://api.apitraffic.io/v1/accounts/${accountSid}/apm/analytics/dependencies?${params}`, {
  headers: { Authorization: `Bearer ${process.env.APITRAFFIC_TOKEN}` },
});
const { points } = await response.json();
json
{
  "sourceState": "ready",
  "unit": "us",
  "orderBy": "error_rate",
  "points": [
    {
      "type": "http.out",
      "system": "http",
      "host": "payments.acme-pay.example",
      "db": "",
      "target": "",
      "op": "",
      "calls": 1020,
      "rows": 1020,
      "total": 612000000,
      "avg": 600000,
      "p50": 210000,
      "p95": 3990000,
      "p99": 4010000,
      "max": 4020000,
      "errors": 61,
      "errorRate": 0.0598,
      "lastSeen": "2026-10-19T23:57:40.000Z",
      "latestVersion": "v2026.10.19",
      "sampledRequests": 1020,
      "callsPerRequest": 1,
      "errorClasses": { "timeout": 47, "5xx": 14 }
    }
  ]
}

Errors

Status Code Meaning
400 1000 A parameter is missing or invalid, for example limit above 1000.
403 2221 The plan does not include APM.
502 5105 The query failed. Retry.
503 5102, 5103, 5104 Analytics are temporarily unavailable. Retry after Retry-After seconds.
504 5101 The query took too long. Narrow the range and retry.