Skip to content

Usage ​

2 endpoints. Every path below is relative to the API base URL and already includes the /api/v1 prefix — see conventions for authentication, pagination, errors and idempotency.

Endpoint
GET/billing/usageList raw usage events for a period with provider cost, platform fee, customer charge and margin
GET/billing/usage/summarySummarise usage for a period grouped by component, provider, model or call with cost and margin totals

Endpoints ​

List raw usage events for a period with provider cost, platform fee, customer charge and margin ​

GET/billing/usage
  • Requires billing.read.
  • Defaults to the last 30 days; component, provider, model, call_id, campaign_id and assistant_id accept repeated values. Malformed from/to yields a 500, not a 422.
bash
curl -X GET "$CALLAGENT_API_URL/billing/usage" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/billing/usage`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/billing/usage');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/billing/usage",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
403Neither the API key scope nor the session user's permission allows billing.read

Example response, generated from the schema:

json
{
  "data": [
    {
      "id": null,
      "call_id": "01JQ0000000000000000000000",
      "component": "string",
      "provider": "string",
      "model": "string",
      "billing_mode": "string",
      "quantity": "string",
      "unit": "string",
      "billable_units": "string",
      "currency": "string",
      "provider_cost": "string",
      "platform_fee": "string",
      "customer_charge": "string",
      "margin": "string",
      "is_free": true,
      "occurred_at": "2026-01-01T12:00:00+00:00"
    }
  ],
  "meta": {
    "current_page": 1,
    "per_page": 25,
    "total": 1,
    "last_page": 1,
    "from": "+40712345678",
    "to": "+40712345678"
  }
}

Summarise usage for a period grouped by component, provider, model or call with cost and margin totals ​

GET/billing/usage/summary
  • Requires billing.read.
  • An unrecognised by value silently falls back to component instead of failing. Malformed from/to yields a 500, not a 422.

Query parameters

NameTypeRequiredNotes
bystring—
bash
curl -X GET "$CALLAGENT_API_URL/billing/usage/summary?by=string" \
  -H "Authorization: Bearer $CALLAGENT_API_KEY" \
  -H "Accept: application/json"
js
const response = await fetch(`${process.env.CALLAGENT_API_URL}/billing/usage/summary?by=string`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${process.env.CALLAGENT_API_KEY}`,
    Accept: 'application/json',
  },
});

if (!response.ok) {
  const { error } = await response.json();
  throw new Error(`${error.type}: ${error.message}`);
}

const { data } = await response.json();
php
<?php

$handle = curl_init(getenv('CALLAGENT_API_URL') . '/billing/usage/summary?by=string');

curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('CALLAGENT_API_KEY'),
        'Accept: application/json',
    ],
]);

$body = json_decode(curl_exec($handle), true);
$status = curl_getinfo($handle, CURLINFO_HTTP_CODE);
curl_close($handle);

if ($status >= 400) {
    throw new RuntimeException("{$body['error']['type']}: {$body['error']['message']}");
}

$data = $body['data'];
python
import os, requests

response = requests.get(
    f"{os.environ['CALLAGENT_API_URL']}/billing/usage/summary?by=string",
    headers={"Authorization": f"Bearer {os.environ['CALLAGENT_API_KEY']}"},
    timeout=30,
)
response.raise_for_status()
data = response.json()["data"]

Responses

StatusBody
200data-wrapped array

Errors

StatusWhen it happens
403Neither the API key scope nor the session user's permission allows billing.read

Example response, generated from the schema:

json
{
  "data": [
    "string"
  ],
  "meta": {
    "by": "string",
    "from": "+40712345678",
    "to": "+40712345678"
  }
}

Documented against the code. Anything not yet implemented is labelled, never described as working.