curl --request GET \
--url https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts"
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts', 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.clarityq.ai/api/v1/products/{product_id}/usage/prompts",
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts"
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts")
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{
"start_date": "2023-12-25",
"end_date": "2023-12-25",
"total_prompts": 123,
"breakdown_by": [
"user"
],
"unit": "PROMPTS",
"total_cqt": 123,
"rows": [
{
"product_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"product_name": "<string>",
"prompt_count": 123,
"user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"user_email": "<string>",
"origin": "APP",
"usage_type": "ASK_ANYTHING",
"task_id": "<string>",
"task_name": "<string>",
"date": "2023-12-25",
"cqt": 123
}
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Get Prompt Usage
Return prompt usage for the organization that owns the given product as flat count buckets, always grouped by product. Use the repeatable breakdown_by parameter to control dimensions (user, origin, usage_type, date); by default counts are broken down by origin, aggregated over the whole window. Use usage_type to attribute prompts to the channel that produced them (TASK for scheduled tasks, ASK_ANYTHING, BUILDER, API, SLACK, EMBED, DIAGNOSIS), or task for one row per scheduled task, carrying the task’s own id and name. Both are served from the metering ledger and cannot be combined with origin, and both state the organization’s billing unit: an organization billed in CQT reads the cqt fields, one billed in prompts reads prompt_count and gets no cqt at all. The API key authorizes its own product, but the response covers every product in that organization so a single key gives org-wide visibility. Counts cover all prompt origins unless the origin parameter is supplied. Requires prompt usage tracking to be enabled for the organization. Dates are optional and default to the last 30 days.
curl --request GET \
--url https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts \
--header 'X-API-Key: <api-key>'import requests
url = "https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts"
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts', 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.clarityq.ai/api/v1/products/{product_id}/usage/prompts",
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts"
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.clarityq.ai/api/v1/products/{product_id}/usage/prompts")
.header("X-API-Key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.clarityq.ai/api/v1/products/{product_id}/usage/prompts")
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{
"start_date": "2023-12-25",
"end_date": "2023-12-25",
"total_prompts": 123,
"breakdown_by": [
"user"
],
"unit": "PROMPTS",
"total_cqt": 123,
"rows": [
{
"product_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"product_name": "<string>",
"prompt_count": 123,
"user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"user_email": "<string>",
"origin": "APP",
"usage_type": "ASK_ANYTHING",
"task_id": "<string>",
"task_name": "<string>",
"date": "2023-12-25",
"cqt": 123
}
]
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}breakdown_by parameter to control dimensions —
user, origin (APP, SLACK or API_KEY), usage_type and task (both below) and date
(UTC calendar day). By default counts are broken down by origin, aggregated over the whole
window.
Your API key authorizes its own product, but the response covers every product in that
organization, so a single key gives org-wide visibility. Requires prompt usage tracking to
be enabled for your organization.
Both dates are optional: end_date defaults to today (UTC) and start_date to 30 days
before end_date, so calling with no date parameters returns the last 30 days. The response
always echoes the resolved window.
Dimension fields appear on rows only when the matching breakdown_by value was requested.
GET /api/v1/products/{product_id}/usage/prompts
?start_date=2026-05-01&end_date=2026-05-31
&breakdown_by=user&breakdown_by=origin
{
"start_date": "2026-05-01",
"end_date": "2026-05-31",
"breakdown_by": ["user", "origin"],
"total_prompts": 12,
"rows": [
{
"product_id": "00000000-0000-0000-0000-000000000000",
"product_name": "Acme Analytics",
"user_id": "11111111-1111-1111-1111-111111111111",
"user_email": "jane@acme.com",
"origin": "APP",
"prompt_count": 12
}
]
}
Attributing usage to scheduled tasks
origin tells you how a prompt arrived — from the app, from Slack, or through an API key. It
does not tell you what produced it: a scheduled task runs under its owner and is reported as
APP, indistinguishable from that person typing a question.
Break down by usage_type instead to attribute usage to the channel that produced it:
| Value | What it covers |
|---|---|
TASK | Scheduled task runs |
ASK_ANYTHING | Questions asked in the app |
BUILDER | Context layer work in the app |
API | Questions sent through the API |
SLACK | Questions asked in Slack |
EMBED | Questions asked in an embedded analyst |
DIAGNOSIS | Automatic root-cause runs on a negatively rated answer |
date or user as usual, and add the usage_type query parameter to narrow
to a single value. Those seven are the values that carry prompts; BACKGROUND exists as a usage
type but is never a billable prompt, so filtering on it returns 422 rather than an empty
response.
GET /api/v1/products/{product_id}/usage/prompts
?start_date=2026-05-01&end_date=2026-05-31
&breakdown_by=usage_type&breakdown_by=date
&usage_type=TASK
{
"start_date": "2026-05-01",
"end_date": "2026-05-31",
"breakdown_by": ["usage_type", "date"],
"total_prompts": 5,
"unit": "PROMPTS",
"rows": [
{
"product_id": "00000000-0000-0000-0000-000000000000",
"product_name": "Acme Analytics",
"usage_type": "TASK",
"date": "2026-05-01",
"prompt_count": 4
},
{
"product_id": "00000000-0000-0000-0000-000000000000",
"product_name": "Acme Analytics",
"usage_type": "TASK",
"date": "2026-05-02",
"prompt_count": 1
}
]
}
One row per scheduled task
usage_type tells you how much came from scheduled tasks. breakdown_by=task tells you which
task: one row each, carrying the task’s own id and name.
GET /api/v1/products/{product_id}/usage/prompts
?start_date=2026-05-01&end_date=2026-05-31
&breakdown_by=task
{
"start_date": "2026-05-01",
"end_date": "2026-05-31",
"breakdown_by": ["task"],
"total_prompts": 3,
"unit": "CQT",
"total_cqt": 340,
"rows": [
{
"product_id": "00000000-0000-0000-0000-000000000000",
"product_name": "Acme Analytics",
"task_id": "task-Ab3xY9Kq2Z",
"task_name": "Yesterday's Ads ARPU Report",
"prompt_count": 2,
"cqt": 300
},
{
"product_id": "00000000-0000-0000-0000-000000000000",
"product_name": "Acme Analytics",
"task_id": "task-7Rt2Wm5Pd1",
"task_name": "Weekly Retention",
"prompt_count": 1,
"cqt": 40
}
]
}
date or user to split it further.
task_id matches the id of the task in the Tasks API, so these counts join straight onto your
own list of scheduled tasks.
breakdown_by=task covers scheduled task runs only — nothing else has a task to be attributed
to. A usage_type filter that contradicts that (anything other than TASK) returns 422.origin cannot be combined with usage_type or task in one request — they are measured
separately and their totals are not guaranteed to match to the prompt. Asking for both returns
422.Which number to read
Ausage_type or task breakdown states your organization’s billing unit in unit:
PROMPTS— readprompt_counton each row andtotal_promptson the response.CQT— readcqton each row andtotal_cqton the response. Rows still carryprompt_count, but CQT is what you are billed on. Usage from before your organization moved to CQT billing is never included, so a window that starts earlier is reported from the switch date onwards and the response echoes the adjustedstart_date.
cqt and total_cqt are omitted entirely for organizations billed in prompts.Authorizations
API key obtained from the ClarityQ dashboard.
Path Parameters
Query Parameters
First UTC calendar day to include (YYYY-MM-DD). Defaults to 30 days before end_date.
Last UTC calendar day to include, inclusive (YYYY-MM-DD). Defaults to today (UTC).
Dimensions to break the counts down by (repeatable): user, origin, usage_type, task, date. Product is always included. Defaults to origin. origin cannot be combined with usage_type or task. task covers scheduled task runs only.
Extra dimensions a prompt usage row can be broken down by (product is always included).
user, origin, usage_type, task, date Restrict to these products in the org (repeatable). Defaults to all products.
Restrict to these users (repeatable). Defaults to all users.
Filter to users whose email or full name contains this text.
Restrict to a single prompt origin (APP, SLACK, API_KEY). Defaults to all origins. Channel a prompt was sent through, used to filter the usage export.
APP, SLACK, API_KEY, EMBED, DIAGNOSIS Restrict to a single usage type (TASK, ASK_ANYTHING, BUILDER, API, SLACK, EMBED, DIAGNOSIS). Requires breakdown_by=usage_type. Defaults to all types. BACKGROUND carries no prompts and is rejected. Closed, ordered enum. The FE hard-codes column order and colors from it.
ASK_ANYTHING, BUILDER, EMBED, SLACK, API, TASK, DIAGNOSIS, BACKGROUND Response
Successful Response
Org-wide prompt usage for a date window, one row per requested dimension combination.
First UTC calendar day included in the window (YYYY-MM-DD)
Last UTC calendar day included in the window, inclusive (YYYY-MM-DD)
Total prompts across all rows in the response
Extra dimensions the rows are broken down by (product is always included)
Extra dimensions a prompt usage row can be broken down by (product is always included).
user, origin, usage_type, task, date The org's billing unit. CQT orgs should read cqt; prompt-billed orgs read prompt_count. Stated on a usage_type breakdown only
PROMPTS, CQT Total CQT across all rows. Present only for an org billed in CQT
Prompt-count buckets, one per product and requested dimension combination
Show child attributes
Show child attributes