Billing consumption
curl --request GET \
--url https://api.goyappr.com/billing/consumption \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.goyappr.com/billing/consumption"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.goyappr.com/billing/consumption', 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.goyappr.com/billing/consumption",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.goyappr.com/billing/consumption"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.goyappr.com/billing/consumption")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/billing/consumption")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z",
"group_by": "<string>",
"data": [
{
"period": "2026-05-07",
"product": "voice_call",
"total_amount_cents": 123,
"count": 123,
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"input_tokens": 34645047,
"output_tokens": 205402,
"total_tokens": 34850449
}
]
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Billing
Billing Consumption
Aggregated negative-balance debits from your credit account, bucketed by date and
product. Useful for usage dashboards, monthly invoice reconciliation, and anomaly
detection. Required scope billing:read.
By default, top-ups (positive credits) are excluded — pass include_topups=true to
include them.
GET
/
billing
/
consumption
Billing consumption
curl --request GET \
--url https://api.goyappr.com/billing/consumption \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.goyappr.com/billing/consumption"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.goyappr.com/billing/consumption', 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.goyappr.com/billing/consumption",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>"
],
]);
$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.goyappr.com/billing/consumption"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
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.goyappr.com/billing/consumption")
.header("Authorization", "Bearer <token>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/billing/consumption")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <token>'
response = http.request(request)
puts response.read_body{
"from": "2023-11-07T05:31:56Z",
"to": "2023-11-07T05:31:56Z",
"group_by": "<string>",
"data": [
{
"period": "2026-05-07",
"product": "voice_call",
"total_amount_cents": 123,
"count": 123,
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"input_tokens": 34645047,
"output_tokens": 205402,
"total_tokens": 34850449
}
]
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Aggregated debits from your credit account, bucketed by date and product. Useful for usage dashboards, monthly reconciliation, and anomaly detection.
By default, top-ups are excluded — pass
Input dominates output by a wide margin on evals — often 150:1. That’s expected: the agent’s conversation context is re-sent on every turn, so a long case accumulates input tokens quadratically while output stays roughly constant per turn. If a suite is costing more than you expect, the lever is usually case length and prompt size, not the number of runs.
include_topups=true to fold them in for full statement parity.
Common queries
# This month's voice-call spend, day by day
curl "https://api.goyappr.com/billing/consumption?from=2026-05-01T00:00:00Z&group_by=day&product=voice_call" \
-H "Authorization: Bearer $YAPPR_API_KEY"
# Eval spend for the year, monthly
curl "https://api.goyappr.com/billing/consumption?from=2026-01-01T00:00:00Z&group_by=month&product=eval_run" \
-H "Authorization: Bearer $YAPPR_API_KEY"
# Per-agent voice-call spend last 30 days
curl "https://api.goyappr.com/billing/consumption?group_by=agent&product=voice_call" \
-H "Authorization: Bearer $YAPPR_API_KEY"
# Total spend for one specific suite_run (no native filter — query eval_runs and sum)
# (use `GET /agent-eval/runs?suite_run_id=...` and sum `total_cost_cents` client-side)
Products
| Product | What it covers |
|---|---|
voice_call | Paid call minutes (inbound + outbound + web). Per-agent grouping populates here. |
eval_run | Agent-eval runs. |
phone_number | Monthly number rent. |
topup | Positive credit purchases. Excluded by default. |
refund | Reverse charges (negative). |
Token usage
Buckets for token-metered products carryinput_tokens, output_tokens and total_tokens alongside the amount. Today that means eval_run — eval charges are a direct function of tokens consumed, so these fields are what explain a given line.
Products that don’t meter tokens omit these fields entirely rather than returning 0, so total_tokens being absent means “not applicable here”, never “nothing was used”.
curl "https://api.goyappr.com/billing/consumption?group_by=day&product=eval_run" \
-H "Authorization: Bearer $YAPPR_API_KEY"
{
"data": [
{
"period": "2026-08-13",
"product": "eval_run",
"total_amount_cents": 7448,
"count": 328,
"input_tokens": 34645047,
"output_tokens": 205402,
"total_tokens": 34850449
}
],
"range": { "from": "...", "to": "...", "group_by": "day", "product": "eval_run" }
}
Authorizations
Your Yappr API key (e.g. ypr_live_...). Generate one in the dashboard under Settings → API Keys.
Query Parameters
Start of the window. Defaults to 30 days ago.
End of the window (exclusive). Defaults to now.
Bucket granularity. agent returns one row per agent_id (currently only populated for voice_call).
Available options:
day, month, total, agent Filter to a single product category.
Available options:
voice_call, eval_run, phone_number, topup, refund