Overview
GET /v2/dial_metrics is in development and can change before general availability.GET /v2/dial_metrics returns the outbound dial rate your account produced through the Voice API Dial command and TeXML, next to the dials-per-second limit in force at the time. Use it to chart dial volume, see when the limit rejected dials, and size a limit increase request.
Each dial_metric record is one bucket: one region, one time interval. Results are newest first by default; see Sort order.
Choose a granularity
granularity is required. It sets the bucket size and the history available.
A request whose
start_time is older than the retention window of its granularity fails with 422 and error code 10033. The response does not return empty data.
start_time is inclusive and end_time is exclusive. A bucket is returned when it starts inside that range. Both are ISO 8601 date-times, for example 2026-09-29T12:00:00.000Z.
Read the live rate
There is no separate “current” endpoint. The live rate is the newestgranularity=second record of each region. Request the last two minutes newest first:
date -v-2M form is macOS. On Linux use date -u -d '2 minutes ago' +%Y-%m-%dT%H:%M:%SZ. Records come newest first, so the first record for each region is that region’s live rate. Do not use page[limit]=1: it returns a single record, and with traffic in more than one region it hides the others. A region with no record in the window has a live rate of 0.
Telnyx counts a 5-second window only after every call-processing node has reported it, about 15 seconds after the window closes. The newest record is therefore about 20 seconds old. The same rule applies to every granularity: an in-progress minute or hour contains complete 5-second windows only.
Sort order
sort takes -start_time (default, newest first) or start_time (oldest first). region follows the same direction for records with the same start_time. Any other value returns 422 with error code 10032 and source.parameter set to sort. The response echoes the applied value in meta.sort.
Missing buckets are zero
The API returns only buckets in which at least one dial occurred. Treat a missing bucket as zero dials and 0 DPS. If nosecond record exists for the last minute or so, the live rate is 0.
Compare peak DPS with the limit
For each bucket:dials.total,average_dps, andpeak_dpscount every dial attempt, rejected ones included.average_dpsisdials.totaldivided by the bucket duration, rounded to 4 decimal places.peak_dpsis the busiest 5-second window in the bucket, rounded to 4 decimal places, with all call-processing nodes of the region added together first. Forgranularity=secondit equalsaverage_dps.dps_limitis the limit in force during that busiest window.nullmeans unlimited.
peak_dps and dps_limit describe the same window, compare them directly. peak_dps above dps_limit is expected when dials were rejected. dials.rejected.dps_limit is the authoritative signal: if it is above 0, dials in that bucket were rejected by the DPS limit. Do not compare average_dps with dps_limit: bursts hide inside the average.
Dials rejected by a limit are still counted in dials.total. dials.rejected splits them by dps_limit, hourly_limit, and daily_limit.
How the limit is enforced
Telnyx enforces your DPS limit per region over fixed 5-second windows: a window allowsdps_limit × 5 dial attempts. Several call-processing nodes share each region’s limit, and they exchange their counts with a short delay. Near the limit, a few dials can therefore be rejected while a window’s total is just under dps_limit × 5, or accepted while it is just over. The counts this API returns are exact; only enforcement at the threshold is approximate. To avoid rejections, pace dials with headroom below your limit instead of at it. See Dials Per Second Limit for the default limit and how to raise it.
Regions are not summed
region is a string. Current values are us, eu, australia, middle_east, canada, and india. Telnyx can add values, so your client must tolerate regions it does not recognize.
The DPS limit is enforced per region, so the API returns one record per region per bucket, ordered by start_time and then region. Do not add records of different regions together: the sum can exceed every limit without any dial being rejected, and no limit applies to it. Group by region and compare each series with its own dps_limit.
Paginate
Results are cursor paginated.page[limit] defaults to 1,000 and is clamped to 1-10,000. The response carries no total count.
When more records follow, meta.next holds the path of the next page and meta.cursors.after holds its cursor. On the last page meta.cursors is empty and meta.next is absent. Treat cursors as opaque.
If page[after] matches no records, the response is an empty page, not an error. meta.cursors.after and meta.cursors.before both echo the cursor you sent.
data, and request meta.next until it is absent.
Errors
Errors use the standarderrors array, with source.parameter naming the field at fault.
401, code10009: authentication failed.422, code10004:granularity,start_time, orend_timeis missing.422, code10032:granularityis notsecond,minute, orhour, orsortis not-start_timeorstart_time.422, code10026: a date-time,page[limit], orpage[after]is invalid.422, code10033:end_timeis not afterstart_time, orstart_timeis outside the retention window.404, code10005: the route does not exist.429: the API request rate limit was exceeded. Responses carry theX-RateLimit-*headers and, when supplied,Retry-After. See API rate limiting.500, code10007: unexpected error.
Rate limits
Requests to this endpoint are rate limited per user. Above the limit the API returns429 with error code 10011; every response carries the X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers, so read them instead of hard-coding a limit. New data arrives every 5 seconds, so polling the live rate more often than that returns nothing new. See API rate limiting for how to back off.
Related
- Dials Per Second Limit — default limit, how it is calculated, and how to raise it.
- API errors — general error format and codes.