curl --request GET \
--url https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution', 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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"as_of": "2026-08-14T18:00:00Z",
"buckets": {
"Upload": {
"label": "Uploading (batch)",
"windows": {
"86400": {
"cap": 2000,
"entries": [
{
"credential_id": "cred_1a2b3c4d",
"credential_name": "Acme Outbound",
"pct_of_used": 77.8,
"used": 700
},
{
"pct_of_used": 22.2,
"used": 200
}
],
"used": 900
}
}
}
},
"tenancy_id": "ten_9f2c1a7b3d4e5f60"
}{
"detail": "Authentication required"
}{
"detail": "Domain not found"
}{
"detail": "margins['Upload'] must be between 1 and 100"
}{
"detail": "Rate limit exceeded: 100 per 1 minute"
}Read per-credential budget attribution for a Domain
Read which of your credentials spent this Domain’s provider budget — every rate bucket and every window (per-minute, hourly and daily) in one request. Several credentials can point at the same Domain and they all draw on ONE shared allowance, so this is what answers “which credential lane is consuming the budget?”.
Each window carries an entry per credential plus one entry whose credential_id is null: the UNATTRIBUTED remainder. That entry is expected and is not an error. Two things land in it — other systems can spend the same Domain’s provider budget without going through this platform at all, and a small number of this platform’s own calls are made outside the paced dispatch path (testing a credential, for example) and are not attributed. Because the remainder is always present, pct_of_used totals 100 within every window, and the spend nobody can attribute stays visible instead of being quietly spread across your credentials.
Display names are resolved when you read, so a renamed credential is never stale. A credential you have since DELETED keeps its row with a credential_name of null — the calls were really made, and dropping the row would move real spend out of the total.
Like every budget surface here this is a live projection of the quota ledger and never a reservation. as_of is when the counters were read and is null for a Domain that has never dispatched. Readable by any organization member. Cross-tenant access returns 404, never 403.
curl --request GET \
--url https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution"
headers = {"X-API-Key": "<api-key>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {'X-API-Key': '<api-key>'}};
fetch('https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution', 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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"X-API-Key: <api-key>"
],
]);
$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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("X-API-Key", "<api-key>")
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.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getdialed.ai/v1/platforms/five9/domains/{tenancy_id}/attribution")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["X-API-Key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"as_of": "2026-08-14T18:00:00Z",
"buckets": {
"Upload": {
"label": "Uploading (batch)",
"windows": {
"86400": {
"cap": 2000,
"entries": [
{
"credential_id": "cred_1a2b3c4d",
"credential_name": "Acme Outbound",
"pct_of_used": 77.8,
"used": 700
},
{
"pct_of_used": 22.2,
"used": 200
}
],
"used": 900
}
}
}
},
"tenancy_id": "ten_9f2c1a7b3d4e5f60"
}{
"detail": "Authentication required"
}{
"detail": "Domain not found"
}{
"detail": "margins['Upload'] must be between 1 and 100"
}{
"detail": "Rate limit exceeded: 100 per 1 minute"
}Authorizations
Path Parameters
Response
Successful Response
Which credentials spent one Five9 Domain's provider budget.
Several credentials can resolve to the same Domain and they all draw on ONE shared provider budget, so this breaks each window's spend down by the credential that caused it.
An unattributed entry — an entry whose credential_id is null — is
EXPECTED and is not an error. Two things land there. Other systems can spend
the same Domain's provider budget without going through this platform at all,
and a small number of this platform's own calls are made outside the paced
dispatch path (for example when you test a credential), which are not
attributed. Showing the remainder explicitly is what keeps the percentages
honest: they always total 100, and the part nobody can attribute stays
visible rather than being silently spread across your credentials.