---
title: "GetAgentUsageBreakdown"
description: "Break down project usage by agent credential"
canonical: "https://pgbeam.com/docs/go-sdk/agents/getAgentUsageBreakdown"
last-updated: "2026-10-19T19:34:59.000Z"
---

# GetAgentUsageBreakdown

> Break down project usage by agent credential

URL: https://pgbeam.com/docs/go-sdk/agents/getAgentUsageBreakdown

{/* Auto-generated from OpenAPI. Do not edit. Run `pnpm generate:sdk-docs` to regenerate. */}

Aggregates the audit trail into per-agent usage for a window: statements by decision, rows and bytes returned, the cache outcome breakdown, and latency percentiles. Read-only, derived entirely from entries the gateway already records.

Grouped by credential, not by session. `session_id` is 32 bits of randomness minted per connection, so it identifies a connection rather than an agent or a run, and at scale it collides; the credential is the only stable identity in the trail.

This endpoint reports usage and deliberately attributes no dollar figure to an agent. Overage is computed on the organization's total against a plan limit, so no single agent causes it independently of the others, and any per-agent split of that bill is a policy choice rather than a measurement. The organization's limits and marginal rates are returned alongside the usage so a caller can apply its own policy, with both meanings of a zero limit already resolved.

Three things are reported rather than assumed. Usage recorded against no credential is its own line, so agents plus unattributed equals totals exactly. Latency covers only entries that ran and carried a finite value: every refusal writes a literal zero because there was nothing to time, and counting those would drag an agent's percentiles toward zero in proportion to how often it was refused, so the heavily blocked agent would report the fastest queries. And gap markers left by undelivered entries set `complete` to false, since a total over a trail with holes in it is a floor, not a measurement.

Both `start` and `end` are optional. Omitting `end` means now; omitting `start` means 30 days before the end. The window is half-open and is capped at 92 days, because this aggregate reads every row in the window on the request path and an unbounded one would sort a year of latencies per group. `requested_start` and `requested_end` echo the window that was actually used, so a caller that pinned neither still knows what the totals cover.

## Usage

```go
result, err := client.Agents.GetAgentUsageBreakdown(ctx, "prj_xxx", nil)
```

## Parameters

| Parameter          | Type                                   | Required | Description                                                                                                                                                                                                                                                                                                                                             |
| ------------------ | -------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ctx                | `context.Context`                      | Yes      | Request context                                                                                                                                                                                                                                                                                                                                         |
| projectID          | `string`                               | Yes      | Unique project identifier (prefixed, e.g. prj_xxx).                                                                                                                                                                                                                                                                                                     |
| params             | `*pgbeam.GetAgentUsageBreakdownParams` | No       | Query and header parameters                                                                                                                                                                                                                                                                                                                             |
| params.Start       | `*time.Time`                           | No       | Return entries at or after this timestamp (inclusive lower bound).                                                                                                                                                                                                                                                                                      |
| params.End         | `*time.Time`                           | No       | Return entries strictly older than this timestamp (cursor / upper bound).                                                                                                                                                                                                                                                                               |
| params.IfNoneMatch | `*string`                              | No       | Entity tag the client already holds, taken from the `ETag` of an earlier response. When it still matches the current representation the server answers `304 Not Modified` with no body, so a poll that finds nothing changed costs a round trip rather than a transfer. A comma-separated list is accepted, and `*` matches any current representation. |

## Response

`(*pgbeam.AgentUsageReport, error)`: per-agent usage for the window.

## Example

```go
import pgbeam "go.pgbeam.com/sdk"

client := pgbeam.NewClient(&pgbeam.ClientOptions{
  APIKey: "pbu_...",
})

result, err := client.Agents.GetAgentUsageBreakdown(ctx, "prj_xxx", &pgbeam.GetAgentUsageBreakdownParams{})
if err != nil {
  log.Fatal(err)
}
fmt.Println(result)
```

## Errors

| Status | Description                                                                                                                                                                                                                                                                                           |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 400    | The request was rejected. `code` is `INVALID_INPUT`, and `errors` names the offending fields when the failure was a validation one.                                                                                                                                                                   |
| 401    | Missing or invalid authentication. `code` is `UNAUTHORIZED`.                                                                                                                                                                                                                                          |
| 403    | The caller is authenticated but not allowed to perform this operation. `code` is `FORBIDDEN` when the caller's role is insufficient, and `PLAN_LIMIT_REACHED` when the organization's plan is what stands in the way. The two are answered differently, so branch on the code rather than the status. |
| 404    | The resource does not exist, or the caller is not entitled to know that it does. `code` is `NOT_FOUND`.                                                                                                                                                                                               |
| 429    | Rate limited. `code` is `RATE_LIMITED`.                                                                                                                                                                                                                                                               |
| 500    | The request failed for a reason on our side. `code` is `INTERNAL_ERROR`. Quote `request_id` when reporting it.                                                                                                                                                                                        |