> ## Documentation Index
> Fetch the complete documentation index at: https://docs.starleads.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Track Consumption

> Build automated balance monitoring on the Starleads API: read your current credit balance, raise an alert when it drops below a threshold, then drill into a channel/month/agent breakdown to understand where the credits went.

## Introduction

Starleads bills your usage in **credits**. Every billing period comes with a pool of included credits; each voice call, SMS or other billable action draws it down. When the pool runs low your agents stop working, so you want to know *before* it happens -- not after.

This guide shows you how to build a complete **balance-monitoring loop** on top of the public API using a single API key:

1. Read your **current balance** with `GET /Consumption`.
2. Decide whether to **alert** based on the remaining credits, the usage percentage, and the subscription status.
3. When usage is high, **drill down** with `GET /Consumption/breakdown` to see which channels, months and agents consumed the credits.

Everything below relies only on your API key passed in the `X-Api-Key` header. The company is derived from the key -- you never pass a company identifier. Figures are reported **as-is**: a negative remaining balance or a usage above 100% is published verbatim, so your monitoring can react to overage instead of seeing a clamped `0`.

<Note>These billing endpoints expose company-wide data (balance, breakdown, contract and ledger). Any holder of your API key can read them. See the [Authentication guide](/documentation/authentification) before sharing keys.</Note>

## Getting Started

<Steps>
  <Step title="Read the current balance" icon="gauge">
    Call `GET /Consumption` to get the balance for the **current billing period**. The response tells you how many credits were included, how many were consumed, how many remain, and when the period ends -- the end date is when your credits recharge.

    Read these fields:

    | Field              | Type            | Meaning                                                                                            |
    | ------------------ | --------------- | -------------------------------------------------------------------------------------------------- |
    | `includedCredits`  | number          | Credits granted for the current billing period.                                                    |
    | `consumedCredits`  | number          | Credits already consumed in the period.                                                            |
    | `remainingCredits` | number          | Credits left. Published as-is, **including negative values** when you overshoot.                   |
    | `usagePercent`     | number          | Consumption as a percentage of `includedCredits`. Published as-is, **including values above 100**. |
    | `periodStart`      | date-time (UTC) | Start of the current billing period.                                                               |
    | `periodEnd`        | date-time (UTC) | End of the current period -- the date your credits recharge.                                       |
    | `status`           | string          | Subscription status: `Active`, `PastDue`, `Paused`, `Cancelled`.                                   |

    <Note>If the company has no active subscription, this endpoint returns **404**, not a zeroed balance. Treat 404 as "no subscription to monitor", not as "zero credits left".</Note>

    **Endpoint**: `GET /Consumption`
  </Step>

  <Step title="Decide whether to alert" icon="bell">
    With the balance in hand, apply your own alerting rules. A robust monitor checks three things, in order:

    1. **Status first.** If `status` is not `Active` (e.g. `PastDue`, `Paused`, `Cancelled`), alert regardless of the numbers -- billing may already be interrupted.
    2. **Threshold on the balance.** Alert when `remainingCredits` drops below a floor you choose (for example 500 credits), or when `usagePercent` crosses a ceiling (for example 80%). Use whichever expresses your budget best; `usagePercent` is convenient because it is normalised across plans.
    3. **Overage.** A negative `remainingCredits` (or `usagePercent > 100`) means you are already over the included pool. Escalate this separately from a simple "running low" warning.

    Because `periodEnd` is the recharge date, you can also tell the difference between "low but the period resets tomorrow" and "low with two weeks to go".

    **No new endpoint here** -- this step is pure logic on the response from step 1.
  </Step>

  <Step title="Drill into the breakdown" icon="magnifying-glass-chart">
    When an alert fires (or on a schedule, e.g. weekly), call `GET /Consumption/breakdown` over a date range to understand *where* the credits went. The response splits the total three ways -- **by channel**, **by month**, and **by agent** (each agent with its own per-campaign breakdown).

    The range is passed as `from` and `to` query parameters (both inclusive, UTC). It is **mandatory**, must be ordered (`to` after `from`), and may span **at most 366 days**. A range with no consumption returns a total of `0`, not an error.

    Each of the three axes sums exactly to `totalCredits`. If the upstream total ever exceeds the sum of the itemised entries, a residual entry is added on each axis so nothing disappears: channel `"unattributed"`, month `"unattributed"`, or an agent with `agentId: null` and `nameStatus: "Unattributed"`. A deleted agent is still reported, with `nameStatus: "Deleted"`, so its credits are never silently dropped.

    Read these fields:

    | Field                   | Type           | Meaning                                                              |
    | ----------------------- | -------------- | -------------------------------------------------------------------- |
    | `totalCredits`          | number         | Total credits consumed over the range. Each axis below sums to this. |
    | `byChannel[].channel`   | string         | Channel identifier (e.g. `voice`, `sms`), or `"unattributed"`.       |
    | `byChannel[].credits`   | number         | Credits consumed on that channel.                                    |
    | `byMonth[].month`       | string         | Month in `YYYY-MM` form, or `"unattributed"`.                        |
    | `byMonth[].credits`     | number         | Credits consumed in that month.                                      |
    | `byAgent[].agentId`     | string \| null | Agent identifier. `null` for a deleted agent or the residual.        |
    | `byAgent[].nameStatus`  | string         | `Active`, `Deleted`, or `Unattributed`.                              |
    | `byAgent[].credits`     | number         | Credits consumed by that agent.                                      |
    | `byAgent[].campaigns[]` | array          | Per-campaign breakdown for the agent (`campaignId`, `credits`).      |

    **Endpoint**: `GET /Consumption/breakdown?from=...&to=...`
  </Step>
