Composer 2.5 Usage in Admin Usage Events Data API

We are using the Admin Get Usage Event Data API (/teams/filtered-usage-events) to pull per-conversation usage for internal cost tracking, keyed by conversationId.

For included models like Grok 4.5, this works and returns usage events back with kind = “Included in Business” even while we’re still under our monthly included limit.

For Composer 2.5, we get no such usage events for a conversation while under the included limit .

Questions:

  1. Is this the intended behavior — are Composer 2.5 usage events only emitted once billing starts?
  2. Is there any setting (team/admin config, or a parameter on the endpoint) that surfaces included Composer 2.5 usage while still under quota?
  3. If not, is there another way to retrieve usage for a given conversationId?

Thanks :slight_smile:

Hi @Chris_Bowers Thanks for the post! Lot of info to share but hope this is helpful:

Q1. No, Composer 2.5 events aren’t held back until billing starts. A usage event is emitted for every request regardless of billing state, and Composer 2.5 isn’t treated differently from Grok 4.5 on that path. What varies is the kind field, which reflects the billing outcome of that individual request: Included in Business while the member’s included allowance covers it, Usage-based once a request is served on demand, and values like Errored, Not Charged for failures.

Q2. There’s no team setting or endpoint parameter that changes this, and nothing is withheld while you’re under quota.

Q3. /teams/filtered-usage-events is still the right endpoint. There are three things about the integration that would each produce exactly what you’re seeing, so they’re worth ruling out first:

  1. Composer 2.5 records under two model strings. You’ll see both composer-2.5 and composer-2.5-fast in the model field, returned verbatim. An exact match on composer-2.5 silently drops all of the fast variant traffic. Prefix matching catches both.

  2. kind is decided per request, not per conversation. Included allowance is tracked per member and per model pool rather than as one team wide bucket, so a single conversation can legitimately contain a mix of Included in Business and Usage-based rows. If your aggregation only keeps rows where kind is Included in Business, a conversation whose requests were served on demand looks identical to one that returned nothing at all. A team level “we’re under the included limit” reading also won’t always match what an individual member’s requests do.

  3. There’s no conversationId request filter. The accepted filters are startDate, endDate, userId, email, serviceAccountId, cloudAgentId, automationId, hostingType, page and pageSize. conversationId comes back as a response field that you group on client side. If the conversations you’re tracking are cloud agent runs (bc- prefixed ids), you can filter server side with cloudAgentId, which is an exact match on a single run, or pass * for all cloud agent runs.

Two smaller things on the same endpoint: page all the way through rather than reading just the first page, since pageSize defaults to 100 and maxes at 1000, and note that the data is aggregated hourly, so a conversation that just finished may not show up immediately. The full parameter and response field list is in the Admin API docs.

If you’ve ruled all three out and a specific conversation still comes back with zero rows, reply with the conversationId, the model you expected, and the exact time window you queried, and I’ll trace that one directly.