</Steps>

## Code Examples

The examples below assemble the three steps into one runnable monitor. Set `THRESHOLD_CREDITS` and `THRESHOLD_PERCENT` to match your budget.

### Read the current balance

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://api.starleads.co/Consumption \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  API_KEY = "YOUR_API_KEY"
  BASE_URL = "https://api.starleads.co"

  def get_balance():
      response = requests.get(
          f"{BASE_URL}/Consumption",
          headers={"X-Api-Key": API_KEY},
      )
      if response.status_code == 404:
          raise RuntimeError("No active subscription to monitor.")
      response.raise_for_status()
      return response.json()

  balance = get_balance()
  print(f"Remaining: {balance['remainingCredits']} ({balance['usagePercent']}% used)")
  print(f"Status: {balance['status']}, recharges on {balance['periodEnd']}")
  ```
</CodeGroup>

### Decide whether to alert

<CodeGroup>
  ```bash cURL theme={null}
  # Fetch the balance, then evaluate the alert rules with jq.
  curl -s -X GET https://api.starleads.co/Consumption \
    -H "X-Api-Key: YOUR_API_KEY" \
  | jq '
      if .status != "Active" then "ALERT: subscription is \(.status)"
      elif .remainingCredits < 500 then "ALERT: only \(.remainingCredits) credits left"
      elif .usagePercent >= 80 then "ALERT: \(.usagePercent)% of credits used"
      else "OK"
      end
    '
  ```

  ```python Python theme={null}
  THRESHOLD_CREDITS = 500      # alert when fewer credits remain
  THRESHOLD_PERCENT = 80       # alert when usage crosses this percentage

  def should_alert(balance):
      if balance["status"] != "Active":
          return f"Subscription is {balance['status']}"
      if balance["remainingCredits"] < 0:
          return f"Overage: {balance['remainingCredits']} credits (over the included pool)"
      if balance["remainingCredits"] < THRESHOLD_CREDITS:
          return f"Low balance: {balance['remainingCredits']} credits remaining"
      if balance["usagePercent"] >= THRESHOLD_PERCENT:
          return f"High usage: {balance['usagePercent']}% of credits consumed"
      return None

  reason = should_alert(balance)
  if reason:
      print(f"ALERT -- {reason} (period ends {balance['periodEnd']})")
  else:
      print("Balance is healthy.")
  ```
</CodeGroup>

### Drill into the breakdown

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://api.starleads.co/Consumption/breakdown?from=2026-01-01&to=2026-01-31" \
    -H "X-Api-Key: YOUR_API_KEY"
  ```

  ```python Python theme={null}
  from datetime import date, timedelta

  def get_breakdown(from_date, to_date):
      response = requests.get(
          f"{BASE_URL}/Consumption/breakdown",
          headers={"X-Api-Key": API_KEY},
          params={"from": from_date.isoformat(), "to": to_date.isoformat()},
      )
      response.raise_for_status()
      return response.json()

  # When an alert fires, look at the last 30 days to see where credits went.
  if reason:
      today = date.today()
      breakdown = get_breakdown(today - timedelta(days=30), today)

      print(f"Total consumed: {breakdown['totalCredits']}")

      print("By channel:")
      for row in breakdown["byChannel"]:
          print(f"  {row['channel']}: {row['credits']}")

      print("Top agents:")
      top = sorted(breakdown["byAgent"], key=lambda a: a["credits"], reverse=True)
      for agent in top[:5]:
          label = agent["agentId"] or agent["nameStatus"]
          print(f"  {label} ({agent['nameStatus']}): {agent['credits']}")
  ```
</CodeGroup>

### Putting it together

<CodeGroup>
  ```python Python theme={null}
  from datetime import date, timedelta

  def monitor():
      balance = get_balance()
      reason = should_alert(balance)
      if not reason:
          return

      # Alert is firing -- attach a 30-day breakdown for context.
      today = date.today()
      breakdown = get_breakdown(today - timedelta(days=30), today)
      top_channel = max(breakdown["byChannel"], key=lambda c: c["credits"], default=None)

      message = (
          f"[Starleads] {reason}. "
          f"Remaining: {balance['remainingCredits']} credits, "
          f"period ends {balance['periodEnd']}."
      )
      if top_channel:
          message += f" Biggest driver (30d): {top_channel['channel']} = {top_channel['credits']} credits."

      # Send `message` to your alerting channel (email, Slack, PagerDuty, ...).
      print(message)

  monitor()
  ```
</CodeGroup>

<Tip>Run `monitor()` on a schedule (e.g. every hour via cron). `GET /Consumption` is rate-limited to 30 requests per minute and `GET /Consumption/breakdown` to 10 per minute, which is ample for periodic monitoring.</Tip>

## Going Further

* **Audit the ledger.** To see the individual credit movements behind the totals -- one line per debit, credit, adjustment or refund -- use `GET /Consumption/transactions`. It is paginated with the standard `pageNumber` / `pageSize` convention.
* **Inspect your plan and limits.** `GET /Subscription` returns your plan name, subscription status, active features and effective limits, so a monitor can also flag when you are close to a contractual limit. No pricing information is exposed.

## API Reference

Explore all consumption and subscription endpoints:

<CardGroup cols={2}>
  <Card title="Current consumption" icon="gauge" href="/api-reference/consumption/get-current-consumption">
    Read the credit balance for the current billing period.
  </Card>

  <Card title="Consumption breakdown" icon="chart-pie" href="/api-reference/consumption/get-consumption-breakdown">
    Split consumption by channel, month and agent over a date range.
  </Card>

  <Card title="Consumption transactions" icon="receipt" href="/api-reference/consumption/get-consumption-transactions">
    List the individual credit ledger entries, paginated.
  </Card>

  <Card title="Subscription contract" icon="file-contract" href="/api-reference/subscription/get-subscription-contract">
    Read your plan, status, active features and effective limits.
  </Card>
</CardGroup>
