# Welcome to Revenium

Go beyond tracking tokens and latency to measure the true economic outcomes of your AI.

Revenium provides a complete, end-to-end solution for AI spending, visibility, and control. We combine granular AI observability with a powerful usage-based billing engine to support everything from internal chargebacks to automated customer invoicing and credit card collections.

Unlike other platforms that require stitching together complex integrations across multiple vendors, Revenium delivers a unified, developer-friendly experience. You can quickly understand AI costs, identify savings opportunities, and smoothly launch usage-based subscription models - all from one centralized platform.

<a href="https://app.revenium.ai/" class="button primary">Sign Up Here</a>

***

### <i class="fa-ruler">:ruler:</i> The Revenium Difference: Measuring Economic Outcomes

Traditional observability tools tell you if your AI executed successfully. **Revenium tells you if your AI is actually profitable.** A 100% technical success rate means nothing if the business goal fails. We help you shift focus from individual traces to holistic economic outcomes.

* **Calculate the "True Cost" of AI:** Track the three real dimensions of AI spend: raw token usage, hidden external API tool costs, and the human time required to rescue failed workflows. While most companies know they spend a massive amount of time fixing broken AI, nobody actually tracks it. Revenium brings these "hidden economics" into the light so you can manage them.
* **Outcome-Based Troubleshooting:** When an AI workflow fails its business objective, stop hunting through isolated logs. Trace the entire "job" back to the exact prompt to see where the agent's reasoning broke down.
* **API-Driven Pattern Matching:** Instantly compare workflows that achieved their business outcome against those that failed, zeroing in on the exact bottlenecks burning your budget.
* **AI Insights:** Revenium's Recommendations Engine runs your usage data through detectors that surface anomalies, cost opportunities, and operational issues — each finding grounded in your actual transactions, ranked by potential monthly savings, and paired with a concrete suggested action. [See AI Insights →](/optimize-performance/ai-insights)

### <i class="fa-bezier-curve">:bezier-curve:</i> Choose Your Path

Revenium supports your entire team at every stage of your AI journey. Based on your role, here is where you should start in the sidebar:

#### <i class="fa-code">:code:</i> For Developers: Ship & Optimize

You need to integrate quickly, ensure zero latency overhead, and figure out exactly why an LLM call failed.

* Head to the [Quickstart](/get-started/quickstart) to drop in our SDKs and see your first metered call in under 5 minutes.
* Check out [Monitor Latency & Performance](/optimize-performance/monitor-latency-and-performance) to monitor Time-to-First-Token (TTFT) and [debug raw logs and traces](/optimize-performance/debug-logs-and-traces).

#### <i class="fa-money-bills">:money-bills:</i> For Finance & Ops: Cost Control & Attribution

When AI is deployed centrally across a large organization, the challenge isn't just paying the bill—it’s knowing which department is responsible for it. Revenium transforms your raw AI spend into a transparent, accountable financial system. Whether you are recovering costs from internal business units or preventing a single experimental agent from draining a quarterly budget, we provide the visibility needed to scale AI sustainably.

* Implement Internal Cross-Charging: Use the [Product and Pricing](/monetize-your-ai/create-pricing-models-and-products) engine to map AI costs to specific departments, projects, or cost centers.
* Set [Budget Guardrails & Alerts](/track-and-control-costs/set-budgets-and-alerts): Establish real-time thresholds for specific business units. Receive instant notifications via Slack or Email the moment a department reaches 80% of its allocated AI budget.
* Audit "True Cost" ROI: [Build custom dashboards](/track-and-control-costs/build-custom-dashboards-and-charts) that combine token costs, external API tool calls , and human escalation time to see the actual return on investment for any internal AI initiative.

#### <i class="fa-box-dollar">:box-dollar:</i> For Product Teams: Monetize Your AI

You need to convert raw AI usage into billable digital products and subscriptions, or you need to understand how different profiles of customers' spending differs to help you properly price your AI-centric products or features.

* Jump to [Monetize Your AI](/monetize-your-ai/tutorial-build-usage-based-billing) to read our end-to-end tutorial on building usage-based billing.
* Learn how to [create pricing models](/monetize-your-ai/create-pricing-models-and-products), [manage customer credentials](/monetize-your-ai/manage-customers-and-credentials), and [automate invoicing & payments](/monetize-your-ai/automate-invoicing-and-payments).

#### <i class="fa-robot">:robot:</i> For AI Engineers: Instrument Agents

You are building complex workflows with tools like LangChain or CrewAI and need to trace execution loops, hidden API calls, and hallucination costs.

* Explore [Instrument Your Agents](/instrument-your-agents/agent-instrumentation-guide) to bring your own AI agent workloads into Revenium and track decision costs, outcomes, and tool usage.

***

### <i class="fa-question">:question:</i> How it Works: A Real-World Example

Let's imagine a B2B software company that deploys an **AI Sales Agent** to automatically qualify leads and close small deals.

Within this workflow, the AI agent relies on:

1. **An LLM** to converse with the prospect.
2. **External Tools (like ZoomInfo)** to fetch company data.
3. **Human Escalation** if the agent gets stuck and a human rep has to take over.

**Their Objective:** Measure the true ROI of the AI agent by tracking its actual business outcome (deals closed) against its *total* cost (tokens + tool API calls + human escalation time). See the [runnable examples](/get-started/quickstart/examples) — sales, coding-workflow, and customer-support scenarios that follow this exact pattern with simulated revenue, tool spend, and escalation cost.

Here is how they achieve this using Revenium:

1. **Instrument & Attribute (< 5 minutes):** They drop in the Revenium SDK to wrap the agent's workflow. Revenium immediately begins capturing token usage, automatically attributing costs back to specific sales campaigns and CRM Opportunity IDs.
2. **Track Hidden Tool Costs (< 5 minutes):** Revenium reveals the hidden economics of the workflow. The team discovers that on a "happy path," the agent calls the ZoomInfo API once. But on an "unhappy path," the agent gets confused and calls ZoomInfo six times, causing external API costs to completely dwarf the raw token costs and also triggers an expensive human escalation to fix the error.
3. **Measure the Business Outcome (\~ 10 minutes):** Instead of just looking at engineering metrics (e.g., "The LLM didn't crash"), they look at the business funnel. They see that out of 160 jobs, the agent successfully closed 32 deals, generating $9,000 in revenue against a true AI cost of $1,800 (tokens + tools + human escalation).
4. **Outcome-Based Pattern Matching (Automated):** Using Revenium's API, the engineering team doesn't have to manually point-and-click through logs. Revenium automatically compares the 30% of workflows that failed their business outcome against the thousands that succeeded.
5. **Fix the Root Cause:** The pattern matching leads them straight to the root cause prompt. They discover the agent was failing and looping its tool calls because it couldn't parse a specific qualification criteria. They fix the prompt, eliminate the wasted ZoomInfo calls, and instantly increase the agent's profit margin.


# Quickstart

The fastest way to see Revenium working is to connect an AI coding assistant and your code repository. In under 10 minutes you have the assistant connected and live dashboards showing who is using each assistant and what it costs; once your code host is connected and its first sync completes, Revenium adds per-developer productivity metrics that line spend up against shipped pull requests.

Start with the walkthrough below, then add the other sources that matter to you.

## Start here: connect your coding assistant and GitHub

* [Connect Your Coding Assistant & Code Repository](/get-started/quickstart/5-minute-quickstart) — connect Claude Code, Cursor, Codex, Copilot, or Gemini CLI, connect GitHub or GitLab, and see dashboards and per-developer productivity metrics in under 10 minutes.
* [Connect Your Agent](/get-started/quickstart/connect-your-agent) — choose the setup path that matches how your coding agent runs.

## Instrument your own code or API traffic

If you are metering an application you build rather than an off-the-shelf assistant, use one of these paths instead:

* [Connecting Providers](/get-started/quickstart/connecting-providers) — route provider traffic (OpenAI, Anthropic, and others) through Revenium.
* [API Data Sources & OTLP](/get-started/quickstart/api-data-sources-and-otlp) — send usage from your own services over OpenTelemetry.
* [Workspace Connections](/get-started/quickstart/workspace-connections) — link a workspace to organize sources and teams.
* [Examples](/get-started/quickstart/examples) — end-to-end walkthroughs for sales, coding, and customer-support agents.


# Connect Your Coding Assistant & Code Repository

Connect an AI coding assistant and your code repository — GitHub or GitLab — to see how your team uses AI coding tools and what those tools deliver. In under 10 minutes you have the assistant connected and your usage dashboards live — per-tool and per-developer usage and cost against API-equivalent value. Per-developer productivity metrics that pair AI spend with the pull requests your developers ship appear once your code host is connected and its first sync completes.

You will connect the assistant first — that alone populates the usage dashboards — then connect your code repository to add the per-developer productivity view.

***

### <i class="fa-list-radio">:list-radio:</i> Before you begin

You need a Revenium account.

<a href="https://app.revenium.ai/" class="button primary">Sign in or Register</a>

***

## How it works

1. You connect a coding assistant, which sends usage telemetry to Revenium.
2. Revenium groups that usage by tool, team, and developer, and estimates its API-equivalent value.
3. You connect GitHub or GitLab, which adds shipped pull requests as an output signal.
4. Revenium cross-references spend against delivery and shows per-developer productivity metrics.

***

## 1. Get your metering key

In Revenium, open [**Connections → SDK Setup**](https://app.revenium.ai/connections/sdk-setup) and copy your metering key (it begins with `rev_mk_`). This key authenticates telemetry from your coding assistant into your Revenium account. Keep it handy for the next step.

## 2. Connect your coding assistant

Revenium connects Claude Code, Codex, Gemini CLI, GitHub Copilot, and Cursor. In **Connections**, each assistant has a ready-to-paste setup prompt — select your tool, copy the prompt, and paste it into that assistant. The prompt already contains your key and the exact commands, so this is the quickest path. Repeat for each assistant you want to track.

Four of the five are set up from the command line, using one package:

```bash
npm install -g @revenium/cli
```

Each assistant then has its own setup command:

| Assistant      | Setup command                                  |
| -------------- | ---------------------------------------------- |
| Claude Code    | `revenium-metering setup --api-key <your-key>` |
| Codex          | `revenium-codex setup --api-key <your-key>`    |
| Gemini CLI     | `revenium-gemini setup --api-key <your-key>`   |
| GitHub Copilot | `revenium-copilot setup --api-key <your-key>`  |

After setup, reload your environment so the assistant picks up the new configuration — the setup output tells you how (for example `source ~/.claude/revenium.env` for Claude Code, or `exec $SHELL` for Codex). Then confirm it worked:

```bash
revenium-metering status        # shows the resolved configuration
revenium-metering test --verbose # sends a test metric end to end
```

**Cursor is different — it needs no CLI install.** Cursor usage is synced by Revenium directly: in the dashboard open **Connections → Providers**, click **Link Provider**, select **Cursor**, and enter your Cursor **team** API key (a personal user key will not work). Revenium then syncs Cursor usage every 5 minutes.

**GitHub Copilot has prerequisites** before its setup command will work: Copilot Business or Enterprise on your organization, the **Copilot usage metrics** policy enabled in your GitHub org settings, and a GitHub classic token with `manage_billing:copilot`, `read:org`, and `admin:org`. Copilot data flows continuously once you start the sync (`revenium-copilot sync --watch`).

{% hint style="info" %}
**Rolling out to a whole team?** Coding assistants that support centrally-managed configuration can be set up once by an administrator and delivered to every developer automatically, with no per-developer install. See your assistant's centrally-managed configuration documentation for that; the per-user command above is for fast individual onboarding and for importing historical usage.
{% endhint %}

Run a short session in your assistant. Usage appears in Revenium after the next telemetry flush.

## 3. Connect your code repository for per-developer attribution

Your code host adds output data — merged pull requests, or merged requests on GitLab — so you can measure delivery next to spend. Revenium connects to **GitHub and GitLab**; the walkthrough below uses GitHub, and the GitLab flow is the same shape.

1. In Revenium, open **Connections → Integrations**, where GitHub, GitLab, and Slack are connected.
2. On the GitHub card, choose **Connect** and enter your GitHub organization.
3. Provide a read-only token. Revenium gives you a **Create a pre-filled token on GitHub** button that pre-selects exactly the permissions needed — Pull requests and Metadata (read-only) under Repository permissions, plus Members (read-only) under Organization permissions. If you only have a classic token, `repo` (or `public_repo` for public-only orgs) plus `read:org` also works, though it grants more than Revenium needs.
4. Choose the repositories to track, or connect the whole organization — pull requests are counted across every repo in the org.
5. Save the connection.

For GitLab, connect a personal access token with the `read_api` and `read_user` scopes; Revenium then counts merged merge requests per user across your group.

{% hint style="info" %}
**A fine-grained GitHub token may need org approval.** When the token targets an organization, an org owner or admin has to approve it before it can read org data. Until then the connection can show as **Connected** while pull request and member data stays empty — check **Settings → Third-party Access → Personal access tokens → Pending requests** in your GitHub org if nothing appears after a sync.
{% endhint %}

For per-developer attribution to line up, the email addresses on your developers' commits should match the email addresses Revenium has for those developers. Org members are auto-mapped by email, and you can edit the mapping for anyone who does not match automatically.

The first sync is not instant — give it a few minutes before you expect to see pull request data.

Revenium splits AI-assisted from human-authored work using the `Co-Authored-By` trailers at the bottom of commits. The default pattern is `noreply@anthropic.com`, which covers Claude Code. If your team uses other AI assistants that sign commits, add their signatures — one pattern per line — on the same card; work without a matching trailer simply counts as human-authored.

## 4. See your dashboards and productivity metrics

Open **Intelligence → AI Assistants** in the sidebar.

* The **Overview** shows every connected tool side by side — active users and total cost per tool for the period you select, plus aggregate adoption, sessions per user, usage trend, and API-equivalent value.
* Each tool has its own **per-tool dashboard** with a per-user breakdown: who is using it, how many sessions they run, how many tokens they consume, and what that costs.
* On the **Claude Code** tab, once your code host is connected, the **Value by User** table gains three productivity columns:

  | Column              | What it shows                                    |
  | ------------------- | ------------------------------------------------ |
  | **PRs Merged**      | Pull requests the developer merged in the period |
  | **PRs with Claude** | Pull requests where a commit was AI co-authored  |
  | **Cost/PR**         | AI spend divided by pull requests merged         |

  Connect GitLab instead and the same columns count merged merge requests, labelled **MRs** and **Cost/MR**.
* The **By Employee** tab rolls every connected assistant and direct API spend up to the individual — the view for chargebacks and for spotting concentrated spend. Start with the **Attribution Coverage** figure, which tells you how much of your identifiable AI spend is tied to a known person.

That is the full picture: usage, cost, and per-developer delivery, all in one place.

### Where to go next

* [Analyze AI tooling spend](/track-and-control-costs/analyze-ai-tooling-spend) — go deeper on who is using which assistant, how intensively, and whether the seats you bought are earning their cost.
* [Set budgets and alerts](/track-and-control-costs/set-budgets-and-alerts) — put caps on that spend and get told in Slack when a team or tool spikes.

***

## Instrument your own code or API traffic

The steps above connect off-the-shelf coding assistants. If instead you want to meter an application you build — your own AI calls or API traffic — Revenium acts as zero-latency middleware: install the SDK, set your keys, and wrap your client.

### Install the SDK

{% tabs %}
{% tab title="Python" %}

```bash
pip install "revenium-python-sdk[openai]"
```

{% endtab %}

{% tab title="NodeJS" %}

```bash
npm install @revenium/middleware
```

{% endtab %}

{% tab title="Direct API" %}

```bash
curl -X POST "https://api.revenium.ai/meter/v2/ai/completions" \
    -H "Content-Type: application/json" \
    -H "x-api-key: YOUR_REVENIUM_API_KEY" \
    -d '{
      "transactionId": "<your-per-request-uuid>",
      "provider": "openai",
      "model": "gpt-4o-mini",
      "operationType": "CHAT",
      "inputTokenCount": 200,
      "outputTokenCount": 500,
      "totalTokenCount": 700,
      "stopReason": "END",
      "requestTime": "2026-05-22T00:00:00Z",
      "completionStartTime": "2026-05-22T00:00:01Z",
      "responseTime": "2026-05-22T00:00:02Z",
      "requestDuration": 2000,
      "organizationName": "acme-corp",
      "productName": "saas-app-gold-tier",
      "agent": "support-agent",
      "traceId": "conv-28a7e9d4"
    }'
```

{% hint style="info" %}
**`transactionId` is your correlation key.** Generate a UUID in your application *before* the AI call and send it to Revenium. Re-use it on retries — Revenium dedupes by `transactionId` so retries won't double-count. Send only one of `transactionId` or `spanId` per request.
{% endhint %}

{% hint style="info" %}
**Pick the right host for your key.** Keys minted in production target `https://api.revenium.ai`. Keys minted in a dev/staging tenant target that environment's API host — the SDKs read this from `REVENIUM_METERING_BASE_URL` (overrideable per environment). If the curl above returns `403 Forbidden`, your key is for a different environment than the host it was sent to.
{% endhint %}
{% endtab %}
{% endtabs %}

### Set environment variables

```bash
# Your Revenium Routing & Auth
# Metering key (rev_mk_*): metering-only scope used by the SDK + OTLP to emit metering events to Revenium.
export REVENIUM_METERING_API_KEY="your_revenium_api_key"
# Provider key: your standard provider API key used for the actual LLM call (swap for ANTHROPIC_API_KEY, etc. when using other providers).
export OPENAI_API_KEY="your_openai_api_key"
```

### Wrap your client

{% tabs %}
{% tab title="Python" %}

```python
import openai
import revenium_middleware.openai

response = openai.chat.completions.create(
    model="gpt-4o-mini",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {
            "role": "user",
            "content": "What is the meaning of life, the universe and everything?",
        },
    ],
    max_tokens=500,
    usage_metadata={
         "trace_id": "conv-28a7e9d4",
         "task_type": "summarize-customer-issue",
         "subscriber": {
             "id": "subscriberid-1234567890",
             "email": "user@example.com",
             "credential": {
                 "name": "engineering-api-key",
                 "value": "actual-api-key-value"
             }
         },
         "organization_name": "acme-corp",
         "subscription_id": "startup-plan-Q1",
         "product_name": "saas-app-gold-tier",
         "agent": "support-agent",
    },
)
print(response.choices[0].message.content)
```

{% endtab %}

{% tab title="NodeJS" %}

> Requires ESM — set `"type": "module"` in `package.json`, or wrap the call in an `async` function.

```typescript
import { Initialize, GetClient } from "@revenium/middleware/openai";

Initialize();
const openai = GetClient();

const response = await openai.chat().completions().create(
  {
    model: "gpt-4o-mini",
    messages: [
      { role: "system", content: "You are a helpful assistant." },
      {
        role: "user",
        content: "What is the meaning of life, the universe and everything?",
      },
    ],
    max_tokens: 500,
  },
  {
    traceId: "conv-28a7e9d4",
    taskType: "summarize-customer-issue",
    subscriber: {
      id: "subscriberid-1234567890",
      email: "user@example.com",
      credential: {
        name: "engineering-api-key",
        value: "actual-api-key-value",
      },
    },
    organizationName: "acme-corp",
    subscriptionId: "startup-plan-Q1",
    productName: "saas-app-gold-tier",
    agent: "support-agent",
  }
);

console.log(response.choices[0].message.content);
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**traceId is the field you plan around.** transactionId is auto-generated by the SDK (from the OpenAI response id) or by Revenium (if you omit it on a direct API call). What you control is `traceId` — use it to group multiple AI calls that belong to one user request, conversation, or workflow. Plan your `traceId` scheme — session, conversation, or job ID — before instrumenting, so related calls group consistently from the start.
{% endhint %}

For deeper attribution, budgets, and monetization, continue with [Attribute Your Usage](/track-and-control-costs/instrument-your-code), [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts), and [Monetize Your Apps](/monetize-your-ai/tutorial-build-usage-based-billing).


# Connect Your Agent

If you want to meter usage from a coding assistant such as Claude Code, Cursor, Codex, Gemini CLI, or GitHub Copilot, that is covered by [Connect Your Coding Assistant & Code Repository](/get-started/quickstart/5-minute-quickstart).

This page is for connecting your own agents and AI tooling to Revenium: giving an assistant access to Revenium data and docs, letting Revvy instrument a codebase, sending telemetry over OTLP, or calling the API directly.

## Choose Your Path

| Goal                                            | Start here                                            | Use when                                                                                                     |
| ----------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Give an AI assistant access to Revenium docs    | [Context7 and AI docs access](/integrations/context7) | You want your agent to retrieve Revenium schemas, SDK guidance, and API references while it works.           |
| Connect an MCP-compatible assistant to Revenium | [MCP Server](/integrations/mcp-server)                | You want an agent to query Revenium data, inspect cost spikes, or help configure governance.                 |
| Let Revvy instrument a codebase                 | [Revvy CLI](/integrations/revvy-cli)                  | You want a guided CLI flow that scans code, configures metering, and helps AI coding tools finish the setup. |
| Send telemetry through standard OTLP            | [OTLP Integration](/integrations/otlp-integration)    | You already use OpenTelemetry or need a vendor-neutral telemetry path.                                       |
| Call the API directly                           | [API Reference](https://revenium.readme.io)           | You need direct API integration or schema-level implementation details.                                      |

## Where This Fits

Use Quickstart pages when you need orientation and a first path. Use Integrations pages when you need exact commands, keys, protocol details, provider setup, or long-term maintenance guidance.

## Related

* [Connect Your Coding Assistant & Code Repository](/get-started/quickstart/5-minute-quickstart)
* [Connecting Providers](/get-started/quickstart/connecting-providers)
* [API Data Sources and OTLP](/get-started/quickstart/api-data-sources-and-otlp)
* [Integration Options](/integrations/integrations)


# Connecting Providers

While the Revenium SDK intercepts your live application traffic, connecting your underlying AI provider accounts (like OpenAI or Anthropic) unlocks the other half of the FinOps picture.

> **🔑 Note on Provider Permissions:** Different AI platforms have different permission models. Always check the specific instructions on the "Link Provider" screen to ensure you use the correct key type

When you add your provider API Keys, Revenium actively syncs with the provider to pull your granular usage records and workspace data. This immediately unlocks three key dashboards:

<table><thead><tr><th width="204.390625">Insight</th><th>What It Tells You</th></tr></thead><tbody><tr><td><strong>Providers</strong></td><td>The exact percentage of your provider bill that is actively metered and protected by Revenium.</td></tr><tr><td><strong>Models</strong></td><td>The true Cost per 1M tokens across all your active AI models so you can compare performance vs. price.</td></tr><tr><td><strong>API Keys</strong></td><td>A breakdown of cost, usage, and tokens by individual API key to help you spot rogue or uninstrumented scripts.</td></tr></tbody></table>

***

### <i class="fa-link">:link:</i> How to Link a Provider

1. Head over to [Connections > Providers](https://app.revenium.ai/connections/providers) in your left sidebar and click **+ Link Provider**.
2. Select your AI platform, drop in your API key, and hit **Create**.
   1. For details on how to connect Revenium's supported providers, [read here](/integrations/provider-integrations#how-to-link-a-provider).

Revenium will instantly authenticate the key and start syncing your historical data.

***

### <i class="fa-eyes">:eyes:</i> Viewing Your Data

Once your key is authenticated, you don't have to wait for an end-of-month report. Head straight over to the **Overview** section in your left sidebar to see your data instantly populated across three main tabs:

* **Providers:** Check your Coverage Ratio and total top-level spend.
* **Models:** View your Model Efficiency and compare your actual cost per 1M tokens.
* **API Keys:** Audit individual key usage to easily spot uninstrumented or rogue scripts.

> **Note on Syncing:** If you have a massive historical footprint, it may take a few moments for all data to appear. You can click **View Sync Logs** on the Provider dashboard to verify that Revenium is actively processing your records.


# API Data Sources & OTLP

Use this page when your application already emits OpenTelemetry and you want to send that telemetry to Revenium. If you need runtime cost controls, richer business attribution, or the simplest first integration, start with the SDK path instead.

## Quick Path

1. Create or choose a metering-only Revenium API key (`rev_mk_`) for the environment.
2. Point your OpenTelemetry exporter at Revenium.
3. Run a test request.
4. Confirm tokens, model, provider, and cost appear in logs, traces, or AI analytics.

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.revenium.ai/meter/v2/otlp
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer rev_mk_your_tenant_yourkey"
```

{% hint style="warning" %}
Python OpenTelemetry SDKs require the header value to be percent-encoded. Use `Authorization=Bearer%20rev_mk_your_tenant_yourkey` if your Python telemetry does not arrive.
{% endhint %}

## When To Use This Path

| Scenario                                                              | Start here                                         |
| --------------------------------------------------------------------- | -------------------------------------------------- |
| Your app already emits OpenTelemetry and you want telemetry ingestion | [OTLP Integration](/integrations/otlp-integration) |
| You need runtime cost controls, SDK attribution, or middleware setup  | [SDK Setup](/integrations/sdk-setup)               |
| You need to understand data-source identifiers                        | [API Data Sources](/integrations/api-data-sources) |
| You need schema-level API detail                                      | [API Reference](https://revenium.readme.io)        |

## What Revenium Reads

For OTLP spans and logs, Revenium reads standard GenAI semantic convention fields for provider, model, token usage, timing, and errors. Revenium-specific attributes such as `revenium.product.name`, `revenium.organization.name`, and `revenium.subscriber.id` add business attribution.

For the full endpoint matrix, authentication priority, gRPC caveats, and payload examples, continue to [OTLP Integration](/integrations/otlp-integration).


# Workspace Connections

Use this page as the quickstart handoff for connecting team workflow systems. The detailed setup and maintenance guidance lives in [Slack](/integrations/slack) and [GitHub Integration](/track-and-control-costs/analyze-ai-tooling-spend/github-integration).

## What You Can Connect

| Connection | Use it for                                                                                            | Full setup                                                                                 |
| ---------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| GitHub     | Correlate AI coding assistant usage with merged pull requests and mapped developer identities.        | [GitHub Integration](/track-and-control-costs/analyze-ai-tooling-spend/github-integration) |
| Slack      | Route AI cost alerts, anomaly notifications, and reports into the channels your team already watches. | [Slack](/integrations/slack)                                                               |

## Where It Appears

In the Revenium app, open **Connections → Integrations**. Each connection shows its status, credentials, configuration, and sync controls from the same area.

## Next

* [Slack](/integrations/slack)
* [GitHub Integration](/track-and-control-costs/analyze-ai-tooling-spend/github-integration)
* [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts)
* [Analyze AI Tooling Spend](/track-and-control-costs/analyze-ai-tooling-spend)


# Examples

Three outcome-based examples that show how Revenium connects AI cost, tool usage, traces, and business value.

Most AI reporting starts with tokens, latency, and provider invoices. That is useful infrastructure telemetry, but it does not answer the business question: did the agent create value?

The hard part of scaling AI agents is closing that gap. A workflow can look healthy technically while still being economically unclear. It may call the right models, use the right tools, and complete the right steps, but finance and operations still need to know what the work produced, what it cost, and where human escalation changed the economics.

These examples show the outcome-based pattern Revenium is designed to support. Each scenario connects model cost, tool cost, trace behavior, and a terminal business outcome so teams can evaluate agent work as unit economics, not just usage.

Here is a quick tour of a sample deployment .\
The intent of these examples is to answer the question: **did the agent produce more value than it cost?** So each one meters *everything* the agent does — the model calls, the external tools it reaches for, and the points where it hands off to a person — tied to a business outcome.

And that's the interesting part: some steps are **fully automated** — the agent calling tools like data enrichment, CI, or a knowledge base on its own — and some keep a **human in the loop**, where the agent escalates to a person. Revenium meters **both**, so you get the true, all-in cost set against the real value produced.<br>

{% embed url="<https://youtu.be/KzlYIxm1G2U>" %}

## The Measurement Pattern

Each scenario follows the same loop:

1. The agent performs a recognizable business workflow.
2. Model calls and tool actions are metered with business context.
3. Related steps are joined into a trace.
4. The workflow reports an outcome for the job.
5. Revenium compares the cost of the work with the value it created or protected.

That pattern is reusable across agentic systems. The examples here focus on outcome-based workflows because they make the value question explicit: revenue generated, engineering work deflected, or support cost avoided.

## The Three Scenarios

| Scenario                      | What It Measures                                                                                           |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------- |
| **AI Sales Agent**            | Revenue attribution — converted pipeline value vs. enrichment, model, and human review cost.               |
| **AI Coding Workflow**        | Engineering value — deflected engineering effort across PR review, test gen, RCA, release gates, dep risk. |
| **AI Customer Support Agent** | Deflection economics — tickets resolved without human handling vs. escalation and upsell value.            |

Each scenario has its own page in this section:

* [AI Sales Agent Example](/get-started/quickstart/examples/ai-sales-agent)
* [AI Coding Workflow Example](/get-started/quickstart/examples/ai-coding-workflow)
* [AI Customer Support Agent Example](/get-started/quickstart/examples/ai-customer-support)

## Source & Setup

The runnable code lives in the public Revenium Python SDK. Installation, environment variables, exact commands, payload details, and tunables are maintained there:

* **Examples README (canonical):** [github.com/revenium/revenium-python-sdk/blob/main/examples/agentic\_outcomes/README.md](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md)
* **Shared runtime (used by all three scenarios):** [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)

```bash
# the example scripts live in the SDK repo — clone it, install the SDK, then run from inside the repo
git clone https://github.com/revenium/revenium-python-sdk.git
cd revenium-python-sdk
pip install revenium-python-sdk
# then run any scenario, e.g.:
python examples/agentic_outcomes/sales.py --count 5
```

Set `REVENIUM_API_KEY` (a write-scope key, `rev_sk_…`, generated at [app.revenium.ai → Integrations](https://app.revenium.ai/connections/sdk-setup)) before running.

For a first run, use a demo team or clearly named demo data so the sample does not mix with production traffic. Start small, confirm the run appears in the expected Revenium views, then increase volume only if you need a denser dashboard sample.

## What Revenium Should Show

Use the examples to review the same workflow from several angles:

* [**ROI and unit economics**](/track-and-control-costs/analyze-roi-and-unit-economics): value generated or avoided cost compared with AI, tool, and human escalation costs.
* [**Logs and traces**](/optimize-performance/debug-logs-and-traces): the exact sequence of model calls, tool actions, timings, and outcome linkage for an individual job.
* [**Latency and performance**](/optimize-performance/monitor-latency-and-performance): workloads that are unusually slow, expensive, or transaction-heavy.
* [**Agent decision costs**](/instrument-your-agents/analyze-decision-costs) and [**tool usage**](/instrument-your-agents/monitor-agent-tool-usage): movement of work between agent roles and the economic impact of external tools.

The usual review path is: start in ROI, choose a representative job, then inspect the trace and performance details behind it.

## Related Reading

For current product updates, see the [Revenium changelog](/get-started/changelog). For broader writing on AI economics, outcomes, cost control, and agent operations, see the [Revenium blog](https://www.revenium.ai/blog).

## Notes

* Values are illustrative demo values, not performance or ROI guarantees.
* Prompt details in the UI depend on your workspace prompt-capture settings.


# AI Sales Agent Example

Measure whether an AI-assisted sales workflow creates enough revenue to justify model, tool, and human review costs.

AI sales agents can research accounts, enrich leads, qualify opportunities, and prepare follow-up before a human ever touches the deal. That work has a real cost: model calls, enrichment tools, contact search, and review time. The business question is whether the agent creates enough qualified pipeline or converted revenue to justify that spend.

This example simulates a sales funnel — prospecting, qualification, and close-prep — and ties model spend, enrichment cost, and human review cost back to a converted revenue outcome. Some jobs convert; the rest complete without revenue, so the funnel economics stay visible.

For the broader outcome-measurement pattern across these examples, see the [overview page](/get-started/quickstart/examples).

## What You'll See

When the run completes, these Revenium views populate with the demo data:

* **ROI dashboard** — total agent cost vs. converted revenue, with a value ratio for the sales workflow.
* **Conversion Funnel** — converted vs. unsuccessful jobs across the run.
* **Cost Composition** — split between AI model spend, enrichment tool spend, and human escalation cost.
* **Tool Cost ratio** — share of cost driven by Zoominfo / Apollo / SDR handoff vs. the model itself.
* **Traces** — per-job sequence of prospecting → qualification → close, with parent/child step linkage.
* **Agent decision costs & Tool usage** — role-level attribution for the sales agent and its tools.

## Run It

The example scripts ship in the public SDK repo, not on PyPI. Clone the repo first, then run from inside it:

```bash
git clone https://github.com/revenium/revenium-python-sdk.git
cd revenium-python-sdk
pip install revenium-python-sdk
python examples/agentic_outcomes/sales.py --count 5
```

Set `REVENIUM_API_KEY` (a write-scope key, `rev_sk_…`, generated at [app.revenium.ai → Integrations](https://app.revenium.ai/connections/sdk-setup)) before running. Use `--dry-run` or `--plan` to preview without sending data.

## View The Source

The runnable scenario lives in the public SDK:

* **sales.py** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Shared runtime (common.py)** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Examples README** — [github.com/revenium/revenium-python-sdk/blob/main/examples/agentic\_outcomes/README.md](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md)

## Customize

The top of `sales.py` exposes the customization points: `SUBSCRIBER`, `LLM_STEPS`, `TOOL_STEPS`, the conversion rule in `pick_outcome`, and the metadata fields in `build_metadata`. Tweak these to match your sales motion (your model mix, your enrichment vendors, your conversion rate, your average deal size). For the full TUNABLES reference and recipes, see the [TUNABLES section of the examples README](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md#tunables).

## Why This Matters

Sales teams rarely need another token chart. They need to know whether the agent helped create pipeline, whether expensive enrichment was worth it, and where human review changed the economics. This example connects operational evidence from the trace with the business result reported on the job.

## Related Views

* [ROI and unit economics](/track-and-control-costs/analyze-roi-and-unit-economics)
* [Logs and traces](/optimize-performance/debug-logs-and-traces)
* [Agent decision costs](/instrument-your-agents/analyze-decision-costs)
* [Tool usage](/instrument-your-agents/monitor-agent-tool-usage)

## Notes

* Values are illustrative demo values, not performance or ROI guarantees.
* Use a demo team or clearly named demo data for first runs.
* Prompt details in the UI depend on your workspace prompt-capture settings.


# AI Coding Workflow Example

Measure engineering value from AI coding workflows by connecting model calls, tools, traces, human review, and outcomes.

AI coding agents can review pull requests, generate tests, investigate incidents, check releases, and assess dependency risk. Those workflows often look productive in an IDE, but they are hard to evaluate economically unless the engineering work, model usage, tool activity, human review, and outcome are connected.

This example simulates a multi-scenario coding workflow — PR review, regression test generation, incident RCA, release readiness checks, and dependency risk analysis — across multiple agent roles (orchestration, implementation, review, validation). Each job either completes autonomously, escalates to a human, or is canceled, and the deflected engineering value is reported alongside the agent cost.

For the broader outcome-measurement pattern across these examples, see the [overview page](/get-started/quickstart/examples).

## What You'll See

When the run completes, these Revenium views populate with the demo data:

* **ROI dashboard** — coding-agent cost vs. deflected engineering value, with net value per job.
* **Deflection Rate** — share of jobs completed autonomously vs. escalated or canceled.
* **Cost Composition** — AI model spend vs. tool spend (repo search, CI compile/test, GitHub review submission) vs. human escalation cost.
* **Scenario Mix** — distribution across PR review, test gen, RCA, release gate, and dep risk.
* **Traces** — multi-step engineering workflows with parent/child relationships, step duration, and outcome linkage.
* **Agent decision costs** — role-level attribution across orchestration, implementation, review, and validation.
* **Performance** — duration outliers and expensive traces, useful for larger batch runs.

## Run It

The example scripts ship in the public SDK repo, not on PyPI. Clone the repo first, then run from inside it:

```bash
git clone https://github.com/revenium/revenium-python-sdk.git
cd revenium-python-sdk
pip install revenium-python-sdk
python examples/agentic_outcomes/coding.py --count 5
```

Set `REVENIUM_API_KEY` (a write-scope key, `rev_sk_…`, generated at [app.revenium.ai → Integrations](https://app.revenium.ai/connections/sdk-setup)) before running. Use `--dry-run` or `--plan` to preview, or `--only-scenario pr-review` to limit to one scenario.

## View The Source

The runnable scenario lives in the public SDK:

* **coding.py** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Shared runtime (common.py)** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Examples README** — [github.com/revenium/revenium-python-sdk/blob/main/examples/agentic\_outcomes/README.md](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md)

## Customize

The top of `coding.py` exposes the customization points: `SCENARIOS` (workflow mix and per-scenario step sequences), `LLM_STEPS` and `TOOL_STEPS` (reusable step templates), `OUTCOME_WEIGHTS` (autonomous completion / escalation / cancellation rates), and the `ESCALATION_TOOL` cost. Adjust these to match your engineering motion. For the full TUNABLES reference, see the [TUNABLES section of the examples README](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md#tunables).

## Why This Matters

AI coding assistants often create value by removing small pieces of engineering work: a review pass, a test draft, an incident summary, or a release check. Those wins are easy to miss if the platform only reports token spend. This example turns that work into measurable unit economics — cost of the agent, value it claims to deflect, and the operational evidence behind the claim.

## Related Views

* [ROI and unit economics](/track-and-control-costs/analyze-roi-and-unit-economics)
* [Logs and traces](/optimize-performance/debug-logs-and-traces)
* [Latency and performance](/optimize-performance/monitor-latency-and-performance)
* [Agent decision costs](/instrument-your-agents/analyze-decision-costs)
* [Tool usage](/instrument-your-agents/monitor-agent-tool-usage)

## Notes

* Values are illustrative demo values, not engineering benchmark claims.
* Human escalation represents review or takeover cost, not a product recommendation.
* Prompt details in the UI depend on your workspace prompt-capture settings.


# AI Customer Support Agent Example

Measure support deflection by connecting ticket workflows, tool costs, human escalation, and resolved-ticket outcomes.

AI support agents can classify tickets, search knowledge, draft responses, update support systems, and decide when a customer needs a human. The business value is not just ticket volume; it is whether the agent resolves routine work at a lower cost while escalating the cases that still need human judgment.

This example simulates a support queue across three motions — ticket triage, ticket resolution, and escalation handling — with three terminal outcomes per ticket: deflected, escalated, or converted (an upsell or renewal during the support session). The result is a deflection-economics view rather than a deflection-rate count.

For the broader outcome-measurement pattern across these examples, see the [overview page](/get-started/quickstart/examples).

## What You'll See

When the run completes, these Revenium views populate with the demo data:

* **ROI dashboard** — support-agent cost vs. deflected human handling cost plus upsell value, with net value.
* **Deflection Rate** — share of tickets resolved without human handling.
* **Outcome Mix** — deflected vs. escalated vs. converted (upsell) tickets.
* **Cost Composition** — AI model spend, tool spend (KB search, CRM lookup, ticket update), and human escalation review cost.
* **Tool Cost ratio** — share of cost driven by support tools vs. the model itself.
* **Traces** — per-ticket sequence of classify → KB search → draft → verify → ticket update.
* **Performance** — transaction count and duration outliers, useful for high-volume support batches.

## Run It

The example scripts ship in the public SDK repo, not on PyPI. Clone the repo first, then run from inside it:

```bash
git clone https://github.com/revenium/revenium-python-sdk.git
cd revenium-python-sdk
pip install revenium-python-sdk
python examples/agentic_outcomes/support.py --count 5
```

Set `REVENIUM_API_KEY` (a write-scope key, `rev_sk_…`, generated at [app.revenium.ai → Integrations](https://app.revenium.ai/connections/sdk-setup)) before running. Use `--dry-run` or `--plan` to preview, or `--force-outcome ESCALATED` to drive a specific outcome path.

## View The Source

The runnable scenario lives in the public SDK:

* **support.py** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Shared runtime (common.py)** — [examples/agentic\_outcomes/ directory](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes)
* **Examples README** — [github.com/revenium/revenium-python-sdk/blob/main/examples/agentic\_outcomes/README.md](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md)

## Customize

The top of `support.py` exposes the customization points: `SCENARIOS` (triage / resolution / escalation mix and step sequences), `LLM_STEPS` and `TOOL_STEPS` (reusable step templates), `OUTCOME_WEIGHTS` (deflection / escalation / conversion rates), `UPSELL_VALUE_RANGE`, and the `ESCALATION_TOOL` cost. Tweak to match your support motion. For the full TUNABLES reference, see the [TUNABLES section of the examples README](https://github.com/revenium/revenium-python-sdk/blob/main/examples/agentic_outcomes/README.md#tunables).

## Why This Matters

Support automation can look successful if you only count resolved tickets, but cost and escalation behavior change the story. A deflected ticket is valuable when the total cost of the agent and tools is lower than the human work it avoided. This example connects the support workflow, the operational cost, and the ticket outcome so teams can reason about deflection as unit economics.

## Related Views

* [ROI and unit economics](/track-and-control-costs/analyze-roi-and-unit-economics)
* [Logs and traces](/optimize-performance/debug-logs-and-traces)
* [Latency and performance](/optimize-performance/monitor-latency-and-performance)
* [Agent decision costs](/instrument-your-agents/analyze-decision-costs)
* [Tool usage](/instrument-your-agents/monitor-agent-tool-usage)

## Notes

* Values are illustrative demo values, not support benchmark claims.
* Prompt details in the UI depend on your workspace prompt-capture settings.
* Keep first runs small enough that individual ticket traces are easy to inspect.


# Personalize Your Workspace

What happens the first time you sign in: pick how you'll use Revenium, get a home and sidebar tailored to that role, connect your AI assistants with a guided setup, and start from one-click alert temp

The first time you sign in, Revenium asks how you plan to use it and tailors the app around that answer. Picking a role reorders your sidebar, changes what your home page leads with, and pre-selects the alert templates most relevant to you. Nothing is locked in — you can change your role or reset the layout at any time.

***

### <i class="fa-user-gear">:user-gear:</i> Choose your role

On first sign-in an onboarding dialog asks how you'll use Revenium. Pick the role that fits you best:

<figure><img src="/files/ns2JFG2nR0LaXseCeshz" alt="Onboarding dialog asking &#x22;What&#x27;s your main goal in Revenium?&#x22; with three role cards"><figcaption><p>Pick your role on first sign-in — CxOs &#x26; Finance, Product Leaders, or Platform &#x26; Engineering Teams.</p></figcaption></figure>

| Role                             | Best for                             | Your workspace leads with                                                                                                 |
| -------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------- |
| **CxOs & Finance**               | Figuring out the bill                | Costs & Revenue, Billing, and Alerts first; a home focused on budgets and where spend is concentrated.                    |
| **Product Leaders**              | Building AI apps with unit economics | AI Assistants, Performance, and spend-by-product first; a home showing adoption alongside cost and margin per product.    |
| **Platform & Engineering Teams** | Common metrics and services at scale | AI Assistants, Performance, Dashboards, and Cost Sources first; a home showing adoption by team and what to connect next. |

Your choice only affects your own view — it does not change your permissions, your team, or what other users see. If you'd rather explore first, you can skip the dialog and pick a role later.

***

### <i class="fa-house">:house:</i> Your personalized home

After you pick a role, the home page adapts to it:

<figure><img src="/files/9GGj0mDqfiBSa7wxI0Z7" alt="Personalized home for the CxOs &#x26; Finance role"><figcaption><p>A role-tailored home: your tagline, a guided coding-assistant setup card, next-step prompters, and connection status.</p></figcaption></figure>

The prompters and emphasis shift with your role — Product Leaders lead with adoption and spend-by-product, while Platform & Engineering Teams lead with engineering insights and connecting data sources.

<figure><img src="/files/pyNFUeOOmCutAgZ2Ly20" alt="Personalized home for the Product Leaders role"><figcaption><p>Product Leaders — "Build AI apps with unit economics."</p></figcaption></figure>

<figure><img src="/files/RVsriUrTXTDQ4kpMlecT" alt="Personalized home for the Platform &#x26; Engineering Teams role"><figcaption><p>Platform &#x26; Engineering Teams — "Common metrics &#x26; services at scale."</p></figcaption></figure>

* **Next-step prompters** — under "What do you want to do?", a short row of suggested actions for your role, such as understanding a cost change, measuring team adoption, seeing spend by customer or product, connecting a data source, or setting up an alert. Each card takes you straight to the relevant screen.
* **Guided coding-assistant setup** — a "Set up a coding assistant" card at the top when there's an assistant left to connect (covered below).
* **Connection & setup status** — at-a-glance cards showing what's already wired up: whether Revenium is receiving data (SDK / provider integrations), Slack connection, active alerts, and colleagues invited — each with a shortcut to finish the next step.
* **Role-aware layout** — the sections and insights most useful to your role are surfaced first, so the first screen you see reflects the questions you're most likely to ask.
* **Sidebar ordering** — navigation is reordered to put your most-used areas near the top.

***

### <i class="fa-sliders">:sliders:</i> Change your role or layout

Use the role switcher in the top navigation bar at any time:

* **Change your persona…** — reopens the role picker to switch roles.
* **Show all sections** — temporarily reveals every navigation section, regardless of your role.
* **Customize sidebar…** — reorder sections and items with drag-and-drop, show or hide sections, and set your default landing page. Your customization is saved to your browser and layered on top of your role's defaults.

{% hint style="info" %}
Sidebar customization and the "show all sections" preference are stored per browser and cleared when you sign out. Your selected role is saved to your account and follows you across devices.
{% endhint %}

***

### <i class="fa-robot">:robot:</i> Connect your AI assistants (guided setup)

If your workspace has no AI assistant data yet, your home shows a guided setup card that walks you through connecting Claude Code, Claude Cowork, Cursor, Gemini CLI, Codex CLI, or GitHub Copilot in three steps:

1. **Pricing mode** — tell Revenium whether you pay for the assistant as a fixed subscription/seat (kept as an API-equivalent estimate) or at API rates (counted as real spend). See [Configure AI Assistant Pricing Mode](/track-and-control-costs/analyze-ai-tooling-spend/configure-coding-assistant-billing-models).
2. **Pick your assistant** — choose which assistant to connect first.

<figure><img src="/files/7YatDO3snyQH7uDAsVzg" alt="Guided setup step: pick your assistant"><figcaption><p>Pick the assistant to connect: Claude Code, Claude Cowork, Cursor, Gemini, Codex, or Copilot.</p></figcaption></figure>

3. **Install method** — when your chosen assistant supports more than one collection method, pick how usage is gathered: managed settings from the provider's admin console, a per-developer CLI install, or an admin-run API sync that pulls organization usage on a schedule. Assistants with a single supported method skip this step and go straight to the setup instructions.

<figure><img src="/files/ENsrxPNDF88E67mLlayX" alt="Guided setup step: pick your install method"><figcaption><p>Choose how usage is collected — e.g. admin-console managed settings or a per-developer CLI install.</p></figcaption></figure>

{% hint style="info" %}
If your team's AI assistant pricing mode is already set, the wizard skips the first step and starts at **Pick your assistant**.
{% endhint %}

The card links to the detailed setup instructions for each path. For the full picture of what the assistant dashboards show once connected, see [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend).

***

### <i class="fa-bell">:bell:</i> Start from one-click alert templates

Rather than building an alert from scratch, your Alerts landing screen offers one-click templates chosen for your role — for example a week-over-week spend jump, a daily or monthly spend cap you can edit, a per-model cost spike, a rising error rate, or a token-usage surge. Click a template to create the alert instantly (cross-provider, notifying you by email by default), or choose **Customize** to add a Slack channel or open the full alert builder.

See [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts#one-click-templates) for the full list and details.


# Changelog

### 2.18.0

* **Drill through almost any chart** — Click into nearly every chart to see the individual transactions behind a number, so you can go from a headline figure to the detail that explains it in one step.
* **Provider Comparison** — A new Provider Comparison tab shows spend and usage across your AI providers in a single view. (Distinct from the Provider Comparison chart template in Chart Builder.)
* **Broader activity search** — Free-text search covers the unified activity feed and the tool registry, not just completions.
* **More coding-assistant PR analytics** — The analytics API now aggregates merged pull requests and merge requests by week or by month, as well as by day.
* **Searchable team switcher** — Find and jump to a specific team from the sidebar faster.
* **API filter discovery** — Client integrations can now look up the valid metric-task-type and model-source values directly from the API instead of hardcoding them.
* **Revenium MCP server enhancements** — The self-hosted Revenium MCP server now supports managing cost-control guardrails and agents, viewing squad activity, and reading budgets, billing, and business analytics directly from your AI tools.
* **Multi-period spend budgets** — Set cumulative spend budgets against provider spend over daily, weekly, monthly, or quarterly periods, so provider-based cost controls track the same cadence your team already plans around.
* **Backend performance improvements** — A round of backend performance work makes everyday operations across the platform faster and more responsive.

### 2.17.0

* **Guardrails** — Manage spend notifications and hard limits in one place, with rule history and read-only inspection access.
* **Guardrail hand-off from AI-by-Employee** — Start a Guardrail prefilled from a filtered employee view, and show developers your own message when an enforced limit blocks a request.
* **New AI Insights spend detectors** — Two new checks surface cost risk automatically: one flags when your cost per call is rising faster than usage, and one flags when a single API key, subscriber, product, or agent breaks from its own historical spending pattern.
* **Automatic spend-spike explanations** — When a day's AI spend jumps, Revenium now explains the cause on the AI Assistant view: which people and usage drove the spike against their own normal, set beside what the team produced that day — so a high-spend day reads as high output rather than a surprise.
* Improved **AI Insights attribution** so each recommendation highlights the usage pattern that most sets it apart — making it faster to see why a finding was raised.
* Improved **AI spend efficiency analysis** with daily spend and token context, incomplete-day indicators, a recent-trend view across the selected period, and the option to break spend and spend-versus-token trends down by vendor.
* **Redesigned Tasks page** — The Tasks view under Costs & Revenue is redesigned with a headline spend figure, a cost-trend chart split by provider and SDK, and a per-task breakdown — so you can see spend over time per run and by task at a glance.
* **Provider spend reconciliation** — Compare billed and metered totals with clear coverage-health states and clearer handling of data gaps or unusually high ratios.
* **Billed vs metered clarity** — Every analytics surface now labels whether a figure is *Billed* (an actual provider invoice) or *Metered* (usage Revenium observes directly), so you always know whether a number is a real charge or an estimate.
* **AI-by-Employee analysis** — Filter employee-level usage by model tier, provider, and vendor, compare team benchmarks and cost per million tokens, customize table columns, and export CSVs for focused reviews.
* **GitLab integration** — Connect a GitLab group and optional project scope from the Integrations page, manage the connection, and trigger synchronization.
* **GitHub user mapping improvements** — Edit existing user mappings and map multiple GitHub accounts to a single corporate email, keeping per-employee attribution accurate.
* **Read-only role** — Give teammates view-only access across the workspace: read-only users can review dashboards, budgets, and settings without being able to create, edit, or delete.
* **Sample-data previews** — See representative analytics and assistant dashboards before connecting data or while waiting for data to arrive.
* **Provider Comparison chart template** — Create a prefilled Chart Builder dashboard that places provider billing and metered usage charts together.
* **Job grouping for cost traces** — Examine anomalies across the related trace types that make up a business process or outcome.
* **Ready-to-paste setup prompts** — Choose a coding assistant on Connections and copy the relevant setup instructions.
* **Coding-assistant activity included by default** — Logs, traces, and employee analysis now include AI coding assistant usage (Claude Code, Cursor, Copilot, and similar tools) as soon as an assistant is connected, so a new account shows data right away. Turn it off for a team when you'd rather exclude it, and the choice is remembered on future visits.
* **Custom dashboard management** — Delete custom dashboards directly from dashboard rows with confirmation, while system dashboards and read-only access remain protected.
* **Metering logs search** — Find specific completions, metrics, and tool events by identifier or attribute instead of scrolling.
* **API compatibility** — Completion-metering responses now return `transactionId`, `subscriberEmail` is accepted alongside `clientEmailAddress`, and `streamed` is accepted and returned alongside `isStreamed`.
* **Anomaly metric API migration** — Response and schema enum values now use `UPPER_SNAKE_CASE`: `TOTAL_COST`, `TRACE_DURATION`, and `TRANSACTION_COUNT`. Update response parsing and generated enum bindings; legacy camelCase values remain accepted on input.
* **Strict ingestion mode** — Optionally require metering payloads to reference only objects already set up in your account, so unrecognized records can't quietly enter your data. Rejected records are held for review and resubmission with an itemized list of what failed.
* **More reliable metering delivery** — The Python, Node.js, and Go integrations now hold and retry metering events through brief service interruptions, so your usage keeps flowing to Revenium instead of dropping when a downstream service is momentarily unavailable.
* **Deleted-transaction accuracy** — Your analytics reflect exactly the transactions you keep: anything you remove is cleanly excluded across dashboards, recommendations, employee usage, margin, ROI, cost, and assistant views — so every figure stays trustworthy.
* **Large-team dashboard performance** — Assistant dashboard charts stay responsive and readable as organizations grow.
* **Logout** — Signing out is now immediate and reliable.
* **Details dialogs** — A footer Close action keeps dialogs easy to dismiss when notifications cover the top-right control.
* **Model cost attribution** — Pricing resolves reliably from short model names, without requiring a fully qualified name.

### 2.16.0

* **Provider-based alerts** — Set alerts directly on provider spend and provider data sources, not just metered telemetry. A new Data Source toggle on the Create Alert flow lets you choose between Telemetry and Provider data, so cost coming straight from a provider account can trigger a notification. Alerts now evaluate per organization with isolated batches.
* **AI by Employee view** — Track per-employee AI spend, token usage, and cost efficiency across all AI sources in a single view
* **Role-based navigation** — Pick a persona for your role on first run and switch anytime from a new persona menu. Your home page, sidebar order, and highlighted insights adapt to the persona you choose; you can customize which sections appear and set a default so the app always opens the way you work.
* **Model mix and cost efficiency** — Per-user AI dashboards now center on model mix and blended cost per million tokens ($/Mtok) instead of raw token counts, and surface spend concentration so you can spot the few people or models driving disproportionate cost.
* **Connect multiple GitHub organizations** — Connect more than one GitHub organization and choose exactly which repositories to track through a new repository picker, instead of a single-organization connection.
* **Provider billing charts** — A dedicated provider billing view on the provider cost dashboard, scoped to the team you're viewing so charts reflect the active team.
* **Open team creation** — Teams can now be created without upgrading to an enterprise plan.
* **Hosted Revenium MCP server** — Connect AI agents to Revenium through the new hosted, multi-tenant MCP server with OAuth sign-in at `mcp.revenium.ai` — no local MCP server setup required.
* Fixed a **Revenium CLI** backfill bug that could overcount tokens.
* Improved **Teams management** — view team members, land on the Teams tab by default, and see role badges at a glance.
* Improved **provider cost dashboards** — provider dropdown now sourced from your connected credentials with help overlays, corrected spend-vs-tokens dual-axis charts, adaptive day/week/month granularity, and a clearer provider billing empty state.
* Fixed **Top Movers** to scope spend-vs-tokens to the active team and rank by dollar movement.
* Fixed **AI-by-employee** reporting to stop double-counting non-assistant agents and to classify corporate vs. personal domains more reliably.
* Improved **API validation** — requests with invalid product identifiers now return a clear validation error.
* Fixed a bug that created **duplicate organizations** when names differed only by capitalization.
* Fixed **metering ingest** to accept the `streamed` alias and correctly record streamed-request flags.
* **Metering responses** now include the transaction ID, so submissions are easier to trace and reconcile.
* Fixed **sign-in team assignment** so users reliably land in the correct team.
* Fixed **duplicate onboarding notifications** on first data ingest.
* Fixed **API billing analytics** to scope results to the requested team.
* Fixed the **version-update notification** being hidden behind other dialogs.

### 2.15.0

* **Cost analytics by AI job** — The Traces page now has a **Job** view that aggregates cost, anomalies, and trends by agentic job instead of by individual trace. See average and P95 cost per job, your most expensive jobs, and cost trends by job type — and open a job to see its transactions grouped by trace.
* **Faster dashboards** — Many complex dashboards now load faster, particularly for large accounts.
* **Click-through AI Insights** — AI Insights now shows where concentrated error cost is coming from and lets you click straight from an insight card into the filtered transactions behind it.
* **Role-restricted API keys** — Creating a write-scope API key is now restricted by role, so you can let people issue read-only keys without granting write access.
* Updated the **Revenium CLI** to track GitHub Copilot usage through GitHub's current Metrics API so Copilot spend keeps reporting reliably.
* Fixed categorical charts (including top tools by call count) to paginate fully instead of capping results.
* Fixed Cost Trends charts to show P95/P99 reference lines, with more consistent number and timezone formatting across dashboards.
* Fixed invoice PDF and CSV exports to return a clear not-found response when a document cannot be generated, and billing to resolve products by exact name.
* Fixed broken command-palette (Cmd+K) links and improved Subscribers and Credentials search filtering.
* Fixed sign-in to preserve your intended destination after authenticating.

### 2.14.0

* **AI Insights detects two new classes of waste** — `max_tokens` cutoffs (so responses are being truncated mid-thought while you pay for incomplete answers), and subscribers or agents whose AI spend has gone largely dormant. Each finding includes a dollar-quantified savings estimate and example transactions to verify it.
* **AI Insights is now available through the MCP server** — AI agents talking to Revenium via MCP can now run and read AI Insights recommendations as a first-class tool action.
* **Azure Cost Management integration** — connect your Azure subscription via a Service Principal to pull daily cost data into Revenium, with spend attributed to the specific model that drove it (the same per-model breakdown you already get for OpenAI and other providers). Supports JSON-paste for credentials and maps Azure billing errors to actionable guidance.
* **GitHub Copilot support** — track your organization's Copilot usage in Revenium: connect with the Revenium CLI (`revenium-copilot`) and see adoption and usage on the new **Copilot dashboard**, alongside your other AI coding assistants.
* **AI Assistant Pricing Mode** — a per-team setting (**Management > Teams > Team AI Settings**) that controls whether AI assistant usage (Claude Code, Claude Cowork, Cursor IDE, Gemini CLI, Codex CLI, GitHub Copilot) counts as real API spend or stays as a subscription/seat-based estimate on AI Assistant dashboards, so your cost reports reflect what you actually pay.
* **Metering retries are now safe out of the box** — the `Idempotency-Key` header on metering endpoints is now enabled, and the Node, Python, Go, and MCP SDKs generate the key automatically. Retried submissions within a 24-hour window are deduplicated server-side.
* **Webhook verification helpers in every SDK** — verify HMAC-signed webhooks from Revenium with a single SDK call in Python, Node, or Go. Pairs with the server-side signing and rotation shipped last release.
* **Revenium MCP server now auto-generates Idempotency-Key on metering** — completes the SDK side of the metering-idempotency rollout for AI agents that submit usage via MCP.
* **Top Movers API now ranks by absolute dollar change** — previously sorted by percent change, which buried high-dollar moves behind tiny-customer fluctuations.
* **Python SDK fix for AWS Bedrock** — cache token counts on the Bedrock Anthropic path were previously not included.
* **Cross-SDK terminology cleanup** — `organizationName` and `productName` are now the canonical field names across every SDK, middleware, and MCP surface. The deprecated `organizationId`/`productId` aliases have been dropped from wire emission in the CLI, MCP, Node and Go middleware, n8n UI, and ingest paths.

### 2.13.0

* **Cursor cost tracking is now zero-setup** — paste your Cursor team API key into provider settings and Revenium pulls usage every five minutes directly from Cursor's API.
* Added **OpenAI Codex CLI dashboard** — full adoption, cost, and efficiency reporting for Codex CLI on par with the Cursor and Gemini dashboards, with Codex Desktop, App, and CLI unified as a single provider.
* **AI alert emails** now use distinct subject prefixes — `AI Anomaly Alert:` when an alert fires and `AI Anomaly Resolved:` when it resolves — so inbox filters and rules can route them separately.
* Added **HMAC signing for outbound webhooks** — verify that webhook payloads truly came from Revenium using a per-webhook signing secret, with safe rotation and a one-click test-event button.
* Added **Idempotency-Key support on metering** — retry failed metering calls safely with no risk of double-counted usage; identical retries within a 24-hour window are deduplicated server-side.
* Added **standard `X-RateLimit-*` response headers** — Revenium's API now returns predictable per-tenant request budgets with `X-RateLimit-*` and `Retry-After` headers and a documented `/integrations/rate-limits` reference, so customers can program against the limits (This is in addition to the existing 4xx-error-pattern protection shipped in v2.12.0.)
* Added a **coding-assistant pricing mode** in Team settings — choose whether coding-assistant traffic is paid for using API rates or seat-based pricing.
* Improved **AI Insights progress feedback** — determinate progress card with elapsed time, navbar spinner across all routes, sharper empty states, and a period selector on the page.
* Improved **Cost Controls notifications and UI** — fixed spend-display refresh, hard-limit display, mode column and filter parity, Slack link path, deduplicated breach notifications, and clearer "Mode" toggle states.
* Improved **subscription analytics** — user retention cohort analysis, CSV export per segment, pagination, and an unmapped-GitHub-users filter.
* Improved **Webhooks discoverability** — moved into the Alerts tab where customers already manage notification channels.
* Improved **Python SDK** with a built-in agentic outcomes API, cost-controls + circuit breaker integration, and renamed `ReveniumCostLimitExceeded` to `BudgetExceededError` for clearer error handling.
* Updated **Node middleware** with separate metering and enforcement circuit breakers so an enforcement issue cannot stop metering.
* Updated **Go middleware** to derive cost-control scope from filter dimensions.
* Fixed **traces page** chart-axis, label, and date-picker alignment on cost, performance, and efficiency views.
* Fixed **advanced search filters** silently falling back to the default date range on the Logs page.

### 2.12.0

* Added **AI Insights** — a new analytics surface that runs your usage data through an AI Recommendations Engine and returns prioritized, actionable findings with potential monthly savings, severity, and suggested actions.
* Added **Cost Controls** — define Budget Rules with dimensional filters, Slack and webhook notification channels, and a per-rule event log. Runtime enforcement is now available across Revenium's SDK library, including Node, Go, and Python, so spend limits are enforced at the call site.
* **Enhanced AI Coding Adoption analytics** — scatter plot grouping users by output and engagement, segment tabs and badges across the Value-by-User table, derived metrics columns (Cost per PR, Adoption rate, Tokens per Session) and session efficiency metrics.
* Added **Claude PR attribution via Co-Authored-By** — Revenium now detects Claude-assisted pull requests, attributes them to the correct user and team, and exposes a sortable PRs-with-Claude column on the Adoption tab.
* Added **provider credit tracking for AWS Bedrock and GCP Vertex** — provider-issued credits are captured, surfaced per-provider on the Provider cost dashboard, and applied in billing analytics so reported spend reflects what you actually pay
* Added **Revvy Onboarding Agent & CLI** — a new agent-driven instrumentation assistant that helps you onboard your application to Revenium. It includes an AI callsite search, code integration guidance, GitHub Actions template, and machine-readable call-site manifest for AI agents.
* Updated **MCP Server** with improved error handling and additional API coverage
* Improved **team-switch reliability** in the web application
* Improved **multimodal alert metric guidance** in the Create Alert flow
* Fixed edge case bugs in **resolved-alert notifications** that were silently failing to deliver to Slack and email

### 2.11.0

* Added Claude Cowork Dashboard with per-user value reporting, cost by model, token and cache utilization breakdowns, and a one-line OTLP configuration from the Claude Desktop admin UI that instruments your entire company's Cowork usage with zero per-machine setup
* Added GitHub integration for AI Coding Dashboard team attribution — map Claude Code usage to teams via PR authorship to directly correlate Claude Code usage to the outcomes that matter
* Added scoped API key permissions — create read-only, metering-only, or full-access keys per integration; legacy keys continue to work unchanged
* Added environment filtering across Logs and Traces — filter by dev, staging, prod, etc.
* Added a unified Go metering SDK with first-class support for Anthropic (streaming + vision), Google (chat, embeddings, image, video), fal.ai (Run/Subscribe/Stream), LiteLLM (with SSE streaming), and the Responses API
* Added clickable ROI cards — click any box on the ROI page to drill into detailed job filtering
* Updated MCP Server to FastMCP 3.x, Tool Registry management with pricing tiers, Jobs & Outcomes management, and expanded analytics wiring for cost-by-user and tool costs
* Improved Pricing sidebar organization by splitting Cost Sources and Revenue Sources into dedicated sections

### 2.10.0

* Added redesigned navigation with Costs & Revenue Attribution promoted to first-level tabs, sticky headers, and new date picker across dashboards
* Added global search command palette (Cmd+K / Ctrl+K) for instant navigation to any page or entity
* Added search and value range filtering to Jobs API, with user-supplied job identifiers as primary keys
* Added default organization preference — set your preferred organization to auto-load on login
* Added per-million-token pricing display across AI Models pages with sub-cent tooltips
* Added starred dashboards and revamped My Dashboards from card grid to sortable data table
* Added organization tree view with full hierarchy and pagination for large org structures
* Added coding assistant toggle to Logs page for filtering AI coding tool metrics
* Improved performance of AI Assistants API endpoints
* Updated MCP Server to FastMCP 3.x, added support for AI jobs, outcomes, and tool cost management
* Updated Go middleware with centralized core architecture including circuit breaker, retry, and tool event metering

### 2.9.0

* Added ROI Dashboard with conversion funnels, revenue vs cost analysis, job transactions, and per-job ROI tracking
* Added Cursor AI Coding Dashboard with usage reporting & subscription management
* Added Revenium Coverage Ratio showing what percentage of provider spending is metered by Revenium
* Added real-time sync status and freshness indicators to the Provider Dashboard
* Added URL-based date filter persistence across dashboards, enabling bookmarking and sharing
* Added Jobs API support to the Revenium metering SDKs
* Added fal.ai middleware wrapper for Node.js and Go
* Added LiteLLM Go middleware for LiteLLM proxy integration
* Added multimodal metering for Imagen, Veo, and Gemini Vision to the Google Python middleware
* Added LangChain SDK
* Updated MCP Server with higher-performance analytics endpoints and expanded test coverage
* Updated middleware packages across 5 providers with canonical model name resolution
* Improved AI Provider billing sync reliability — historical syncs no longer time out on large datasets

### 2.8.0

* Added native OpenTelemetry GenAI semantic conventions support, enabling direct ingestion from LangChain, OpenLLMetry, Traceloop, and any OTel-instrumented AI application
* Added gRPC OTLP endpoint (port 4317) for zero-configuration integration with standard OpenTelemetry exporters
* Added share-to-Slack and share-to-email for charts and dashboards
* Added Tool Registry Logs tab for reviewing tool event history
* Added budget-specific creation flow from the Budgets dashboard
* Added multimodal pricing column and provider/modality filters to AI Models pricing page
* Added custom provider support when adding new AI models

### 2.7.0

* Added Tool Registry Analytics Dashboard with 11 charts covering tool cost distribution, agent breakdown, and cost iceberg views
* Added full multimodal pricing: audio token pricing for GPT-4o Realtime/Transcribe, bidirectional audio cost tracking, DALL-E 3 size-variant pricing refinements, and HD TTS pricing deduplication
* Added VIDEO\_COUNT, AUDIO\_COUNT, duration, characters, and credits as first-class metrics in the alert system and chart builder
* Added Custom Dashboards with modality grouping and subscriber/user breakdowns for improved query performance
* Added provider dashboard drill-through — integration status cards are now clickable with provider-specific detail
* Added configurable concurrency for AI metrics processing
* Added subscriber/user grouping in chart builder
* Improved line item processing latency with direct async event-based processing
* Improved billing calculation performance for high-volume accounts
* Improved AI metric alert monitoring performance
* Improved element aggregation performance
* Fixed a type error in VIDEO\_COUNT/AUDIO\_COUNT alert evaluation
* Fixed customer cost query grouping and sync logs operation filter
* Fixed bar chart rendering artifacts, donut chart sizing, and y-axis label formatting

### 2.6.0

* Added multimodal image pricing with DALL-E 3 size-variant cost attribution for accurate per-call billing
* Added pixel-based cost calculation for image generation models
* Added FOCUS v1.0 compliant cost export, enabling direct integration with FinOps platforms
* Added customer product profitability charts to the pre-defined dashboard library
* Added session count metric to the AI traces analytics endpoint
* Added unified delete endpoint for AI metrics
* Improved metering throughput
* Improved alert monitoring performance
* Fixed bug in custom pricing support for AI completion metrics
* Fixed dashboard editing controls
* Fixed Google SSO token initialization race condition
* Relabeled "Sessions/User" to "Requests/User" on AI Coding dashboard for accuracy

### 2.5.0

* Added AI Coding Dashboard supporting multiple coding assistants (Claude Code, Gemini CLI) with organization-level views
* Added Connections page for unified API credential and provider integration management
* Added Custom Dashboards with improved analytics performance
* Added role-based prompt viewing permissions with admin controls
* Added Relative Change Alerts with task type filtering for monitoring usage trends
* Added OpenAI audio cost tracking for Whisper (STT) and text-to-speech services
* Added multimodal pricing sync for FAL and Runway providers
* Improved credential input UX with structured form fields for AWS Bedrock, LiteLLM, and PiAPI
* Improved query performance for trace and AI transaction endpoints
* Fixed pagination navigation and advanced search parameter handling
* Fixed SSO token handling stability

### 2.4.0

* Added support for Claude Code usage metering
* Added Claude Code Dashboard with cost analysis, token analytics, user attribution, and model comparison views
* Added support in all middleware for sending prompt data to revenium for analysis (requires manual opt-in)
* Added Prompt Viewer modal with message visualization, role-based coloring, and metrics context
* Added webhook notification channel for alerts with retry logic and circuit breaker patterns
* Added extended time ranges: 90 days, 6 months, 12 months, and custom date ranges for all analytics queries
* Added non-token AI cost tracking for audio, image, and video AI services
* Added Gemini CLI telemetry support
* Added Fal.ai and Runway ML integrations via Go middleware
* Added Perplexity Python SDK support
* Added connection status indicators in UI to quickly provide data ingest status
* Added multi-field search for Products API across name, owner email, and asset sources
* Simplified OpenRouter credentials management
* Improved AI transaction details modal with dedicated sections for cost, provider, timing, and tokens
* Fixed duration display inconsistencies across all views
* Fixed notification template logo display and email formatting
* Fixed Slack OAuth redirect URI handling
* Fixed chart flickering occurring in some situations


# Instrument Your Code

The fastest, lowest-maintenance way to send cost data to Revenium is the SDK plus your existing provider client (OpenAI, Anthropic, LiteLLM, etc.). The SDK handles the metering payload — including required fields and attribution — so you don't need to construct it yourself.

### Send Data via the SDK

The Revenium Python SDK instruments your existing provider clients with a single line of code. Set your metering API key in the environment first — the SDK still instruments the client without it, but it submits nothing and logs a warning rather than raising, so metering appears to work while no data arrives:

```bash
export REVENIUM_METERING_API_KEY="your-key"
```

```python
import revenium_middleware.openai  # auto-instruments the OpenAI client on import
from openai import OpenAI

client = OpenAI()  # completions are metered to Revenium once the key above is set
```

For other languages and providers (LiteLLM, OpenRouter, Anthropic, Google), see [SDK Setup](/integrations/sdk-setup). The SDKs document the full set of supported fields, attribution metadata, and language-specific patterns in their READMEs and example libraries — treat them as the canonical reference for what to send.

### Already on OpenTelemetry?

If your stack already emits OpenTelemetry, you don't need to add Revenium-specific instrumentation. Revenium accepts OTLP traces, metrics, and logs directly — point your OTel collector at the Revenium OTLP endpoint and your existing spans flow in, with span identifiers carrying over without remapping. For setup details, endpoints, and authentication, see [OTLP Integration](/integrations/otlp-integration).

### Enrich Calls with Business Attribution

Out of the box, the SDK sends model, token counts, and cost. To unlock the full dashboard — cost by customer, cost by product, agent ROI, trace analytics — pass attribution alongside each call:

* **`organizationName`** — the customer account (parent company). The backend now requires `organizationName`; the legacy `organizationId` alias is silently dropped.
* **`productName`** — the commercial tier or SKU the customer is on. The backend now requires `productName`; the legacy `productId` alias is silently dropped.
* **`subscriber`** — sub-object identifying the end customer: `{ id, email, credential: { name, value } }`.
* **`agent`** — the specific agent making the call. Powers per-agent cost views and the Tool Registry.
* **`traceId`** — links sequential AI calls into a single workflow for Trace Analytics.
* **`taskType`** — categorises what the agent was doing (qualification, support, code review, etc.).

The more attribution you send, the more dimensions become available in dashboards, alerts, and cost controls. For the complete field list including subscription, quality scoring, and cost-control fields, see [SDK Setup → Usage Metadata](/integrations/sdk-setup#usage-metadata).

### What You Can Meter

Revenium accepts more than just LLM completions. Send any combination of these event types — each has its own pricing curves and its own dashboard slice, so spend never collapses into a single number:

| Event type           | What it captures                                                                                               | Reference                                                                                                        |
| -------------------- | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| **AI completions**   | LLM API calls — OpenAI, Anthropic, Bedrock, Google, and the long tail of providers                             | [SDK Setup](/integrations/sdk-setup) · [API Reference](https://revenium.readme.io/reference/meter_ai_completion) |
| **Tool events**      | Agent tool and function-call invocations — often as expensive or more than the LLM call itself                 | [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage)                                     |
| **Agent outcomes**   | Terminal business result of an agent run — CONVERTED, DEFLECTED, ESCALATED, CUSTOM, with optional dollar value | [AI Outcomes](/instrument-your-agents/agent-outcomes)                                                            |
| **Image generation** | Image workloads (DALL·E, Stable Diffusion, fal.ai, provider-native vision)                                     | [API Reference](https://revenium.readme.io/reference/meter_ai_images)                                            |
| **Audio operations** | Speech-to-text, text-to-speech, transcription                                                                  | [API Reference](https://revenium.readme.io/reference/meter_ai_audio)                                             |
| **Video operations** | Video generation, analysis, captioning pipelines                                                               | [API Reference](https://revenium.readme.io/reference/meter_ai_video)                                             |
| **Custom events**    | Arbitrary consumption units — OCR pages, retrieval rows scanned, document enrichments                          | [API Reference](https://revenium.readme.io/reference/meter_event)                                                |

Multimodal workloads benefit most from the dedicated endpoints — they apply the correct pricing curves automatically. Use custom events only when the unit you bill on doesn't fit a structured type.

### Beyond Standard Tokens: Quality & Custom Metrics

Most teams start with tokens and latency. As AI workloads mature, two more dimensions become valuable:

* **Response quality measurement.** Cost and latency tell you what you spent — they don't tell you whether the output was any good. The SDK can carry a quality score per call, sourced from whatever evaluation logic you trust: RAGAS-style retrieval evaluation, LLM-as-a-judge pipelines, downstream user feedback, or a human review queue. Once recorded, dashboards correlate quality against cost, model choice, agent, and customer — so you can see whether the cheaper model is actually losing you revenue, or whether one agent's outputs are systematically weaker than another's.
* **Custom consumption metrics.** Some workloads are billed or evaluated in units that aren't tokens, audio seconds, or image counts — pages parsed by an OCR pipeline, rows scanned by a retrieval index, documents enriched by an extraction agent. Revenium accepts arbitrary numeric metrics alongside the standard event, so these workloads show up in cost-by-product and per-customer dashboards alongside LLM spend. Particularly useful when you're charging customers for an outcome rather than for tokens.

### Direct API Integration

If you can't use the SDK (unsupported language, custom proxy, etc.), see the [API Reference](https://revenium.readme.io) for the raw payload schema across all the event types listed above.

### Related

* [SDK Setup](/integrations/sdk-setup) — provider wrappers, language coverage, the canonical field reference
* [Provider Integrations](/integrations/provider-integrations) — OpenAI, Anthropic, LiteLLM, OpenRouter, fal.ai
* [OTLP Integration](/integrations/otlp-integration) — for stacks already on OpenTelemetry
* [AI Outcomes](/instrument-your-agents/agent-outcomes) — close the ROI loop
* [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage) — meter tool calls alongside LLM calls
* [API Reference](https://revenium.readme.io) — raw HTTP API for direct integrations


# Monitor Infrastructure Costs

Before you can control AI spend, you need to know where it's actually coming from. Revenium connects directly to your AI provider accounts and immediately surfaces the complete picture — what you're spending, where it's going, and how much of it you actually have visibility over.

Head to **Connections > Providers** to connect your accounts, then navigate to **Overview** to see your spend broken down across three views.

> 💡 **Getting the most from this section:** Provider-level data gives you top-down visibility across your entire AI footprint. For deeper attribution — by customer, product, or feature — make sure you are also passing metadata when you [Instrument Your Code](/track-and-control-costs/instrument-your-code). The two work together.

***

### 1. Providers: How Much of Your Spend Can You Actually See?

The most important number here isn't your total cost — it's your **Coverage Ratio**.

This tells you what percentage of your provider bill is actively metered and under Revenium's financial control. Anything below 100% is unaccounted spend: workloads running outside your instrumented infrastructure, forgotten scripts, or environments that haven't been connected yet. Until those gaps are closed, you're making budget decisions on incomplete information.

Alongside coverage, you can see:

* **Cost by workspace:** Break spend down by internal team or environment — production vs. staging, one business unit vs. another — so cost ownership is clear rather than pooled into a single bill nobody owns.
* **Period-over-period comparison:** See immediately whether total spend is trending up or down, without waiting for a monthly invoice to tell you something went wrong two weeks ago.
* **Provider credits and net spend:** For providers such as AWS Bedrock and Google Vertex AI, Revenium can track provider-issued credits and apply them to billing analytics. This helps distinguish gross AI usage from the net spend you actually pay after credits are applied.

**Provider billing charts.** The provider cost dashboard includes a dedicated provider billing chart that visualizes your provider spend over time, so you can see the shape of the bill rather than just its total. The chart is team-scoped: it respects the team currently selected in the product, so the spend you see lines up with the active team rather than mixing teams together. Switch teams from the selector and the chart re-scopes to that team's provider spend.

<figure><img src="/files/vfEc7eHxNtQifHqFX4Wo" alt="" width="563"><figcaption></figcaption></figure>

***

### 2. Models: What Are You Actually Paying Per Token?

Provider pricing pages show list prices. Revenium shows you what you're actually paying, calculated against your real usage patterns.

**Model Efficiency** gives you the true cost per million tokens for every active model in your organization, normalised across providers so you can make direct comparisons. A model that looks cheap in a benchmark can look very different once your specific workloads are factored in.

* **Model Efficiency table:** Rank every active model by cost percentage, request volume, average tokens per USD, and trend. Use it to identify models whose cost share is growing faster than their request share — a reliable signal that usage patterns have shifted in a way worth investigating.
* **Period-over-period comparison:** Validate whether a recent model swap has delivered the savings it promised, or whether costs have quietly crept back up.

***

### 3. API Keys: Find the Spend You Didn't Know You Had

API keys are where financial accountability breaks down in most organizations. The number of active keys is almost always higher than anyone expects, and a meaningful portion of them are typically operating entirely outside your metering coverage.

* **API Key Analytics:** See every active key across your connected providers with a full breakdown of cost, token volume, request count, and trend. Keys that are spending without appearing in your metered traffic are either candidates for instrumentation or candidates for deactivation — either way, they shouldn't stay invisible.
* **Cost concentration:** Quickly identify whether spend is distributed across many keys or driven by a handful. Knowing where it's concentrated tells you where to focus your instrumentation effort first.

> **Through MCP, conversationally.** The questions this page is built around — where is my spend, what's driving it, which keys are responsible — are exactly the kind of questions an AI assistant connected to Revenium via the MCP Server can answer in chat. Ask "what's my total AI spend this month and which providers does it break down to?", "which models have the highest cost share right now?", or "are any API keys driving an unexpected portion of the bill?" The agent runs the queries, breaks the data down across providers, models, customers, agents, or API keys, and tells you what it finds. Useful for the kind of monthly or weekly check-in that's easy to skip when there's no room in the dashboard rotation.


# Analyze ROI & Unit Economics

Once your code is instrumented and sending telemetry, Revenium instantly translates your raw AI logs into financial realities. This section of the platform is where engineering, finance, and product teams align to measure the true profitability of your AI features.

By navigating to the **Costs & Revenue** section in your sidebar, you unlock several targeted dashboards designed to expose hidden costs and calculate exact profit margins.

> 💡 **Prerequisite:** To get the most out of these dashboards, make sure each metering call carries attribution metadata — at minimum, who the customer is, which product they're on, and what kind of task the call was for. Revenium uses these tags to aggregate your unit economics. See [Instrument Your Code → Business Attribution](/track-and-control-costs/instrument-your-code#enrich-calls-with-business-attribution) for the full list.

***

### 1. The ROI Dashboard: Measure Business Outcomes

*The ultimate high-level view of your AI's profitability.*

The ROI tab shifts the focus from engineering metrics to business metrics. It helps you answer: **"Is our AI actually making us money?"**

* **The Conversion Funnel:** Track the drop-off between a job starting, a technically successful LLM execution, and a completed business conversion (e.g., a closed sale or deflected ticket).
* **Total Value vs. Operational Cost:** Compare the estimated revenue generated by successful conversions directly against the total cost of the AI compute to calculate your true ROI percentage.

The ROI dashboard is the *view*; outcomes are the data that feeds it. Without outcome reporting (see [AI Outcomes](/instrument-your-agents/agent-outcomes)), the dashboard has cost but no value side to ratio against. Every reported outcome becomes a row on the Conversion or Cost Avoidance funnel and contributes to the headline Value Ratio.

<figure><img src="/files/leT5kV2TzWEUUmrzvuv6" alt="" width="563"><figcaption></figcaption></figure>

### 2. Top Movers: Spotting Rapid Cost Changes

*Identify exactly who or what is driving sudden spikes in your bill.*

Instead of hunting through line charts to find anomalies, the **Top Movers** tab immediately highlights the biggest period-over-period changes in your AI spend.

* **Track the Deltas:** See exactly which entities have the highest percentage increase (or decrease) in cost compared to the previous period.
* **Cross-Entity Visibility:** Instantly view the biggest movers across four key dimensions: **Agents, Models, Customers, and Products**.
* **Catch "New" Spend:** Quickly spot if a newly deployed agent, a new customer, or a newly swapped model has suddenly started incurring significant costs.

### 3. Tasks & Agents: Granular Cost Breakdown

*Identify exactly which workflows are consuming your budget.*

If your overall costs are spiking, the **Tasks** and **Agents** tabs help you isolate the culprit.

* **Task Cost Trends:** Group your AI spend by specific operations (e.g., "document\_summarization" vs. "deep\_research"). See the average cost per request by task type, allowing you to compare if a specific model is suddenly becoming too expensive for a routine task.
* **Agent Spend Over Time:** If you are running autonomous agents, track their individual burn rates. Easily spot if a specific agent (like your "support\_triage\_agent") is looping or calling external APIs too frequently compared to others.

### 4. Traces & Anomalies: Catching Outliers

*Find the hidden spikes destroying your profit margins.*

Not all AI executions cost the same. The **Traces** dashboard is designed to hunt down the expensive outliers.

* **Cost Anomalies:** Automatically surface Critical (P99) and High (P95) cost anomalies. If a specific trace suddenly costs 40% more than its historical average, it will be flagged here for immediate investigation.
* **Most Expensive Trace Types:** See your cumulative spend broken down by individual trace types over the last 24 hours to quickly triage code inefficiencies.

### 5. Products & Customers: True Unit Economics

*Ensure every user and pricing tier is profitable.*

This is the most critical view for Product and Finance teams building usage-based billing or SaaS subscriptions.

* **Customer Profitability:** Track the exact AI cost to serve individual customers over time. Instantly spot power users who are consuming more AI compute than they pay for in their monthly subscription.
* **Product Tier Margins:** Compare the aggregate costs and revenues across your different product tiers. Verify that the markups on your "Pro" or "Enterprise" plans are accurately covering the cost of the expensive reasoning models assigned to those tiers.

### 6. Budgets: Standing Guardrails on Your Spend

Track ongoing spending limits against any dimension that matters to your business.

The other dashboards on this page tell you what *did* happen. The Budgets tab tells you what's *currently happening* against the limits you've set, so you can see at a glance whether anything is about to go off the rails.

* **Risk-classified budgets**: Every active budget is automatically classified as Low, High, or Critical risk based on how much of its allocation has been consumed and how much time remains in the period. The summary cards at the top of the page surface the totals immediately — total budgets active, how many are at risk right now, total spend across all budgets, and average usage percentage.
* **Per-budget tracking**: Each budget shows its current spend, what percentage of the limit it has consumed, and how long until it resets. A budget at 89.27% used with 10 hours until reset is a different conversation than one at 32.22% — both are visible on the same screen.
* **Grouped budgets**: Set a single budget per-entity rather than one global limit. A grouped budget of $100 per customer, for example, applies the same threshold to every customer individually and tells you how many of them are at risk. The right shape for SaaS products with many similar customers, where one global cap doesn't make sense.
* **Sort by risk**: When you have many budgets, sort by risk descending to put the ones most likely to go over at the top. The 10-second answer to "is anything about to blow up?"

Use this view as the morning-coffee check on your AI spend. If everything is green, no action needed. If something is High or Critical, you know exactly which budget, how much of it has been consumed, and how long until the period resets — enough to decide whether to investigate, raise the limit, or let it ride.

> **Through MCP, conversationally.** Real investigations cross between these dashboards. A cost question becomes a customer question becomes an agent question becomes a model question. An AI assistant connected to Revenium via the MCP Server can follow that thread without you switching tabs. Ask "why did costs spike yesterday and which customers were affected?", "which agents got more expensive over the last week?", or "set me an alert if any customer's spend rises more than 20% week over week" and the agent runs the queries, breaks the data down across providers, models, customers, agents, or API keys, and gives you the answer in one pass. Useful when the question cuts across more than one of these views.


# Build Custom Dashboards & Charts

Revenium's Intelligence dashboards answer the most common questions about AI spend and performance. Custom dashboards and charts go further — giving you the flexibility to build exactly the views your business needs, scoped to the metrics, customers, agents, and time windows that matter to your team right now.

Find your dashboards under **My Dashboards** in the left sidebar, and your custom charts under **Chart Builder**.

***

### <i class="fa-square">:square:</i> Dashboards

A dashboard is a collection of charts organised around a purpose. The most useful ones are built with a specific audience in mind — a weekly finance review, a post-incident engineering debrief, a per-customer profitability summary for your account team.

#### Building a Dashboard

1. Click **+ Add Dashboard** and give it a name and description that will mean something to whoever opens it.
2. Click **+ Add Chart** to pick from the pre-built library — searchable, with a short description of what each chart shows.
3. Arrange your charts on the canvas, then hit **Done Editing** when you're ready.

Each chart can be shared, exported as a PNG or CSV, or copied to your clipboard directly from the dashboard.

#### Deleting a Dashboard

You can remove a custom dashboard directly from its row in **My Dashboards**. Deleting asks you to confirm first, so a dashboard isn't removed by accident. System dashboards — the built-in Intelligence views — and dashboards you only have read-only access to stay protected and can't be deleted, so managing your own custom views never puts the standard reporting at risk.

#### The Pre-Built Chart Library

The library covers the most common reporting needs across cost, revenue, performance, and profitability. A few highlights:

* **Customer Cost Over Time** — how spend per customer trends day by day, useful for spotting who's growing fastest before it becomes a billing conversation.
* **Customer Profitability** — cost against margin per customer, so you can see at a glance who's profitable and who isn't.
* **Task Performance by AI Model** — cost and time per task broken down by model, for validating whether a model change is actually performing better.
* **Token and Tool Cost** — separates raw token spend from external tool call costs over time, essential for agentic workflows where tool costs frequently dwarf token costs.
* **Revenue / Product** — revenue generated per product tier, for pairing against cost data to get to true margin.
* **Provider Comparison** — a prefilled template that opens in the Chart Builder with provider billing and metered usage placed together, so you can line up what a provider bills against the usage Revenium meters for it without building the view from scratch. Add it to any dashboard like any other chart, then adjust the metric, grouping, filters, or time window to fit your team.

<figure><img src="/files/dd3DCWLAxOUpVuUIeweV" alt="" width="563"><figcaption></figcaption></figure>

***

### <i class="fa-pen">:pen:</i> Custom Charts

For more specific questions — the metric combination that maps to how your team thinks, or a view scoped to a single customer, agent, or environment — the chart builder gives you full control.

Head to **Chart Builder** and click **+ Create Chart**. As you configure your chart, a live preview updates in real time alongside a configuration summary, so you can see exactly what you're building and catch anything worth adjusting before you save.

#### Your Metric

The base metrics cover everything Revenium tracks: Total Cost, Request Count, Token Count (input and output separately), Latency, Error Count and Rate, Image Count, Duration, Character Count, and Credits Consumed.

Pair that with a calculation — Total, Average, Per-Request Average, Per-Token Average, Per-Entity Average, Median, or Maximum — and the question your chart answers becomes precise. Total Cost tells you how much you spent. Per-Request Average tells you whether efficiency is improving.

#### How the Data is Grouped

The Primary Group By controls how the data is sliced — by Customer, Model, Provider, Agent, Product, Task, Subscriber, or Modality. This is where a single metric becomes a genuinely useful view. Total Cost grouped by Agent shows which agents are burning the most. Error Rate grouped by Model tells you whether a particular model is underperforming. Latency grouped by Task shows which operations are slow regardless of which model handles them.

#### Filters

Filters let you scope a chart to exactly the slice of data you care about — a specific customer, a single environment, a particular task type, an error reason, or only streamed responses. A chart tracking Total Cost by Model is useful. The same chart filtered to your production environment and scoped to a single customer tier is actionable.

#### Time Window

Date ranges run from the last hour through to the last 365 days, with a custom range for anything in between. Time grain can be set to daily or weekly, or left on Auto for Revenium to choose the most readable resolution for the window you've selected.

> **💡 Tip:** Once saved, any custom chart is available to add to any dashboard — giving you a reporting layer that reflects exactly how your team thinks about AI performance, not just how the platform does.

***

### <i class="fa-building">:building:</i> Examples Worth Building

**"Is our Enterprise tier profitable?"** Total Cost, grouped by Product, filtered to your Enterprise tier — alongside a Revenue / Product chart on the same dashboard to see margin in context.

**"Which customers are consuming disproportionately?"** Total Cost, Per-Entity Average calculation, grouped by Customer, Focus Method set to Top N Items. Surfaces the highest-consuming customers without the rest of the data obscuring them.

**"Is this agent getting more expensive over time?"** Total Cost, grouped by Agent, filtered to a specific agent, Line Chart over Last 90 Days. A rising line not matched by a rise in request count is a signal worth investigating.

**"Where are errors actually happening in production?"** Error Rate, Average calculation, grouped by Model, filtered to your production environment. Shows which models are failing where it matters, not just in aggregate.


# Set Budgets & Alerts

Visibility into your AI spend is only half the picture. The other half is knowing the moment something changes — before a runaway agent, an unexpected usage spike, or a newly onboarded customer turns into a bill you didn't see coming.

Revenium's Guardrails let you define exactly what to watch, set the conditions that matter to your business, and get notified through the channels your team already uses — or stop the spend outright. Open **Guardrails** under **Spend Management** in your sidebar to get started.

***

### Guardrails

Guardrails brings spend notifications, limits, enforcement, and rule history into one place. Use a Guardrail to define what spend to watch, narrow where the rule applies, and choose whether Revenium should notify your team, enforce a hard cap, or do both.

#### How Guardrails work

1. Open **Guardrails** under **Spend Management**.
2. Create a Guardrail and choose the spend you want to watch.
3. Apply the available filters to narrow the rule's scope.
4. Choose a response: notifications, enforcement, or both.
5. Add a custom message when the Guardrail can block a request.
6. Review the Guardrail from the list and use its history to inspect activity.

#### Create a Guardrail

**Watch spend**

Guardrails can monitor two kinds of cost data:

* **Provider billing data** — spend synchronized from a connected provider account. Use this data for notifications because it arrives after the provider has processed the usage.
* **Revenium-metered data** — usage observed through a supported SDK integration. Cumulative limits on this data can be checked before a request is sent.

Provider billing data is not available soon enough for request-time enforcement. To enforce a hard cumulative cap, use Revenium-metered data.

**Choose when it applies**

Use the filters available in the Guardrail form to limit which metered activity the rule evaluates. The same scope is carried into enforcement so the hard cap applies only to matching requests.

**Notify or enforce a cap**

Choose the response that fits the rule:

* **Notify** — route the event to an available email, Slack, or webhook destination. The destinations shown depend on whether enforcement is also enabled.
* **Enforce** — stop a matching SDK-metered request when its cumulative limit has been reached.
* **Notify and enforce** — block the request and route the event through the notification options available for the rule.

An enforced request does not rely on provider billing data. The check uses cumulative usage metered through the SDK so it can happen before the provider processes the request.

**Add a custom block message**

Add customer-authored text to explain why a request was blocked and what the developer should do next. Revenium stores the message with the Guardrail and makes it available with the compiled enforcement rule used by the SDK.

Keep the message specific to the policy. For example, identify the limit that was reached and the team or process to contact, without including credentials or sensitive account details.

#### Review Guardrails and history

The Guardrails list combines notification-only rules and enforced limits in one view. Open a rule's history to inspect its recorded activity and follow the rule from configuration into review.

#### Read-only access

A user with read-only access can inspect the Guardrails list and history. Create, toggle, reset, edit, and delete actions are unavailable.

For broader role guidance, see [Manage Users & Teams](/account-and-resources/manage-users-and-teams).

#### Create a Guardrail from AI by Employee

The active AI by Employee view can prefill a new Guardrail with the current employee analysis scope. Review the form before submitting it: opening the hand-off does not create or save a rule automatically.

See [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend#ai-by-employee) for the employee analysis workflow.

***

### Cost Controls

A Guardrail can be used as an active Cost Control, not just a passive notification. When runtime enforcement is enabled in a supported Revenium SDK, the SDK checks the rule before the model call is sent. Calls blocked by a Cost Control rule do not reach the provider and do not create a metered transaction.

Cost Control rules support **dimensional filters** — scope a rule to a specific organization, product, agent, model, or task type rather than applying it globally. For example, a rule that caps spend per customer applies independently per `organizationName` and triggers only when that customer's usage exceeds the budget. Combining dimensional filters with runtime enforcement gives per-customer, per-product, or per-agent guardrails that fire at the call site.

Use this mode for production guardrails where the right answer is to stop spend at the call site. Use a notification-only Guardrail when the workload should continue but the team needs visibility through Slack, email, webhook, or Alert history.

***

### <i class="fa-bell">:bell:</i> Creating a Guardrail

Guardrails are built in four steps: define what you're watching, set the trigger condition, choose how you want to be notified, and review before saving.

Open **Guardrails** under **Spend Management** and start a new rule to begin.

#### Step 1: Metric & Scope

Choose the metric you want the Guardrail to monitor and narrow the scope to the data that matters.

**The available metrics cover the full range of AI economics:**

* **Total Cost** and **Cost per Transaction** — for spend-level guardrails across your entire operation or per individual request.
* **Tokens per Minute** and **Requests per Minute** — for rate-based monitoring, useful for catching agents that are looping or hammering external APIs.
* **Error Rate** and **Error Count** — for quality and reliability guardrails, so degrading model performance doesn't go unnoticed.
* **Token Count**, **Input Tokens**, **Output Tokens** — for granular usage tracking at the token level.
* **Image, Video, and Audio Count** — for multimodal workloads where generation volume drives cost.
* **Cost per Image**, **Cost per Second**, **Duration**, **Credits Consumed** — for workload-specific efficiency monitoring.

**Scope it down with filters and grouping.** Filters let you focus the Guardrail on a specific dimension — a particular Organization, Credential, Product, Model, Provider, Agent, Subscriber, or Task Type. Grouping goes further: when selected, the Guardrail evaluates the condition separately for each member of that group, so a single Guardrail on Total Cost grouped by Agent will fire individually for any agent that crosses the threshold — not just when the aggregate does.

**Choose the data source: Metered or Billed.** Guardrails can watch two different kinds of cost. Two buttons at the top of the Guardrail form — **Metered** and **Billed** — select which:

* **Metered** — the default. The Guardrail evaluates against usage metered through your instrumented traffic — the completions, tokens, and events flowing through your SDKs, middleware, and OpenTelemetry exporters.
* **Billed** — the Guardrail evaluates against provider-level spend pulled from a connected provider account. Selecting Billed reveals a provider dropdown populated from your connected credentials; pick the provider account you want to watch. Use this to watch cost coming directly from a provider bill, including spend from workloads that aren't yet fully instrumented.

Billed Guardrails are evaluated per organization, so each organization's spend is assessed independently and one organization's data cannot bleed into another's evaluation.

**Cumulative budget periods**

Cumulative budget periods — tracking spend continuously over a **Day, Week, Month, or Quarter** — are available today for Guardrails watching Revenium-metered (SDK) data, since usage is metered as requests happen. Pick the period that matches how you budget; when the calendar period rolls over, tracking resets and starts accumulating again from the new period's start.

Billed spend syncs once a day, so a Billed Guardrail instead compares your synced spend against a threshold you set, evaluated against the most recent day the provider has fully confirmed — a daily spike check rather than a running period total. To track Billed-sourced spend across a Week, Month, or Quarter as a single cumulative budget, meter that traffic through a Revenium SDK; see [SDK Setup](/integrations/sdk-setup).

#### Step 2: Define the Trigger Condition

Specify exactly when the Guardrail should fire.

Set an **operator** (greater than, less than, greater than or equal to, less than or equal to) and a **threshold value** — the point at which the condition becomes worth acting on. You can also set a **Persist for (optional)** window, so the Guardrail only fires if the condition holds for a sustained period rather than a momentary blip. This keeps notifications meaningful and reduces noise.

#### Step 3: Configure Notifications

Choose where the notification is sent. At least one channel is required, and you can add multiple.

* **Email** — direct to any address, no setup required.
* **Slack** — connect your workspace and route notifications to the channel where your team already works. Connect Slack from the **Guardrails** configuration screen before building your first Guardrail.
* **Webhook** — send notification payloads to any endpoint. Useful for routing into incident management tools, triggering automated circuit-breaking in your systems, or feeding into your own internal dashboards. Add a webhook URL directly from the notification step, with optional authentication credentials.

> 💡 **Tip:** Webhooks are particularly powerful for agentic workflows — the moment an agent's cost behavior breaks its expected pattern, a webhook can trigger an automated response before the problem compounds.

#### Step 4: Review & Save

A summary of your full Guardrail configuration is shown before saving — metric, scope, filters applied, condition, and notification channels. Review and confirm, and the Guardrail goes live immediately.

***

### <i class="fa-wand-magic-sparkles">:wand-magic-sparkles:</i> One-Click Templates

The Guardrails landing screen offers ready-made templates so you can turn on the most common Guardrails without stepping through the full builder. The set shown is tailored to your [role](/get-started/personalize-your-workspace) — finance-oriented users see spend-focused templates, engineering-oriented users see reliability and usage templates.

Available templates include:

* **Spend jumps >20% week-over-week** — catch sudden cost increases before they compound.
* **Daily spend over a threshold** — get pinged the day spend crosses a limit you set (the dollar amount is editable before you create it).
* **Monthly spend over budget** — know the moment monthly AI spend crosses your budget (editable amount).
* **Unusual model cost spike** — flag any single model whose cost spikes versus its baseline.
* **Error rate climbing** — catch agents and models failing more than usual.
* **Token usage surge** — spot a sudden jump in token consumption.

Click a template to create the Guardrail instantly — it applies across all providers and notifies you by **email** by default. Want to add a Slack channel, or fine-tune scope and thresholds first? Choose **Customize** on any template to open it in the full Guardrail builder described above.

***

### <i class="fa-eye">:eye:</i> Viewing Alert history

The **Alert history** tab on the Spend History page shows every notification that has fired, when it fired, and against what condition. This gives you an audit trail for cost events and makes it straightforward to understand patterns — whether a particular agent consistently trips a spend Guardrail at the same time each day, or a specific customer's usage reliably spikes at month end.

***

### <i class="fa-bell">:bell:</i> Guardrails Worth Setting Up

**Total Cost > threshold, grouped by Agent** — catches any individual agent whose spend breaks out of expected ranges, without needing a separate Guardrail for each one.

**Error Rate > 5%, filtered by Model** — surfaces model-level degradation in production before it affects end users or compounds into failed workflows worth investigating.

**Requests per Minute > threshold, filtered by Product** — rate-based monitoring for a specific product tier, useful for catching unexpected bursts of usage that might indicate a misconfigured client or an agent looping.

**Cost per Transaction > threshold, grouped by Task Type** — flags when a specific type of task is suddenly becoming significantly more expensive per request than its historical average.

> **Through MCP, conversationally.** Setting budget alerts is one of the capabilities the MCP Server explicitly supports. Once an AI assistant is connected to Revenium, alert creation becomes a sentence rather than a four-step form. Tell the agent "alert me on Slack if any single transaction goes over $5", "send me a daily email if total spend exceeds $1,000", or "warn me if AI spend rises more than 20% week over week" and the agent configures it. Useful when the alert idea comes up in conversation — the moment you spot something worth watching, you can wire up the alert without breaking flow.

***

### Related pages

* [SDK Setup](/integrations/sdk-setup) — connect metered usage for request-time enforcement.
* [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend) — analyze employee-level spend and prefill a Guardrail from the active view.
* [Build Custom Dashboards & Charts](/track-and-control-costs/build-custom-dashboards-and-charts) — review spend changes and cost dimensions before deciding what to control.

### Frequently asked questions

<details>

<summary>Can a Guardrail enforce a cap using provider billing data?</summary>

No. Provider billing data arrives after usage has been processed. Hard cumulative caps use Revenium-metered SDK data so the request can be checked before it reaches the provider.

</details>

<details>

<summary>Does opening a Guardrail from AI by Employee create the rule?</summary>

No. The current view prefills the form. You must review and submit it before the Guardrail is created.

</details>

<details>

<summary>What can a read-only user do?</summary>

A read-only user can view the Guardrails list and history. They cannot create, toggle, reset, edit, or delete a Guardrail.

</details>


# Cost Controls

Use Cost Controls to define rules that block AI requests when configured usage limits are reached.

Cost Controls use Revenium's usage metering data to enforce configured AI spend and usage limits. You define a **Cost Control Rule** in the Revenium app; the [Revenium SDK](/integrations/sdk-setup) running inside your application evaluates incoming AI requests against that rule and blocks the request when the limit is reached.

The SDK evaluates rules locally using a cached ruleset that refreshes every 60 seconds by default (configurable via `REVENIUM_CB_POLL_INTERVAL_SECONDS`). If Revenium is unreachable, the SDK continues using its last cached ruleset. If no ruleset has been fetched, enforcement does not run.

{% hint style="success" %}
**New to Revenium?** Cost Controls require Revenium AI metering. If you haven't configured metering yet, start with [instrumenting your code in the quickstart](/get-started/quickstart/5-minute-quickstart#instrument-your-own-code-or-api-traffic).
{% endhint %}

## How it fits with Budgets & Alerts

Cost Controls work alongside [Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts). Alerts notify you when a metric crosses a threshold, budget views show usage against configured budgets, and Cost Controls enforce configured limits before the AI request proceeds.

| Feature                   | When it fires                                       | What it does                                         |
| ------------------------- | --------------------------------------------------- | ---------------------------------------------------- |
| Cost & Performance Alerts | Metric crosses a threshold                          | **Notifies** via email / Slack                       |
| Budget Monitoring         | Tracking view of all threshold-based budgets        | **Visualizes** pace and risk                         |
| **Cost Controls**         | Rule's hard limit is crossed on an incoming request | **Enforces** — blocks the request before the AI call |

Use these features together when you need both visibility and enforcement. For example, configure an alert at 80% of a monthly limit, use the budget view to review usage trends, and use Cost Controls to enforce the limit for a customer, model, provider, or other scope.

***

## Anatomy of a Cost Control Rule

A cost control rule is defined by five things:

1. **Metric** — what you're counting (total cost, token count, error count, …).
2. **Window** — the rolling period you're counting over (daily / weekly / monthly / quarterly).
3. **Hard limit** — the threshold that trips enforcement.
4. **Action** — what the SDK does when the limit is crossed. New rules use **Block** (the only action selectable in the UI today). `THROTTLE` and `WARN_ONLY` are legacy actions retained for historical rules and event-log rendering only.
5. **Scope** — optional filters (this rule only applies to OpenAI) and group-by (broken out per model).

{% hint style="warning" %}
**Total Cost and unpriced models:** Total Cost enforcement requires the model's pricing to be configured in your pricing tier. If a model lacks pricing data, events for that model contribute $0 to the rule and won't trip the threshold. Use Token Count if you need enforcement regardless of pricing coverage.
{% endhint %}

Cost control rules also support these options:

* **Shadow mode** — the rule evaluates but does NOT enforce. Used to validate a limit before promoting it. All new rules default to shadow.
* **Warning threshold** — a soft threshold below the hard limit that fires a warning notification without blocking.

***

## Creating your first Cost Control Rule

Find **Guardrails** under **Spend Management** in the left nav, or search "cost controls" in the Revenium app.

1. **Open Guardrails** — find it under **Spend Management** in the left nav, or search. You'll see the list of existing rules for your team.
2. **Click Create Cost Control Rule** — the dialog walks you through the required pieces.
3. **Name the rule and pick a metric** — give it a descriptive name (this appears in notifications and the enforcement event log) and pick the cumulative metric you want to cap.
4. **Choose a window and limit** — daily / weekly / monthly / quarterly. Windows are calendar-aligned in UTC. Set the hard limit; optionally set a warning threshold below it.
5. **Note the action** — new rules use **Block**. The Cost Controls form does not surface an action selector today; the rule is created with `action: BLOCK`.
6. **Leave Shadow mode on** — it's on by default. Leave it on for the first evaluation period so you can preview what would happen before promoting to enforce.
7. **Scope it (optional)** — add filters or a Group by dimension to narrow the rule (e.g. only OpenAI, broken out per model).
8. **Attach notification channels (optional)** — Slack + webhook channels configured under **Settings → Integrations → Notification Providers** can receive alerts when the rule fires.
9. **Save.** The rule is available for evaluation after the SDK receives the updated ruleset. Because shadow mode is on, requests are not blocked, but matching events appear in the enforcement event log after the rule is evaluated.

***

## Shadow mode vs enforce

New rules start in **shadow mode**. In shadow mode, the rule matches traffic, aggregates usage, sends configured notifications, and records events, but does not block requests.

Shadow mode is the default so you can review matching behavior before enforcement. It lets you:

* See how much traffic a rule would have blocked over a real evaluation window.
* Catch filter mismatches before they affect customers.
* Validate threshold tuning — if a rule would have fired 50 times in the first hour, your threshold is too low.
* Tune notification noise — test the alerting flow without blocking.

### Promoting to enforce

After you confirm the rule matches the intended traffic and threshold, turn **Shadow mode** off. Subsequent hard-limit crossings execute the rule's declared action — **Block** for new rules.

You can do this from the UI by editing the rule and toggling shadow off.

{% hint style="success" %}
**Best practice:** run a new rule in shadow for at least one full window (a monthly rule for a full month, a daily rule for a full day) before promoting. This gives you a more complete view of usage over the rule's evaluation period.
{% endhint %}

***

## Enforcement actions

When a non-shadow Cost Control rule's hard limit is crossed, the SDK executes the rule's action. New rules support only **Block** today:

| Action | What happens                                                                                                                                                                                   |
| ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Block  | The SDK raises a cost-limit exception **before** the AI provider call. The provider never sees the request. Customer code catches the exception and surfaces a graceful error to the end user. |

### Legacy actions (historical)

`THROTTLE` and `WARN_ONLY` are retained in the API and event-log rendering for rules created before the action selector was removed from the UI. They are **not selectable** when creating a new rule today. If you see these actions in the enforcement event log, they originate from a legacy rule.

### Fail-open by default

If the SDK can't reach Revenium (network issue, Revenium outage, expired API key), **enforcement fails open**. The SDK logs the failure and continues using its last cached ruleset. If no ruleset has been fetched, enforcement does not run.

{% hint style="warning" %}
**Stop enforcement for a rule.** Disable the rule in the UI. SDKs pick up the change on the next ruleset refresh. Re-enable the rule when you want enforcement to resume.
{% endhint %}

***

## SDK setup and configuration

Cost Controls require the Revenium SDK in your application. Use the SDK documentation for language-specific environment variables, exception fields, code examples, and troubleshooting:

| SDK         | Where to find it                         | What it covers                             |
| ----------- | ---------------------------------------- | ------------------------------------------ |
| **Python**  | See [SDK Setup](/integrations/sdk-setup) | Python SDK setup and supported providers.  |
| **Node.js** | See [SDK Setup](/integrations/sdk-setup) | Node.js SDK setup and supported providers. |
| **Go**      | See [SDK Setup](/integrations/sdk-setup) | Go SDK setup and supported providers.      |

Each SDK README also links back here for the conceptual walkthrough.

{% hint style="info" %}
Check each SDK README and changelog for current Cost Controls support by language and provider.
{% endhint %}

***

## Reading the enforcement event log

Every evaluation that blocks (or would-block, in shadow mode) writes an immutable event to the **Enforcement Events** log. The log lives on the rule's detail page and can be filtered to a single rule or span all rules for your team.

Each event captures when the evaluation happened, which rule fired, the action declared, whether it was shadow or live, the metric / current value / threshold / percentage at the moment of evaluation, and a masked API-key hint so you can trace it back to the originating request.

Filter the log to shadow events only while tuning a new rule. This shows which requests matched the rule without enforcing the action.

***

## Disabling vs deleting a rule

* **Disable** — the rule is retained for history but skipped at evaluation time. Re-enable any time. Use this to pause a rule temporarily.
* **Delete** — soft-delete. Removed from evaluation but the event history persists for audit. You cannot un-delete; create a new rule if you need the semantic back.

***

## FAQ

<details>

<summary>How quickly does a new rule start enforcing?</summary>

The SDK polls the compiled-rules endpoint every 60 seconds by default (configurable via `REVENIUM_CB_POLL_INTERVAL_SECONDS`). Allow up to one full poll interval for a new rule to reach every running instance of your application. First-time rule creation may take slightly longer because the server's rule compiler must produce the compiled payload — typical end-to-end time is under two minutes.

</details>

<details>

<summary>What happens if my application can't reach Revenium?</summary>

The SDK fails open. It logs the failure and continues using its last cached ruleset. If it has never successfully fetched a ruleset, enforcement does not run.

</details>

<details>

<summary>Does enforcement add latency to my AI calls?</summary>

The SDK's enforcement check is an in-memory comparison against the cached ruleset. Rule-cache refresh happens in a background task and does not block the request path.

</details>

<details>

<summary>Can I have multiple rules on the same metric?</summary>

Yes. Rules are evaluated independently — every matching rule runs. If two rules would both block the request, the first to fail wins. Use the warning threshold on a blocking rule to get notified before the hard limit is hit, or apply both a global and a per-group cap. For notification-only flows on the same metric, see [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts).

</details>

<details>

<summary>How do I cap spend across all my customers, not per-customer?</summary>

Create a rule with **no filters** and **no group by**. It aggregates all your team's AI spend for the window against a single limit. Pair it with a per-customer rule (filter by organization, or group by organization) if you want both a fleet cap and a per-customer cap.

</details>

<details>

<summary>How do I stop enforcement for a rule?</summary>

Disable the rule from the **Guardrails** page. SDKs pick up the change on the next ruleset refresh.

Re-enable the rule when you want enforcement to resume.

</details>

***

## See also

{% hint style="info" %}
**Notification channels** for Cost Control rules (Slack, webhook) are configured in the Revenium app under **Settings → Integrations → Notification Providers**. Once configured there, they appear in the channel picker on the Cost Control rule form.
{% endhint %}

* [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) — adjacent feature: alerts and budget tracking for notification-only flows.
* [SDK Setup](/integrations/sdk-setup) — install the Revenium SDK that evaluates Cost Control rules.


# Attribute Spend to Teams & Departments

Once AI spend is being metered per developer, the next question is always the same one: which team is that spend coming from? Finance wants a chargeback line per department. Engineering leadership wants to know whether the Payments team's usage justifies its seat count. Neither question is answerable from a flat list of individual developers.

Org units are Revenium's answer. You describe your reporting structure once, map each person to a unit, and every cost report can then be grouped by department. The structure lives in Revenium, not in your telemetry, which means you can build it after the data is already flowing, without re-sending or reprocessing a single event.

{% hint style="warning" %}
**Availability.** Org-unit attribution is enabled per tenant rather than being on by default. If the endpoints below return `403 Feature not available`, it is not yet switched on for your account — contact Revenium to have it enabled. Per-team rollups are currently available through the API; a dimension selector in the UI is still to come. See **Current Limits** below.
{% endhint %}

***

### <i class="fa-sitemap">:sitemap:</i> What an Org Unit Is

An org unit is one node in a tree that mirrors how your organization actually reports. `Engineering`, `Engineering/Platform`, and `Engineering/Platform/Payments` are three units, each a child of the one before it.

Each person is assigned to exactly one unit as their **primary** membership, and that assignment is dated. Because the whole tree carries a path, a rollup at `Engineering` includes every descendant beneath it, so you can look at one department or drill into a single squad without maintaining two different structures.

Two ideas do the work here, and both matter for the sections below:

* **A person is not a user account.** Org-unit people are directory records. Creating one does not create a Revenium login, does not send an invitation, and does not require the person to have sent any telemetry yet. You can load your entire roster on day one, before a single developer has been onboarded.
* **Attribution is resolved when you run the report, not when the event arrives.** Nothing about a department is stamped onto a usage event. The department is worked out at query time by looking up who the person was reporting to at the moment the event happened. This is what makes the two behaviours described in **Retroactive Attribution** and **When Someone Changes Teams** below possible.

***

### <i class="fa-file-csv">:file-csv:</i> The CSV Contract

Bulk import takes a CSV with this header:

```
email,org_unit_path
```

An optional third column, `is_primary`, is accepted. Columns are read **by name**, so their order in the file does not matter.

| Column          | Required | Meaning                                                                                    |
| --------------- | -------- | ------------------------------------------------------------------------------------------ |
| `email`         | Yes      | The developer's email address, matching the identity their tooling reports.                |
| `org_unit_path` | Yes      | Slash-separated unit **names** from the root, for example `Engineering/Platform/Payments`. |
| `is_primary`    | No       | Only primary memberships are supported. Omit it, or set it to `true`.                      |

A realistic file:

```csv
email,org_unit_path
ada.lovelace@example.com,Engineering/Platform/Payments
alan.turing@example.com,Engineering/Platform/Payments
grace.hopper@example.com,Engineering/Platform/Identity
katherine.johnson@example.com,Engineering/Developer Experience
margaret.hamilton@example.com,Engineering/Developer Experience
barbara.liskov@example.com,Data/Analytics Engineering
edsger.dijkstra@example.com,Data/Analytics Engineering
sophie.wilson@example.com,Product/Design Systems
```

You do not create the tree first. Every unit along each path is created if it does not already exist, so the eight rows above build the whole structure on their own, including the intermediate `Engineering/Platform` node that no row names directly. Likewise, a person who is not yet known to Revenium is created and linked automatically.

Repeat imports are safe. A row whose person is already in the unit it names is reported as unchanged rather than written again, so re-uploading a slightly edited roster does not duplicate anything.

{% hint style="info" %}
**File limits.** Uploads are capped at 5 MB, and there is a maximum row count. A file that exceeds either is rejected with a clear error rather than partially applied. For a roster of a few thousand developers, neither limit is a practical concern.
{% endhint %}

***

### <i class="fa-play">:play:</i> Importing: Dry Run First, Then For Real

The import endpoint accepts `multipart/form-data` with a file part named `file`.

Start with a dry run:

```bash
curl -X POST "https://api.revenium.ai/profitstream/v2/api/org-units/import/csv?teamId=YOUR_TEAM_ID&dryRun=true" \
  -H "x-api-key: YOUR_API_KEY" \
  -F "file=@roster.csv"
```

A dry run is not a separate validation routine that might drift from the real thing. It runs the genuine import — the same unit lookups, the same person resolution, the same membership planning — inside a transaction that is rolled back at the end. It is therefore both a true rehearsal and guaranteed to write nothing.

Both dry and real runs return the same report:

```json
{
  "rowsProcessed": 8,
  "unitsCreated": [
    "Engineering (Engineering)",
    "Platform (Engineering/Platform)",
    "Payments (Engineering/Platform/Payments)",
    "Identity (Engineering/Platform/Identity)",
    "Developer Experience (Engineering/Developer Experience)",
    "Data (Data)",
    "Analytics Engineering (Data/Analytics Engineering)",
    "Product (Product)",
    "Design Systems (Product/Design Systems)"
  ],
  "membershipsCreated": 8,
  "membershipsUnchanged": 0,
  "personsCreated": ["ada.lovelace@example.com", "alan.turing@example.com"],
  "errors": []
}
```

Read `errors` before doing anything else. Each entry carries the 1-based line number in your file (the header is line 1) and a human-readable reason, so a malformed roster tells you exactly which rows to fix.

When the report looks right, run the same command with `dryRun=false`.

To move a single person later, without preparing a file, you need the numeric id of the destination unit. List the tree to find it:

```bash
curl "https://api.revenium.ai/profitstream/v2/api/org-units?teamId=YOUR_TEAM_ID" \
  -H "x-api-key: YOUR_API_KEY"
```

Each entry carries its `id`, `name`, `parentId` and full `path`, so you can match on the path you used in the CSV and read the id from the same record. Then assign:

```bash
curl -X PUT "https://api.revenium.ai/profitstream/v2/api/org-units/assignments?teamId=YOUR_TEAM_ID" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "ada.lovelace@example.com", "orgUnitId": 42}'
```

Listing requires an authenticated key; importing and assigning require an API key with permission to manage the organization.

***

### <i class="fa-clock-rotate-left">:clock-rotate-left:</i> Retroactive Attribution: The First Import Covers All History

**This is the most useful property of the design, and it is worth planning your rollout around.**

The first time a person is imported, their membership is backdated to the beginning of time rather than starting on the day you uploaded the file. Every event they have ever sent therefore attributes to the unit you just assigned them.

In practice this means you can run the rollout in the order that is easiest for you:

1. Turn on metering and let developers work. Spend accumulates, attributed to individuals.
2. Weeks later, when you have your roster sorted out, upload the CSV.
3. Every historical report is now broken down by department, including the weeks before the file existed.

There is no backfill job, no reprocessing window, and no need to re-send telemetry. Because departments are resolved when the report runs, the data was never missing — only the structure to interpret it was.

Backdating applies only to a person's **first** assignment. Once someone has a mapping, changing it takes effect from the moment you change it and leaves their earlier history where it was, exactly as a transfer does. A developer imported into the wrong unit and corrected a week later therefore ends up with that week attributed to the wrong department and everything after it attributed correctly, rather than the whole history moving.

That is worth knowing before the first import rather than after it. Run a dry run, read the report, and confirm the tree is right while backdating is still available to you.

{% hint style="info" %}
**The one prerequisite.** Retroactive attribution works on the identity the events already carry, which is the developer's email address. Events that arrived without an email cannot be attributed later, because there is nothing to match the roster against. See [Identity must be an email address](#identity-must-be-an-email-address).
{% endhint %}

***

### <i class="fa-arrows-turn-right">:arrows-turn-right:</i> When Someone Changes Teams

When you reassign a person who already has a mapping, their **historical spend stays with their old team**. Only usage from the moment of the change forward counts against the new one.

This is deliberate, and it is usually the opposite of what people expect, so it is worth being explicit:

> A developer who spends six months on Payments and then moves to Identity leaves six months of spend on the Payments line. Identity's line starts at zero on the day of the move.

That is the correct behaviour for cost accounting. A department's reported spend for a past quarter should not change because somebody transferred afterwards; if it did, no closed period would ever stay closed and chargebacks already issued would stop reconciling.

The boundary is exact. An event landing precisely at the moment of a transfer counts against the **new** unit.

Note the distinction from the previous section, since the two can look contradictory. A **first** assignment is backdated, because before it the person had no department at all and there is no history to protect. A **subsequent** change is not backdated, because there is history, and it belongs where it was earned.

***

### <i class="fa-triangle-exclamation">:triangle-exclamation:</i> Current Limits

These are real constraints today, not caveats about edge cases.

#### The CSV is a point-in-time snapshot

Nothing keeps the tree in step with your directory. Joiners, leavers and transfers are reflected only when somebody uploads a new file. For an organization with normal churn this is a recurring task, not a one-off. Until automated sync ships (see below), plan for a monthly or quarterly re-upload, and treat it as an operational job with an owner.

#### Ambiguous emails are never guessed

If more than one active directory person claims the same email address, the import does not choose between them. The row is reported as ambiguous and left for an administrator to resolve. This is intentional: silently picking one would attribute somebody's spend to the wrong person, and that error is invisible once it is made.

#### Only primary memberships

Each person belongs to exactly one unit. Matrix organizations, dotted-line reporting, and splitting one developer's cost across two departments are not supported. A row that explicitly asks for a non-primary membership is reported as an error rather than being quietly ignored.

#### Identity must be an email address

Attribution matches on email at every stage. A fleet that reports only an opaque identifier and no email address cannot be mapped to a team, no matter how complete the roster is. Those events are still metered, still costed, and still attributed to your organization — they simply fall into the **Unassigned** bucket for department rollups.

Unassigned is a real bucket, not a dropped row. Totals grouped by department always reconcile against the ungrouped total, so a gap in your roster shows up as a visible Unassigned figure rather than as quietly missing money.

If you are configuring Claude Code, the stock configuration already reports developer email correctly, and no extra attribution setup is needed for org units to work. See [Setup Claude Code](/track-and-control-costs/analyze-ai-tooling-spend/setup-claude-code).

#### Rollups are API-only for now

The department dimension is served by the reporting API, but the UI does not yet offer it as a grouping option. Until it does, per-team rollups are retrieved programmatically. Everything else described on this page — building the tree, importing rosters, reassigning people — works today.

***

### <i class="fa-file-export">:file-export:</i> Producing the CSV From Your Directory

Your IT team can generate the file directly from your existing directory. Both recipes below emit the exact two-column format the importer expects. Treat them as starting points: the attribute you use for the department path depends on how your directory is organized, and you will likely want to filter to the population that actually uses AI tooling.

#### Microsoft Entra ID (Azure AD)

Using the Microsoft Graph PowerShell SDK:

```powershell
Connect-MgGraph -Scopes "User.Read.All"

Get-MgUser -All -Property UserPrincipalName,Mail,Department,CompanyName,AccountEnabled |
  Where-Object { $_.AccountEnabled -and $_.Department -and $_.Mail } |
  Select-Object `
    @{Name = 'email';         Expression = { $_.Mail }},
    @{Name = 'org_unit_path'; Expression = { $_.Department }} |
  Export-Csv -Path roster.csv -NoTypeInformation -Encoding utf8NoBOM
```

`Department` is a single value, which produces a flat one-level tree. To build a hierarchy, compose the path from whichever attributes carry your structure, for example a company or division and a department. Swap the `org_unit_path` expression above for:

```powershell
@{Name = 'org_unit_path'; Expression = { "$($_.CompanyName)/$($_.Department)" }}
```

Any attribute you reference in an expression must also appear in `-Property`, which is why `CompanyName` is requested above even though the flat version does not use it. Graph returns nothing for an unrequested attribute, and an empty leading segment would quietly collapse the hierarchy back to a flat tree rather than failing.

#### On-premises Active Directory

Using the ActiveDirectory module on a domain-joined machine:

```powershell
Import-Module ActiveDirectory

Get-ADUser -Filter { Enabled -eq $true } -Properties mail,department,division |
  Where-Object { $_.mail -and $_.department } |
  Select-Object `
    @{Name = 'email';         Expression = { $_.mail }},
    @{Name = 'org_unit_path'; Expression = { if ($_.division) { "$($_.division)/$($_.department)" } else { $_.department } }} |
  Export-Csv -Path roster.csv -NoTypeInformation -Encoding utf8NoBOM
```

If your reporting structure is expressed through the directory's own organizational-unit hierarchy rather than a `department` attribute, derive the path from each user's distinguished name instead, reversing the OU components into a root-first path.

{% hint style="warning" %}
**Windows PowerShell 5.1 and the byte-order mark.** `-Encoding utf8NoBOM` requires PowerShell 6 or later. In Windows PowerShell 5.1, `-Encoding UTF8` writes a byte-order mark at the start of the file, which becomes part of the first column name. Because the importer matches columns **by name**, a file whose header reads as `<BOM>email` will not be recognised. Either run the export in PowerShell 7, or strip the mark afterwards:

```powershell
$csv = Get-Content roster.csv -Raw
[System.IO.File]::WriteAllText(
  (Resolve-Path roster.csv),
  $csv,
  (New-Object System.Text.UTF8Encoding $false)
)
```

{% endhint %}

{% hint style="info" %}
**Check the file before uploading it.** Confirm the header is exactly `email,org_unit_path`, that no value contains a stray comma, and that the file carries no byte-order mark. Then run the import with `dryRun=true` and read the error list. Between them, those two steps catch essentially every formatting problem before anything is written.
{% endhint %}

***

### <i class="fa-rotate">:rotate:</i> Automated Directory Sync

**Automated directory synchronization is not available yet.** CSV import and the assignment endpoints are the supported ways to populate and maintain the tree today. If you have been told otherwise, that is the correct position as of this page's publication.

When it ships it will work as a scheduled pull from Revenium to your directory, on a daily incremental and weekly full reconciliation cycle, rather than as a push from you to us. Connecting it will require:

* **Microsoft Entra ID** — an application registration in your tenant with directory read permission over users and group memberships, administrator consent, and a client credential shared with Revenium.
* **On-premises Active Directory** — synchronization into Entra ID first, since a cloud service cannot read an on-premises directory directly. Organizations already running Entra Connect are covered by the row above.
* **Other providers** — Okta, Google Workspace and HR-system sources are planned behind the same mechanism, each with its own credential model.

The shape of the integration therefore depends on how your directory is run, which is worth establishing early if automated sync matters to your rollout. In the meantime a scheduled export from the recipes above, uploaded on a regular cadence, achieves the same result with an owner attached.

***

### <i class="fa-list-check">:list-check:</i> Rollout Checklist

1. Confirm org-unit attribution is enabled for your tenant. The endpoints return `403` if it is not.
2. Confirm your AI tooling reports developer **email**. Everything else depends on it.
3. Export a roster from your directory using one of the recipes above.
4. Import with `dryRun=true` and resolve every entry in `errors`.
5. Import for real, then check `unitsCreated` matches the structure you intended.
6. Query cost reports grouped by department. Historical periods are included automatically.
7. Assign an owner and a cadence for re-uploading the roster as your organization changes.


# AI Assistants

AI assistants like Claude Code, Claude Cowork, Gemini, Cursor, CoPilot and Codex have become a significant and often poorly tracked line item for engineering teams. Seats get purchased, adoption is assumed, and the actual picture - who's using what, how intensively, and whether the subscription is paying for itself - stays invisible until renewal time.

Revenium connects directly to each assistant and gives you that picture continuously: adoption by team and individual, cost against API-equivalent value, cache efficiency, and inactive seat identification. Find it under Intelligence > AI Assistants in your sidebar.

<figure><img src="/files/VFlgPEYOEpATppjC9UaB" alt="" width="563"><figcaption></figcaption></figure>

***

### <i class="fa-route">:route:</i> Setup Paths (Enterprise vs Per-User)

If your question is "How do I set up Revenium to show AI assistant metrics?", use this reference for onboarding + backfill.

| Setup model                            | Use this when                                                                                                    | Start here                                                                                                                                                                          |
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Enterprise/workspace-wide setup**    | You want organization-level visibility across teams and projects, with standardized attribution and governance.  | [Connect Your Agent](/get-started/quickstart/connect-your-agent) -> [SDK Setup](/integrations/sdk-setup) and [Workspace Connections](/get-started/quickstart/workspace-connections) |
| **Per-user CLI onboarding + Backfill** | For backfill of historical data (manually or via MDM) or if you want an individual developer to onboard quickly. | [Revenium CLI](https://github.com/revenium/revenium-cli-node)                                                                                                                       |

The enterprise path is the recommended default for customer rollouts. The CLI path is still useful for fast individual adoption and testing and is required for historical backfill.

***

### <i class="fa-link">:link:</i> Connecting Your Assistants

A single package covers Claude Code, Cursor, Gemini CLI, GitHub Copilot, and Codex CLI. Get started with:\
npm install -g @revenium/cli

Each tool has its own interactive setup wizard that handles API key validation, connectivity testing, and shell profile configuration automatically. Full setup instructions for each tool, including configuration options and backfill commands for importing historical data, are in the repository.

[**View Setup Instructions on GitHub →**](https://github.com/revenium/revenium-cli-node)

> 💡 Tip: During setup you'll be asked for your subscription tier. Revenium uses this to translate your flat subscription fee into a per-usage cost figure, which is what makes the API-Equivalent Value metric meaningful. It's worth getting right.

***

### <i class="fa-scale-balanced">:scale-balanced:</i> Billing Model: Subscription Seats vs API Rates

Most coding assistants are paid for as fixed seats or subscriptions, but some teams pay API rates for the same assistant traffic. Configure that distinction per team so Revenium knows whether the traffic should stay on AI Assistant dashboards as API-equivalent estimates or count as real spend across cost reports, traces, budgets, alerts, exports, and APIs.

See [Configure Coding Assistant Billing Models](/track-and-control-costs/analyze-ai-tooling-spend/configure-coding-assistant-billing-models) for the full setup flow and impact.

***

### <i class="fa-dollar-sign">:dollar-sign:</i> The Overview: What Are You Actually Getting for Your Money?

Once your tools are connected, the Overview pulls them together side by side — Active Users and Total Cost per tool for the period selected. The combination of those two numbers drives the conversation: a tool with high cost and low active users is a procurement issue. A tool with growing active users and strong session depth is one worth expanding.

The aggregate metrics across all connected tools sharpen that picture further:

* **Active Users** - total unique developers using any AI coding tool across your organization. The headline adoption number, distinct from the per-tool counts above.
* **Sessions per User** - average daily engagement per developer, a proxy for genuine adoption rather than installed-but-ignored.
* **Usage Trend** - period-over-period change in engagement, so you can see whether adoption is growing or quietly declining after the initial rollout.
* **API-Equivalent Value** - the estimated cost if the same usage had been delivered through direct API access. If this significantly exceeds your subscription cost, the tool is delivering real leverage. If it doesn't, that's worth understanding before renewal.

The **Usage by Organization/Department** table breaks all of this down by internal team — users, sessions, cost, and trend — for teams running internal chargebacks or simply wanting to know which departments are driving AI tooling investment.

***

### <i class="fa-hammer">:hammer:</i> Per-Tool Dashboards

Each connected tool has its own detailed view, with the structure varying based on whether the tool is a fixed-seat subscription or a usage-based service.

#### Subscription-Based Tools (Claude Code, Cursor, Gemini CLI, GitHub Copilot, Codex CLI)

The per-user breakdown shows exactly who is using each tool, how many sessions they're running, how many tokens they're consuming, and what that's costing. This surfaces both ends of the distribution — the power users getting the most from the tool, and the inactive seat holders who haven't engaged since onboarding.

**Model Usage Distribution** shows which underlying models are handling requests across the team. For tools that route across multiple models, this tells you whether expensive reasoning models are being used where they add value, or whether usage patterns suggest a configuration adjustment could reduce costs without affecting output quality.

**Cache Utilization** is one of the clearest efficiency signals available. A high cache hit rate means the tool is reusing prior context efficiently rather than reprocessing the same tokens repeatedly. The **Estimated Savings** figure translates that into dollars — useful both for validating current efficiency and for projecting what a broader rollout would cost.

The subscription view surfaces the insight that vendor dashboards rarely volunteer: how many of your paid seats are actually active, and what the inactive ones are costing per month. Revenium flags these directly with the recoverable cost attached, so the decision to reclaim them ahead of renewal is straightforward rather than something that requires a manual audit.

#### Usage-Based Tools (Claude Cowork)

The Cowork dashboard focuses on per-user usage attribution rather than seat utilisation. The headline metrics — API-Equivalent Value, Total Requests, Average Duration, and Total Tokens — give you the size and shape of the workload, with period-over-period comparisons so you can see how usage is trending.

The Usage by Claude Cowork User table breaks the same data down per developer: how many requests each person made, what those requests cost, and how many tokens they consumed. Toggle between Totals (cumulative for the period) and Over Time (trend per user) to switch between "who's been the heaviest user" and "who's been ramping up or backing off." Value by User translates the per-user totals into API-equivalent figures, the same metric that appears on the Overview but scoped to individual subscribers rather than the tool as a whole.

Because Cowork is metered rather than seat-based, the Subscription Overview view that exists for seat-based tools doesn't appear here — there's no inactive seat to reclaim, just usage to attribute and trend.

***

### <i class="fa-users">:users:</i> AI by Employee

The per-tool dashboards above each scope to a single assistant. The **By Employee** tab pivots the same data around people instead — rolling every connected assistant (Claude Code, Claude Cowork, Cursor, Gemini, Codex, Copilot) and direct API spend up to the individual. Where a per-tool view answers "what did Cursor cost," By Employee answers "what did any one person cost across everything" — the view you need for chargebacks and for spotting concentrated spend. It needs no extra setup; it draws on the assistants you've already connected.

Start with the **Attribution Coverage** figure at the top. It tells you how much of your identifiable AI spend has been tied to a known person, and it's the trust indicator for every number below: if coverage is low, the per-employee figures describe only the attributed slice, not your whole AI spend.

From there the page surfaces:

* **Headline KPIs** — Total AI Cost, Active Employees, Avg Cost / Employee, Blended $/Mtok (a single efficiency number for the whole population), and the split between assistant and direct-API spend.
* **Highlights** — top spenders by attributed cost, and highest cost-rate users (inefficient patterns, not just high volume).
* **Charts** — daily spend trend, spend by AI source, spend mix, and how cost is distributed across employees. The daily spend trend can also be broken out by vendor.
* **All Employees table** — per-person cost, % of total, tokens and $/Mtok, requests, channel, and last active — exportable to CSV for finance review.

The **Shadow Spend — Account Types** view splits spend into Corporate and Personal. That split is a **heuristic** based on a configurable corporate-domain allowlist — not a verified employee directory. Read it, and the page as a whole, as a cost-governance and coverage tool: it exists to answer "what are we spending, on whom, and how much of it can we see" — not to monitor individuals.

#### Filter the view

Subscription-based assistant usage is included by default; use the page filters to exclude it when you want to, and to focus on the provider data and model tiers relevant to the analysis. Filters narrow the current result set before you group, choose columns, or export it.

#### Compare groupings and team benchmarks

Group the table by employee, assistant, model, model tier, provider, or vendor. The table adds team-average cost-per-million-token context so an individual result can be compared with the wider team rather than read in isolation.

#### Choose columns and export the result

Select the columns you need for the current analysis. Exporting to CSV uses the current result set, so apply the required filters and grouping before creating the file.

#### Create a Guardrail from the current view

Select **Create Guardrail** from an active employee view to open a new Guardrail with that analysis scope prefilled. Review the form and submit it before the rule is created; the hand-off does not save a Guardrail automatically.

For the full rule workflow, see [Guardrails](/track-and-control-costs/set-budgets-and-alerts).

***

### <i class="fa-forward">:forward:</i> What to Do With What You Find

Use the **Adoption Trend** to time renewal conversations with evidence rather than recency bias. Use **Usage by Department** to make the case for expanding access to teams that aren't yet engaged, or to recover budget from teams where adoption hasn't materialised. Use **API-Equivalent Value** to build the ROI case for finance — showing not just what you spent, but what that spend delivered in terms of developer leverage.


# Configure AI Assistant Pricing Mode

Choose whether each team's AI assistant usage counts as real spend (API-rate) or stays an API-equivalent estimate (subscription or seat-based).

Subscription-based AI assistants are heavily subsidized, do not represent real costs, and are **filtered out of logs & traces by default**. If you pay API rates for AI assistant usage, set that option in your team's configuration so those providers are always counted as real spend.

AI assistant telemetry can therefore represent two different cost models:

* **Subscription or seat-based plans** — your team pays a fixed seat or subscription price. The usage is subsidized and does not represent real cost, so Revenium keeps it on AI Assistant dashboards as an API-equivalent estimate and filters it out of logs and traces by default.
* **API-rate usage** — your team pays the provider by API usage, so selected providers count as real spend across Revenium and their transactions always appear, regardless of the filter selection.

This setting is configured per team. It does not inherit to child teams.

***

## When to use each mode

Use **Subscription or seat-based plans** when the assistant is paid for as a fixed plan, seat, or license. Usage still appears in AI Assistant dashboards for adoption, productivity, API-equivalent value, inactive-seat analysis, and renewal planning. It does not increase real spend in cost reports, traces, budgets, alerts, exports, or APIs.

Use **I pay API rates for AI assistance** when the selected assistant traffic is billed by provider API usage. Selected providers count as real spend everywhere Revenium reports cost, including Costs & Revenue, Traces, Budgets, Alerts, exports, reports, and APIs.

{% hint style="warning" %}
Moving providers into or out of API-rate mode can move active total-cost budget counters immediately when counters are recalculated. Review budget and alert thresholds before saving.
{% endhint %}

***

## Configure the setting

1. Open **Management > Teams**.
2. Edit the team whose AI assistant pricing mode you want to control.
3. Expand **Team AI Settings**.
4. Find **AI Assistant Pricing Mode**.
5. Choose the pricing mode:
   * **Subscription or seat-based plans** keeps AI assistant usage as API-equivalent estimates on AI Assistant dashboards only.
   * **I pay API rates for AI assistance** lets selected providers count as real spend.
6. If you choose API-rate mode, complete the two steps the panel shows:
   * **Step 1 — Acknowledge:** read the real-spend impact warning and check the acknowledgement box. Provider selection stays disabled until you do.
   * **Step 2 — Providers billed by API usage:** select the providers that are billed at API rates. You must select at least one provider to save API-rate mode.

Supported providers are **Claude Code, Claude Cowork, Cursor IDE, Gemini CLI, Codex CLI, and GitHub Copilot**.

Claude Cowork is metered by the provider rather than seat-based, but the team setting still controls whether Cowork telemetry counts as real spend in Revenium-wide reporting or stays scoped to AI Assistant analytics.

{% hint style="info" %}
To switch a team back from API-rate mode to **Subscription or seat-based plans**, Revenium asks you to confirm. Confirming clears all selected API-rate providers and stops counting their usage as real spend; active budget and alert counters are recalculated immediately.
{% endhint %}

***

## What changes after saving

When a provider is set to API-rate mode:

* Provider usage is included in real spend reporting.
* Traces and Costs & Revenue dashboards include the selected provider traffic.
* Budgets, alerts, reports, exports, and APIs use the selected provider traffic as real cost.
* Active total-cost budget counters may change after recalculation.

When a provider is not set to API-rate mode:

* Provider usage remains visible on AI Assistant dashboards.
* Revenium shows API-equivalent value for ROI and renewal analysis.
* The usage does not count as real spend in global cost reporting, budgets, alerts, reports, exports, or APIs.

***

## How this interacts with logs & traces filters

By default, subscription-based AI assistant usage is filtered out of logs and traces because it is subsidized and does not represent real cost. Pricing mode is the team policy that overrides this: **once a provider is set to API-rate billing, all of its transactions appear regardless of the filter selection**, because they now represent real spend.

The per-view AI assistant filters are just different views of the same underlying data — they change what you see in a given view, not what is stored. Your usage data is always captured; the filters and pricing mode only control whether subsidized (subscription) usage is shown alongside real (API-rate) spend.

{% hint style="info" %}
On the logs and traces views you'll see which providers are currently set to API-rate billing — for example, *"Currently Claude Code, Cursor IDE are configured for API-rate billing."* Those providers' transactions always appear; subscription-based providers are filtered out unless you change the view.
{% endhint %}

***

## Related subscription settings

Claude Code also has a **Subscription Overview** tab where you can enter tier allocations and seat costs. That tab is for ROI, utilization, and renewal analysis. It does not by itself make Claude Code usage count as real spend.

Use the team-level **AI Assistant Pricing Mode** setting when you need to decide whether AI assistant traffic should be treated as real provider spend.

***

## Related pages

* [AI Assistant Data Reference](/track-and-control-costs/analyze-ai-tooling-spend/ai-coding-data-reference) — the full field set each provider reports.


# Setup Claude Code

Claude Code supports centrally-managed configuration through the Claude admin console. An administrator defines the settings once; Anthropic delivers them to every authenticated user on next startup. No per-developer install is required.

This is different for individual developer onboarding and does not cover historical backfill - please refer to [this document](/track-and-control-costs/analyze-ai-tooling-spend#setup-paths-enterprise-vs-per-user) for details on how to do that or go direct to <https://github.com/revenium/revenium-cli-node>

**Requirements:**

* Claude for Teams or Claude for Enterprise plan
* Claude Code version that supports managed settings
* Administrator role of **Primary Owner** or **Owner** in the Claude admin console
* Direct connection to `api.anthropic.com` to receive server-managed settings — configuration delivery only; telemetry does not transit Anthropic
* Direct connection to `api.revenium.ai` on port 443 from each developer machine for telemetry egress

{% hint style="info" %}
**Claude Code evolves quickly.** Anthropic updates environment variables, managed-settings fields, and admin console paths frequently. If something does not match what you see in the Claude admin console, cross-reference Anthropic's Claude Code monitoring and server-managed settings docs. The Revenium-specific values below, including the endpoint URL, API key header, and resource attributes, are the values to keep consistent.
{% endhint %}

#### Network Path: Configuration Delivery vs. Telemetry Egress

Configuration delivery and telemetry egress are two independent network paths. Telemetry does **not** transit Anthropic.

```
Configuration delivery (inbound)          Telemetry egress (outbound)

 Claude admin console (Anthropic)          Claude Code process
   |  server-managed settings                |  OTLP / HTTP-JSON, ~5s batches
   |  delivered at sign-in                   |
   v                                         v
 Developer machine ----------------------> api.revenium.ai:443
   ^                                       (direct TLS connection)
   |  ...or MDM / OS policy / settings file
   |  (never contacts Anthropic)
```

* **Configuration delivery** — how the `env` block below reaches the machine. With server-managed settings, Anthropic's servers deliver it at sign-in, which is why `api.anthropic.com` appears in the requirements above. With MDM, OS policy, or a managed settings file, Anthropic is not involved at all.
* **Telemetry egress** — Claude Code embeds the OpenTelemetry SDK and is itself the OTLP exporter. It opens a direct TLS connection from the developer's machine to the host in `OTEL_EXPORTER_OTLP_ENDPOINT` and POSTs batches to `/v1/logs`. Anthropic does not receive, proxy, buffer, or store this telemetry.

Practical consequences:

* **Firewall and proxy rules must name `api.revenium.ai` explicitly.** An allowlist entry for `api.anthropic.com` does not cover telemetry egress; they are separate destinations.
* **If the Revenium endpoint is unreachable, export fails locally.** Claude Code continues to work normally, and nothing is queued at Anthropic for later delivery, so telemetry for that period is not recoverable.
* **Prompt and response content is redacted by default.** The configuration below sends session, identity, model, token, and cost metadata; message bodies are exported as `<REDACTED>` unless an administrator explicitly opts in using Anthropic's content-logging variables.

**Steps:**

1. Sign in to [Claude.ai](https://claude.ai) as Primary Owner or Owner.
2. Navigate to the Managed settings screen. Depending on plan and admin console version, this appears under **Admin Settings → Claude Code → Managed settings** or **Organization settings → Claude Code → Managed settings**.
3. Paste the following JSON, substituting your Revenium metering key.

Use a Revenium metering key (`rev_mk_*`) for Claude Code OTLP telemetry. Do **not** use an Anthropic/OpenAI provider key here; provider keys authenticate model calls, while the Revenium key authenticates telemetry ingest.

```json
{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://api.revenium.ai/meter/v2/otlp",
    "OTEL_EXPORTER_OTLP_HEADERS": "x-api-key=rev_mk_your_tenant_yourkey",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_METRICS_EXPORTER": "none",
    "OTEL_LOGS_EXPORT_INTERVAL": "5000",
    "OTEL_RESOURCE_ATTRIBUTES": "revenium.middleware.source=managed-settings"
  }
}
```

4. Click **Add settings** or save the managed settings.
5. Ask developers to fully quit and relaunch Claude Code after the config push.

On first launch after the settings are picked up, each developer may see a one-time security approval dialog listing the managed environment variables. They should approve the administrator-delivered configuration.

#### Verifying Your Configuration

Ask a developer to run a brief Claude Code session. Usage should appear in Revenium after the next telemetry flush. Your Revenium tenant is identified by the metering key, and Claude Code attaches the developer identity it knows for the session. If your organization uses direct API keys, Bedrock, Vertex, Microsoft Foundry, or a custom `ANTHROPIC_BASE_URL`, attach identity yourself with `OTEL_RESOURCE_ATTRIBUTES`.

If no sessions appear after configuring the settings, check:

* The Revenium metering key is active in your Revenium account
* The OTLP endpoint matches your Revenium environment
* The developer fully quit and relaunched Claude Code after the config push

{% hint style="info" %}
**Field reference**

* **`OTEL_EXPORTER_OTLP_ENDPOINT`** — Revenium's OTLP endpoint. For most customers this is `https://api.revenium.ai/meter/v2/otlp`.
* **`OTEL_EXPORTER_OTLP_HEADERS`** — Your Revenium metering key, prefixed with `x-api-key=`.
* **`OTEL_EXPORTER_OTLP_PROTOCOL`** — Must be `http/json`.
* **`OTEL_LOGS_EXPORTER`** — Must be `otlp`. This enables log export, which is how Revenium receives per-call telemetry.
* **`OTEL_METRICS_EXPORTER`** — Must be `none`. Revenium bills from log events only; leaving metrics enabled is unnecessary and increases HTTP traffic without adding data.
* **`OTEL_LOGS_EXPORT_INTERVAL`** — Milliseconds between log-batch flushes. `5000` matches Claude Code's documented/default flush interval.
* **`OTEL_RESOURCE_ATTRIBUTES`** — OTEL resource attributes attached to every event from this deployment. The required value `revenium.middleware.source=managed-settings` tags telemetry as originating from a centrally-managed settings deployment. Per-developer CLI installs are automatically tagged `revenium-cli`, so the two deployment channels are separable in Revenium reporting. If you add your own attribution labels, append them comma-separated to this value (see [Optional Internal Attribution](#optional-internal-attribution) below).
  {% endhint %}

#### Optional Internal Attribution

The required configuration above is enough for correct metering and dashboard attribution. If you want to sub-segment your own Claude Code usage within your Revenium tenant — for example to compare spend across business units, teams, or internal product lines — extend the existing `OTEL_RESOURCE_ATTRIBUTES` value by appending your labels comma-separated after `revenium.middleware.source=managed-settings`:

```json
{
  "env": {
    "CLAUDE_CODE_ENABLE_TELEMETRY": "1",
    "OTEL_EXPORTER_OTLP_ENDPOINT": "https://api.revenium.ai/meter/v2/otlp",
    "OTEL_EXPORTER_OTLP_HEADERS": "x-api-key=rev_mk_your_tenant_yourkey",
    "OTEL_EXPORTER_OTLP_PROTOCOL": "http/json",
    "OTEL_LOGS_EXPORTER": "otlp",
    "OTEL_METRICS_EXPORTER": "none",
    "OTEL_LOGS_EXPORT_INTERVAL": "5000",
    "OTEL_RESOURCE_ATTRIBUTES": "revenium.middleware.source=managed-settings,organization.name=Engineering,product.name=internal-claude-code"
  }
}
```

Keep `revenium.middleware.source=managed-settings` as the first entry — do not remove it. The additional labels come from a supported set: Revenium reads specific attribute names, and any name outside that set is discarded silently, with no error. Set the values to whatever suits your internal reporting, but keep the attribute names exactly as shown below — a made-up name such as `business_unit` will not appear anywhere in Revenium.

* `organization.name` — a business unit, department, or cost center, such as `Engineering`, `DataPlatform`, or `Marketing`
* `product.name` — the application or use case, such as `internal-claude-code`

You can use `organization.id` and `product.id` in place of the `.name` forms if you prefer stable identifiers. Use the attribute names exactly as written — do not add a `revenium.` prefix to `organization.name` or `product.name`.

{% hint style="warning" %}
**`OTEL_RESOURCE_ATTRIBUTES` formatting constraints:**

* **No spaces in values.** Use underscores, camelCase, or percent-encoding (`%20`) instead, for example `organization.name=Data_Platform` or `organization.name=DataPlatform`, not `organization.name=Data Platform`.
* **Values are case-sensitive.** `Engineering` and `engineering` are treated as separate labels. Pick a canonical form and use it consistently across all configuration and integrations.
  {% endhint %}

{% hint style="info" %}
**Third-party provider compatibility.** [Server-managed settings](https://code.claude.com/docs/en/server-managed-settings) are delivered from Anthropic's servers and require a direct connection to `api.anthropic.com`. They are not delivered when Claude Code is routed through Amazon Bedrock, Google Cloud's Agent Platform, Microsoft Foundry, Claude Platform on AWS, or custom API endpoints via `ANTHROPIC_BASE_URL` or third-party LLM gateways. If your organization uses one of these providers, use endpoint-managed settings or the per-developer CLI setup instead.

Endpoint-managed settings are deployed to each device through native OS policies — macOS managed preferences or the Windows registry — or through a managed settings file, typically using the mobile device management (MDM) or endpoint-management tool your organization already runs. Behind a gateway, this is the delivery channel by design: it enforces the configuration without asking users to change their shells, and the settings file can be protected from user modification at the OS level.
{% endhint %}

{% hint style="info" %}
**Managed settings override user-level configuration.** Values defined in the managed settings `env` block take precedence over shell-exported environment variables on each user's machine, including values the Revenium CLI may have previously set.
{% endhint %}


# Setup Claude Cowork

Claude Cowork telemetry is enabled **once, by an organization administrator**, from the Claude for Work admin console. There is no per-developer install: once an admin points Cowork at Revenium's OTLP endpoint, Anthropic exports usage for every authenticated Cowork user in the organization automatically.

This differs from the per-user CLI onboarding used for Claude Code, Cursor, Gemini, GitHub Copilot, and Codex, and Cowork does **not** support historical backfill — telemetry is real-time only, captured as each Cowork request completes.

**Requirements:**

* Claude for Work (Teams or Enterprise) with Cowork enabled
* Administrator role with access to the Organization / Cowork settings in the Claude admin console
* A Revenium metering key (`rev_mk_*`) from your Revenium account
* Outbound connectivity from Anthropic's export to `https://api.revenium.ai`

{% hint style="info" %}
**Claude Cowork evolves quickly.** Anthropic updates the admin console layout and monitoring fields frequently. If a screen does not match exactly, look for the **Monitoring** / **OTLP** / **observability** section under your organization's Cowork settings. The Revenium-specific values below — the endpoint URL, the `x-api-key` header, and the protocol — are the values to keep consistent.
{% endhint %}

**Steps:**

1. In Claude Desktop, open **Organization → Co-work → Monitoring** (admin access required).
2. Enable OTLP / telemetry export.
3. Set the OTLP endpoint, headers, and resource attributes to the Revenium values:

| Field                   | Value                                         |
| ----------------------- | --------------------------------------------- |
| **OTLP endpoint**       | `https://api.revenium.ai/meter/v2/otlp`       |
| **Header**              | `x-api-key: rev_mk_your_tenant_yourkey`       |
| **Protocol**            | `http/json`                                   |
| **Resource attributes** | `revenium.middleware.source=managed-settings` |

Use a Revenium **metering key** (`rev_mk_*`). Do **not** use an Anthropic/OpenAI provider key here — provider keys authenticate model calls, while the Revenium key authenticates telemetry ingest and identifies your Revenium tenant.

The **Resource attributes** field is required. Set it to `revenium.middleware.source=managed-settings` — this value tags Cowork telemetry as originating from a centrally-managed deployment so it is attributed correctly in Revenium reporting.

4. Save the configuration.

Telemetry begins flowing for all authenticated Cowork users on their next session. Your Revenium tenant is identified by the metering key.

#### Verifying Your Configuration

Ask a user to run a brief Cowork session. Usage should appear in Revenium under **Intelligence → AI Assistants** after the next telemetry flush.

If no usage appears, confirm your data is actually reaching Revenium with a one-line self-test from any terminal — substitute your metering key:

```bash
curl -sS -o /dev/null -w "%{http_code}\n" \
  -X POST "https://api.revenium.ai/meter/v2/otlp/v1/logs" \
  -H "x-api-key: rev_mk_your_tenant_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"resourceLogs":[]}'
```

Interpret the response:

* **`200` / `202`** — your endpoint and key are reaching Revenium correctly. If usage still doesn't show, recheck the metering key is active and that Cowork users have run sessions since the config was saved.
* **`401` / `403` with an auth message** — the metering key is wrong, inactive, or not a `rev_mk_*` key. Generate/confirm the key in your Revenium account.
* **`403` with no auth body, or a connection failure** — the request is being stopped before it reaches Revenium (for example a corporate network or proxy). [Contact Revenium support](https://www.revenium.io/contact) with your egress IP range so we can confirm connectivity.

{% hint style="info" %}
**Field reference**

* **OTLP endpoint** — `https://api.revenium.ai/meter/v2/otlp`. Cowork appends the OTLP signal path (`/v1/logs`) automatically.
* **`x-api-key`** — your Revenium metering key (`rev_mk_*`). Note Cowork uses the `x-api-key` header, not an `Authorization: Bearer` header.
* **Protocol** — `http/json`.
* **Resource attributes** — `revenium.middleware.source=managed-settings`. This required value tags telemetry as originating from a centrally-managed deployment, keeping deployment channels separable in Revenium reporting. If you add your own attribution labels, append them comma-separated to this value and keep `revenium.middleware.source=managed-settings` first (see [Optional Internal Attribution](#optional-internal-attribution) below).
  {% endhint %}

#### Optional Internal Attribution

The required configuration above is enough for correct metering and dashboard attribution. Cowork usage lands under your tenant's default attribution, which is right for most customers.

If you want to sub-segment Cowork usage within your Revenium tenant — for example to compare spend across business units — extend the **Resource attributes** value by appending your labels comma-separated after `revenium.middleware.source=managed-settings`:

```
revenium.middleware.source=managed-settings,organization.name=Engineering,product.name=internal-cowork
```

Keep `revenium.middleware.source=managed-settings` as the first entry — do not remove it. The additional labels are yours to define:

* `organization.name` — a business unit, department, or cost center
* `product.name` — the application or use case

{% hint style="warning" %}
**Resource attribute formatting:** no spaces in values (use underscores or camelCase), and values are case-sensitive — pick a canonical form and use it consistently.
{% endhint %}

#### Billing Classification

Claude Cowork is **metered by usage** (provider-metered) rather than seat-based. The [AI Assistant pricing mode](/track-and-control-costs/analyze-ai-tooling-spend/configure-coding-assistant-billing-models) team setting controls whether Cowork telemetry counts as real API spend in Revenium-wide reporting or stays scoped to AI Assistant analytics.

#### Related

* [AI Assistant Data Reference](/track-and-control-costs/analyze-ai-tooling-spend/ai-coding-data-reference) — the full Cowork data schema and OTLP transport details
* [Setup Claude Code](/track-and-control-costs/analyze-ai-tooling-spend/setup-claude-code) — the equivalent managed-settings flow for Claude Code


# Setup GitHub Copilot

The Revenium CLI syncs GitHub Copilot Business and Enterprise usage metrics from the GitHub Copilot Metrics API into Revenium via OTLP. It tracks code completions, chat interactions, lines of code suggested and accepted, and active users per IDE and language.

**Requirements:**

* GitHub Copilot Business or Enterprise active on your organization
* GitHub PAT (classic) with the following scopes:
  * `manage_billing:copilot`
  * `read:org`
  * Generate at: <https://github.com/settings/tokens>
* "Copilot usage metrics" policy enabled in your GitHub organization settings (Settings > Copilot > Policies)
* Revenium API key (`hak_` or `rev_` prefix). Get it from Connections > SDK Setup in the Revenium dashboard.
* Node.js >= 20.19.0

## 1. Install the Revenium CLI

```bash
npm install -g @revenium/cli
```

You can also use `npx` without installing globally:

```bash
npx --package @revenium/cli revenium-copilot setup
```

## 2. Run the setup wizard

```bash
revenium-copilot setup
```

The wizard prompts for:

* **GitHub personal access token** — validated against the `ghp_` or `github_pat_` prefix
* **GitHub organization slug** — the org whose Copilot usage you want to track
* **Revenium API key** — validated against the `hak_` or `rev_` prefix
* **Copilot subscription tier** — individual, business, or enterprise
* **Email** (optional) — for attribution
* **Organization name** (optional) — for grouping usage
* **Product name** (optional) — for sub-segmenting within the organization
* **Sync interval** (optional) — defaults to 5 minutes

The wizard tests connectivity to both the GitHub Copilot Metrics API and the Revenium endpoint before writing the configuration.

Configuration is saved to `~/.github-copilot/revenium/revenium.env` with restricted file permissions (owner read/write only).

## 3. Verify the configuration

```bash
revenium-copilot status
```

Confirms that both the GitHub API and Revenium endpoint are reachable with the provided credentials. If either shows "unreachable", see [Troubleshooting](#troubleshooting) below.

## 4. Send a test metric

```bash
revenium-copilot test --verbose
```

Sends a zero-cost synthetic event to verify the Revenium pipeline is processing Copilot data. Check AI Assistants > Copilot > Integration Logs to confirm receipt.

## 5. Sync usage data

Pulls Copilot usage from the GitHub API and sends it to Revenium. GitHub usage data has an approximately 24-hour delay.

```bash
# One-time sync (last 28 days):
revenium-copilot sync

# Continuous sync (recommended for production):
revenium-copilot sync --watch

# Custom date range:
revenium-copilot sync --from 2025-01-01 --to 2025-01-31

# Preview what would be sent without actually sending:
revenium-copilot sync --dry-run
```

{% hint style="info" %}
**Continuous sync** runs on the interval configured during setup (default: 5 minutes). It deduplicates data automatically, so restarting the process does not create duplicate records.
{% endhint %}

## 6. Backfill historical data

To import historical Copilot data beyond the default 28-day window:

```bash
# Backfill a specific date range:
revenium-copilot backfill --since 2025-01-01 --to 2025-06-01

# Preview without sending:
revenium-copilot backfill --since 2025-01-01 --to 2025-06-01 --dry-run

# Verbose output:
revenium-copilot backfill --since 2025-01-01 --to 2025-06-01 -v
```

{% hint style="warning" %}
GitHub retains Copilot metrics for a limited window (typically 28 days). Older data may not be available depending on your GitHub plan.
{% endhint %}

## 7. Reset configuration

To remove the stored configuration and start fresh:

```bash
revenium-copilot reset
```

This deletes the configuration at `~/.github-copilot/revenium/` and removes the shell profile source line. You can then run `revenium-copilot setup` again with new credentials.

## Troubleshooting

Start every diagnosis with `revenium-copilot status`. It checks that the configuration exists at `~/.github-copilot/revenium/revenium.env`, parses correctly, and can reach **both** the GitHub Copilot Metrics API and the Revenium endpoint — and it prints the sync state so you can see whether any data has been pulled yet.

### No data appears in Revenium after setup

Copilot metering is **pull-based**: the CLI reads usage from the GitHub Copilot Metrics API and forwards it to Revenium on a schedule. Two things commonly delay the first data:

1. **GitHub's reporting delay.** GitHub aggregates Copilot metrics with an approximately **24-hour delay**, so today's activity will not be available to pull yet. An empty recent window is expected.
2. **The sync must be running.** Run `revenium-copilot status` and check **Sync State** — "No sync has been performed yet" means nothing has been pulled. Run `revenium-copilot sync` for a one-time pull (last 28 days), or `revenium-copilot sync --watch` to keep pulling on the configured interval (default 5 minutes). For ongoing metering, `--watch` must stay running.
3. **Confirm the pipeline.** Run `revenium-copilot test --verbose`, then open **AI Assistants > Copilot > Integration Logs** to confirm the event was received. If the test event lands but real usage does not, the sync is not running or GitHub's 24-hour window has not yet caught up.

### `status` reports "GitHub Copilot API unreachable"

The GitHub side of the pipeline is failing. Check, in order:

* **PAT scopes.** The GitHub personal access token (classic) must carry both `manage_billing:copilot` and `read:org`. A token missing either scope cannot read the metrics API. Regenerate it at <https://github.com/settings/tokens>.
* **Metrics policy.** The "Copilot usage metrics" policy must be enabled for your organization under **Settings > Copilot > Policies**. With the policy off, GitHub returns no metrics even to a correctly-scoped token.
* **Organization slug + plan.** Confirm the org slug entered during setup is correct and that the org has Copilot **Business or Enterprise** active — usage metrics are not available on individual plans.

### `status` reports "Revenium API unhealthy", or authentication is rejected

The Revenium side of the pipeline is failing:

* **Verify the key type.** Copilot telemetry authenticates with a **Revenium** API key (`hak_` or `rev_` prefix), not a GitHub token. A `hak_` key must be in `hak_{tenant}_{key}` form. Get one from **Connections > SDK Setup** in the Revenium dashboard.
* **Verify the endpoint.** The default is `https://api.revenium.ai`.
* **Re-enter credentials.** Run `revenium-copilot setup` to rewrite the configuration with a corrected key or endpoint.

If `status` reports a Revenium connection failure rather than an auth rejection, confirm your data can actually reach Revenium with a one-line self-test from any terminal — substitute your Revenium key:

```bash
curl -sS -o /dev/null -w "%{http_code}\n" \
  -X POST "https://api.revenium.ai/meter/v2/otlp/v1/logs" \
  -H "x-api-key: rev_mk_your_tenant_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"resourceLogs":[]}'
```

* **`200` / `202`** — your endpoint and key are reaching Revenium correctly.
* **`401` / `403` with an auth message** — the key is wrong, inactive, or not a Revenium key.
* **`403` with no auth body, or a connection failure** — the request is being stopped before it reaches Revenium (for example a corporate network or proxy). [Contact Revenium support](https://www.revenium.io/contact) with your egress IP range so we can confirm connectivity.

### Older historical data is missing on backfill

GitHub retains Copilot metrics for a limited window (typically **28 days**). Data older than that window may not be available to backfill, depending on your GitHub plan.

## Command reference

| Command                                                | Description                                |
| ------------------------------------------------------ | ------------------------------------------ |
| `revenium-copilot setup`                               | Interactive setup wizard                   |
| `revenium-copilot status`                              | Verify connectivity to GitHub and Revenium |
| `revenium-copilot test --verbose`                      | Send a synthetic test event                |
| `revenium-copilot sync`                                | One-time sync (last 28 days)               |
| `revenium-copilot sync --watch`                        | Continuous sync at configured interval     |
| `revenium-copilot sync --from <date> --to <date>`      | Sync a specific date range (YYYY-MM-DD)    |
| `revenium-copilot sync --dry-run`                      | Preview sync output without sending        |
| `revenium-copilot backfill --since <date> --to <date>` | Import historical data                     |
| `revenium-copilot reset`                               | Remove configuration and start fresh       |


# Setup Cursor

Revenium tracks Cursor IDE usage by syncing data from the Cursor Admin API. The recommended setup is through the Revenium dashboard, where the backend handles syncing automatically. A CLI is also available for backfilling historical data and debugging.

## Requirements

* Cursor IDE with an active subscription (Pro, Business, or Enterprise)
* Cursor **team** API key (from your Cursor team settings — this is different from a personal user key)
* Revenium account with access to the Providers page

## 1. Add Cursor as a provider

1. In the Revenium dashboard, go to **Connections > Providers**.
2. Select **Cursor** from the list of available providers.
3. Enter your **Cursor team API key**. This key is issued from your Cursor team settings and grants access to the team usage API.
4. Save the configuration.

Once saved, Revenium syncs Cursor usage data automatically every 5 minutes. No CLI installation or local configuration is required.

{% hint style="info" %}
**Team API key required.** Cursor has both personal user keys and team keys. Revenium uses the `/teams/filtered-usage-events` endpoint, which requires a **team** API key. A personal key will not work.
{% endhint %}

## 2. Verify data is flowing

After saving, allow up to 10 minutes for the first sync cycle to complete. Then check **AI Assistants > Cursor** in the dashboard to confirm usage data is appearing.

## CLI (optional)

The Revenium CLI provides additional tools for backfilling historical data and diagnosing connectivity issues. It is not required for standard operation.

### Install

Requires Node.js >= 20.19.0. Check with `node --version`.

```bash
npm install -g @revenium/cli
```

### CLI setup

Run the setup wizard to configure local credentials before using any CLI command:

```bash
revenium-cursor setup
```

The wizard prompts for your Cursor team API key, Revenium API key, subscription tier, and optional attribution fields. Configuration is saved to `~/.cursor/revenium/revenium.env`.

### Backfill historical data

To import Cursor usage data from before you enabled the integration:

```bash
revenium-cursor backfill --since 2025-01-01 --to 2025-06-01

# Preview without sending:
revenium-cursor backfill --since 2025-01-01 --to 2025-06-01 --dry-run

# Control batch size and delay between batches:
revenium-cursor backfill --since 2025-01-01 --batch-size 50 --delay 1000
```

### Diagnose connectivity

```bash
revenium-cursor status
```

Checks that both the Cursor API and Revenium endpoint are reachable with the provided credentials, and prints the current sync state.

### Send a test metric

```bash
revenium-cursor test --verbose
```

Sends a zero-cost synthetic event to verify the pipeline. Check **AI Assistants > Cursor > Integration Logs** to confirm receipt.

### Command reference

| Command                                               | Description                                  |
| ----------------------------------------------------- | -------------------------------------------- |
| `revenium-cursor setup`                               | Interactive setup wizard for CLI credentials |
| `revenium-cursor status`                              | Verify connectivity to Cursor and Revenium   |
| `revenium-cursor test --verbose`                      | Send a synthetic test event                  |
| `revenium-cursor backfill --since <date> --to <date>` | Import historical data                       |
| `revenium-cursor backfill --dry-run`                  | Preview backfill output without sending      |
| `revenium-cursor reset`                               | Remove CLI configuration and start fresh     |

## Troubleshooting

### No data appears after adding the provider

The backend syncs every 5 minutes. Allow up to 10 minutes for the first data to appear. If nothing shows after that:

1. Confirm you used a **team** API key, not a personal user key.
2. Verify the key in **Connections > Providers > Cursor** is correct and has not been regenerated.
3. Confirm your Cursor subscription (Pro, Business, or Enterprise) is active.

### Cursor API key rejected

* The key must be a **Cursor team API key** from your Cursor team settings.
* Personal user API keys do not have access to the team usage endpoint.
* Regenerate the key in Cursor if in doubt and update it in **Connections > Providers**.

### Revenium API key issues (CLI only)

* Cursor telemetry authenticates with a **Revenium** API key (`hak_` or `rev_` prefix), not a Cursor key.
* Get one from **Connections > SDK Setup** in the Revenium dashboard.
* Run `revenium-cursor setup` to update credentials.


# Setup Gemini CLI

The Revenium CLI tracks Gemini CLI usage by injecting OTLP environment variables into your shell. Once configured, every Gemini CLI session automatically reports telemetry to Revenium.

**Requirements:**

* Gemini CLI installed and configured
* Revenium API key (`hak_` or `rev_` prefix). Get it from Connections > SDK Setup in the Revenium dashboard.
* Node.js >= 20.19.0

## 1. Install the Revenium CLI

```bash
npm install -g @revenium/cli
```

You can also use `npx` without installing globally:

```bash
npx --package @revenium/cli revenium-gemini setup
```

## 2. Run the setup wizard

```bash
revenium-gemini setup
```

The wizard prompts for:

* **Revenium API key** — validated against the `hak_` or `rev_` prefix
* **Email** (optional) — for attribution
* **Organization name** (optional) — for grouping usage
* **Product name** (optional) — for sub-segmenting within the organization
* **API endpoint** (optional) — defaults to `https://api.revenium.ai`

The wizard tests connectivity to the Revenium endpoint before writing the configuration.

Configuration is saved to `~/.gemini/revenium.env` (and `~/.gemini/revenium.fish` for Fish shell) with restricted file permissions (owner read/write only). The wizard also updates your shell profile (bash, zsh, or fish) to source the config automatically.

## 3. Restart your terminal

```bash
# Or reload manually:
source ~/.gemini/revenium.env
```

## 4. Verify the configuration

```bash
revenium-gemini status
```

Confirms that the Revenium endpoint is reachable with the provided credentials.

## 5. Send a test metric

```bash
revenium-gemini test --verbose
```

Sends a zero-cost synthetic event to verify the Revenium pipeline is processing Gemini data. Check AI Assistants > Gemini > Integration Logs to confirm receipt.

## 6. Start using Gemini CLI

After setup, use Gemini CLI as you normally would. Telemetry is captured automatically via the OTLP environment variables injected into your shell. Usage appears in Revenium after the next telemetry flush.

{% hint style="info" %}
**How it works:** The setup wizard writes OTLP environment variables (`OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS`, `OTEL_EXPORTER_OTLP_PROTOCOL`, `OTEL_LOGS_EXPORTER`) to a config file and sources it from your shell profile. Gemini CLI reads these natively and reports usage to Revenium without any additional configuration or sync process.
{% endhint %}

{% hint style="info" %}
**No sync or backfill.** Unlike Copilot and Cursor, Gemini CLI operates in real-time only. Telemetry is exported as each request completes. There is no sync command or backfill capability.
{% endhint %}

## Troubleshooting

Start every diagnosis with `revenium-gemini status`. It confirms the configuration exists at `~/.gemini/revenium.env`, reports whether the OTLP environment variables are **loaded in your current shell**, and tests connectivity to the Revenium endpoint.

Because Gemini CLI is real-time only — telemetry is exported as each request completes, with no sync or backfill — the only recourse for missing data is to fix the configuration and run a fresh session. There is no way to recover usage from before metering was working.

### No data appears in Revenium after setup

Gemini CLI reads its OTLP settings from environment variables that the setup wizard writes to `~/.gemini/revenium.env` and sources from your shell profile. The most common cause of missing data is a shell that was opened before setup, so those variables are not present. Work through these in order:

1. **Check that the environment is loaded.** Run `revenium-gemini status`. Under **Environment**, "Environment variables not loaded in current shell" means Gemini has nothing to export to. The status output prints the exact fix — `source ~/.gemini/revenium.env` (or `~/.gemini/revenium.fish` for the Fish shell).
2. **Reload your shell.** Run `exec $SHELL`, open a new terminal, or `source` the config as above. Gemini reads the OTLP variables **at launch**, so it must be started from a shell where they are present.
3. **Send a synthetic event.** Run `revenium-gemini test --verbose`, then open **AI Assistants > Gemini > Integration Logs** to confirm the event was received. If the test event lands but real usage does not, Gemini is being launched from a shell without the variables loaded — return to step 2.
4. **Run a fresh Gemini session.** Usage appears only for sessions run after the environment is loaded; there is no backfill for earlier activity.

### `status` reports the endpoint is unhealthy, or authentication is rejected

The Revenium endpoint is rejecting the request:

* **Verify the key type.** Gemini telemetry authenticates with a **Revenium** API key (`hak_` or `rev_` prefix), not a Google or Gemini provider key. A `hak_` key must be in `hak_{tenant}_{key}` form. Get one from **Connections > SDK Setup** in the Revenium dashboard.
* **Verify the endpoint.** The default is `https://api.revenium.ai`.
* **Re-enter credentials.** Run `revenium-gemini setup` to rewrite the configuration with a corrected key or endpoint.

If `status` reports a connection failure rather than an auth rejection, confirm your data can actually reach Revenium with a one-line self-test from any terminal — substitute your Revenium key:

```bash
curl -sS -o /dev/null -w "%{http_code}\n" \
  -X POST "https://api.revenium.ai/meter/v2/otlp/v1/logs" \
  -H "x-api-key: rev_mk_your_tenant_yourkey" \
  -H "Content-Type: application/json" \
  -d '{"resourceLogs":[]}'
```

* **`200` / `202`** — your endpoint and key are reaching Revenium correctly.
* **`401` / `403` with an auth message** — the key is wrong, inactive, or not a Revenium key.
* **`403` with no auth body, or a connection failure** — the request is being stopped before it reaches Revenium (for example a corporate network or proxy). [Contact Revenium support](https://www.revenium.io/contact) with your egress IP range so we can confirm connectivity.

## Command reference

| Command                          | Description                     |
| -------------------------------- | ------------------------------- |
| `revenium-gemini setup`          | Interactive setup wizard        |
| `revenium-gemini status`         | Verify connectivity to Revenium |
| `revenium-gemini test --verbose` | Send a synthetic test event     |


# Setup Codex CLI

The Revenium CLI tracks OpenAI Codex CLI usage by writing OTLP configuration to the Codex `config.toml` and injecting a shell wrapper that sets the correct environment for each session.

**Requirements:**

* OpenAI Codex CLI installed and configured
* Revenium API key (`hak_` or `rev_` prefix). Get it from Connections > SDK Setup in the Revenium dashboard.
* Node.js >= 20.19.0

## 1. Install the Revenium CLI

```bash
npm install -g @revenium/cli
```

You can also use `npx` without installing globally:

```bash
npx --package @revenium/cli revenium-codex setup
```

## 2. Run the setup wizard

```bash
revenium-codex setup
```

The wizard prompts for:

* **Revenium API key** — validated against the `hak_` or `rev_` prefix
* **Email** (optional) — for backfill attribution
* **Organization name** (optional) — for grouping usage
* **Product name** (optional) — for sub-segmenting within the organization
* **API endpoint** (optional) — defaults to `https://api.revenium.ai`
* **Config path** (optional) — defaults to `~/.codex/config.toml`

The wizard tests connectivity to the Revenium endpoint before writing the configuration.

### Where the configured email applies

{% hint style="info" %}
The email you enter here attributes **backfilled** usage — historical Codex sessions imported with `revenium-codex backfill` are attributed to this address.

Live Codex sessions work differently, depending on how you're signed in to Codex:

* **Signed in to Codex via ChatGPT:** live usage is already attributed to your signed-in account automatically. No configuration is needed, and the wizard's email does not change this.
* **Using an API key with Codex (no ChatGPT sign-in):** Codex does not send per-developer identity on live sessions in this mode, so live usage is attributed to your account's default identity. Run a backfill to attribute this usage by email instead.
  {% endhint %}

Configuration is written to the `[otel]` section of `~/.codex/config.toml`. If an existing `[otel]` section is found, the wizard prompts before overwriting (use `--force` to skip the prompt).

The wizard also creates a shell wrapper function so that conflicting OTLP environment variables from other tools are automatically unset before Codex runs.

## 3. Restart your terminal

```bash
exec $SHELL
```

## 4. Verify the configuration

```bash
revenium-codex status
```

Confirms that the Revenium endpoint is reachable with the provided credentials.

You can also point to a custom config path:

```bash
revenium-codex status --config-path /path/to/config.toml
```

## 5. Send a test metric

```bash
revenium-codex test --verbose
```

Sends a zero-cost synthetic event to verify the Revenium pipeline is processing Codex data. Check AI Assistants > Codex > Integration Logs to confirm receipt.

You can also test with a custom config path:

```bash
revenium-codex test --verbose --config-path /path/to/config.toml
```

## 6. Start using Codex CLI

After setup, use Codex CLI as you normally would. The `config.toml` `[otel]` section tells Codex where to send telemetry, and the shell wrapper ensures no conflicting environment variables interfere. Usage appears in Revenium after the next telemetry flush.

## 7. Backfill historical data

To import historical Codex usage from local session logs:

```bash
# Backfill from a specific date:
revenium-codex backfill --since 2025-01-01 --to 2025-06-01

# Preview without sending:
revenium-codex backfill --since 2025-01-01 --to 2025-06-01 --dry-run

# Control batch size:
revenium-codex backfill --since 2025-01-01 --batch-size 50

# Custom sessions path:
revenium-codex backfill --sessions-path /path/to/sessions

# Custom config path:
revenium-codex backfill --config-path /path/to/config.toml

# Verbose output:
revenium-codex backfill --since 2025-01-01 --verbose
```

Backfill is idempotent — deterministic transaction IDs prevent duplicate records.

{% hint style="info" %}
**Shell wrapper:** The setup creates a shell function that wraps the `codex` binary. This function unsets `OTEL_EXPORTER_OTLP_ENDPOINT`, `OTEL_EXPORTER_OTLP_HEADERS`, `OTEL_EXPORTER_OTLP_PROTOCOL`, and `OTEL_LOGS_EXPORTER` before running Codex, so that environment variables from other tools (like Claude Code or Gemini) do not conflict with Codex's `config.toml` settings.
{% endhint %}

## 8. Troubleshooting

Start every diagnosis with `revenium-codex status` — it checks, in order, that the config exists, is in the correct form, has telemetry enabled, and can reach Revenium, and it names the exact fix for whatever it finds.

### No data appears in Revenium after setup

The most common cause is that the current shell is still running without the wrapper that Codex needs. Work through these in order:

1. **Restart your terminal.** Run `exec $SHELL` or open a new terminal window so the shell wrapper installed during setup is active. Codex reads its telemetry environment through that wrapper.
2. **Check the configuration.** Run `revenium-codex status`. It reports whether the `[otel]` config is present and valid and whether the Revenium endpoint is reachable.
3. **Send a synthetic event.** Run `revenium-codex test --verbose`, then open **AI Assistants > Codex > Integration Logs** to confirm the event was received. If the test event lands but real sessions do not, Codex is running outside the wrapper — return to step 1.
4. **Confirm a session has flushed.** Usage appears only after Codex's next telemetry flush, so allow a completed Codex session before expecting data.

### `status` reports "legacy flat-key \[otel] form"

An older or hand-edited `config.toml` can store the `[otel]` settings in a flat form that Codex silently ignores — the configuration looks present but no telemetry is exported. Migrate it to the supported form:

```bash
revenium-codex setup --force
```

### `status` reports missing `[features] runtime_metrics = true`

Codex only emits OpenTelemetry data when runtime metrics are enabled. If this flag is absent, no usage is sent even though the `[otel]` block is otherwise correct. Restore it with:

```bash
revenium-codex setup --force
```

### `status` reports "No Codex config found"

There is no `[otel]` configuration at `~/.codex/config.toml`. Run `revenium-codex setup` to create it. If you keep Codex's config in a non-default location, point the CLI at it:

```bash
revenium-codex status --config-path /path/to/config.toml
```

### Connection check fails, or authentication is rejected

If `status` or `test` reports a failed connection or a rejected key:

* **Verify the key type.** Codex telemetry authenticates with a **Revenium** API key (`hak_` or `rev_` prefix), not an OpenAI or other provider key. A provider key authenticates model calls; it will not authenticate telemetry ingest. Get a Revenium key from **Connections > SDK Setup** in the Revenium dashboard.
* **Verify the endpoint.** Confirm it matches your Revenium environment. The default is `https://api.revenium.ai`.
* **Re-enter credentials.** Run `revenium-codex setup --force` to rewrite the `[otel]` block with a corrected key or endpoint.

### Telemetry conflicts with another AI tool

If Codex data is missing or misattributed on a machine that also runs Claude Code or Gemini, a conflicting OTLP environment variable from the other tool is the likely cause. Always launch Codex through a shell that has loaded the Revenium wrapper (restart your terminal after setup) — the wrapper unsets the conflicting variables before Codex runs.

## Command reference

| Command                                              | Description                                  |
| ---------------------------------------------------- | -------------------------------------------- |
| `revenium-codex setup`                               | Interactive setup wizard                     |
| `revenium-codex setup --force`                       | Setup, overwriting existing `[otel]` section |
| `revenium-codex status`                              | Verify connectivity to Revenium              |
| `revenium-codex test --verbose`                      | Send a synthetic test event                  |
| `revenium-codex backfill --since <date> --to <date>` | Import historical session data               |
| `revenium-codex backfill --dry-run`                  | Preview backfill output without sending      |
| `revenium-codex backfill --batch-size <n>`           | Control backfill throughput                  |
| `revenium-codex backfill --sessions-path <path>`     | Custom sessions directory                    |
| `revenium-codex backfill --config-path <path>`       | Custom config.toml location                  |


# AI Assistant Data Reference

Complete reference of all data points collected from AI assistant integrations, including Claude Code, Gemini CLI, Cursor IDE, Claude Cowork, Codex CLI, and GitHub Copilot.

This page documents every data point that Revenium collects from AI coding assistant integrations. Use this reference to understand exactly what telemetry is captured, how it's used, and what privacy guarantees apply.

***

## How Data Is Collected

All AI coding assistant data is collected via **OpenTelemetry (OTLP)** log records. Each coding tool has a dedicated integration that exports usage telemetry to Revenium's OTLP endpoint. No proprietary agents or background processes are involved — data flows through the standard OpenTelemetry protocol.

| Tool               | Integration Method          | Data Flow                                      |
| ------------------ | --------------------------- | ---------------------------------------------- |
| **Claude Code**    | `@revenium/cli` npm package | Claude Code hooks → OTLP logs → Revenium       |
| **Gemini CLI SDK** | `@revenium/cli` npm package | Gemini CLI → OTLP logs → Revenium              |
| **Cursor IDE**     | Admin API sync              | Cursor Admin API → Revenium (periodic)         |
| **Claude Cowork**  | Admin UI (OTLP)             | Claude for Work admin → OTLP logs → Revenium   |
| **Codex CLI**      | `@revenium/cli` npm package | Codex CLI → OTLP logs → Revenium               |
| **GitHub Copilot** | Admin API sync              | GitHub Copilot Admin API → Revenium (periodic) |

### Agent Identifiers

Each tool is identified by an **agent** value in the telemetry:

| Tool           | Agent Identifier |
| -------------- | ---------------- |
| Claude Code    | `claude-code`    |
| Gemini CLI     | `gemini-cli`     |
| Cursor IDE     | `cursor-ide`     |
| Claude Cowork  | `claude-cowork`  |
| Codex CLI      | `codex-cli`      |
| GitHub Copilot | `github-copilot` |

***

## Data Privacy

{% hint style="success" %}
**Revenium never collects your code, prompts, or conversation content.** Only usage metadata is transmitted — token counts, model names, timestamps, and session identifiers. This applies to all integrations by default.
{% endhint %}

Specifically, the following are **never** sent in the default configuration:

* Source code or file contents
* Prompt text or system prompts
* AI response content
* API keys, credentials, or secrets
* Repository names or git history (diffs, commits, file contents)
* Screen content or clipboard data

***

## GitHub Integration Data (Optional)

The following section applies **only** when the optional GitHub integration is connected. Without it, the AI Coding Dashboard operates entirely from OTLP telemetry data and does not interact with GitHub in any way.

### What We Read from GitHub

When the integration is active, Revenium makes the following read-only API calls to GitHub:

| Data Read                                           | Purpose                                                     |
| --------------------------------------------------- | ----------------------------------------------------------- |
| Organization member list (usernames, public emails) | Auto-map developers to their corporate email                |
| Public user profiles and email search               | Resolve GitHub logins to email addresses for attribution    |
| Repository names in the organization                | Determine which repos to scan for merged PRs                |
| Merged PR metadata (author, merge date)             | Count PRs merged per developer in the selected period       |
| Commit messages and commit author emails            | Detect AI co-author patterns (e.g. Co-Authored-By trailers) |

{% hint style="warning" %}
Revenium reads commit messages only to detect AI co-authorship. From each commit it retains the `Co-authored-by:` trailer lines from the message and the commit author email addresses, kept for up to 120 days after the pull request is merged, so that attribution can be recomputed when you change your detection patterns. The rest of the message is discarded, and file contents, diffs, and patches are **never** read.
{% endhint %}

### What We Store

| Stored Data                   | Description                                                                                                                                                                                                                                                                                                               |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Daily PR counts per developer | Number of PRs merged and number of AI-assisted PRs, per day                                                                                                                                                                                                                                                               |
| GitHub-to-email mappings      | Links each developer's GitHub username to their corporate email for attribution                                                                                                                                                                                                                                           |
| Per-PR attribution evidence   | For each merged pull request: GitHub organization and repository name, PR number, merge date, author login, commit count, commit author email addresses, and the `Co-authored-by:` trailer lines. Retained for 120 days after the pull request is merged, so attribution can be recomputed when detection patterns change |

### What We Do NOT Access

Even though the GitHub token may have broad permissions (`repo` scope), our implementation only makes the specific API calls listed above. The following are **never** accessed:

* File contents, diffs, or patches
* Pull request descriptions or comments
* Repository source code
* Issues, reviews, or branch data
* GitHub Actions, webhooks, or deployment data
* Private user profile data beyond public email

### Token Permissions

The GitHub integration uses a fine-grained personal access token with three read-only permissions: Pull requests and Metadata at the repository level, plus Members at the organization level. Classic tokens using `repo` and `read:org` are still accepted, but `repo` grants write access to all repository content and is far broader than Revenium needs.

Revenium never reads repository file contents. There are no calls to the Contents API, git trees or blobs, archive downloads, code search, pull request file diffs, or commit patches.

For details on setting up and configuring the GitHub integration, see [GitHub Integration](/track-and-control-costs/analyze-ai-tooling-spend/github-integration).

***

## Common Data Points

The following data points are collected by **all** AI coding assistant integrations. These form the core telemetry schema that powers the [AI Coding Dashboard](/track-and-control-costs/analyze-ai-tooling-spend).

### Token Metrics

| Data Point                | Type    | Description                                                   |
| ------------------------- | ------- | ------------------------------------------------------------- |
| `inputTokenCount`         | Integer | Number of input tokens consumed in the request                |
| `outputTokenCount`        | Integer | Number of output tokens generated by the model                |
| `cacheReadTokenCount`     | Integer | Tokens served from the model's prompt cache (reduces cost)    |
| `cacheCreationTokenCount` | Integer | Tokens written to the model's prompt cache                    |
| `reasoningTokenCount`     | Integer | Extended thinking / chain-of-thought tokens (model-dependent) |
| `totalTokenCount`         | Integer | Sum of all token types for the request                        |

### Cost Metrics

| Data Point    | Type    | Description                                                     |
| ------------- | ------- | --------------------------------------------------------------- |
| `totalCost`   | Decimal | Calculated cost in USD for this request, based on model pricing |
| `cost_source` | String  | Always `coding_assistant` for AI coding tool traffic            |
| `costType`    | String  | Always `AI` for AI coding assistant requests                    |

### Model & Provider Identity

| Data Point | Type   | Description                                                                                                             |
| ---------- | ------ | ----------------------------------------------------------------------------------------------------------------------- |
| `model`    | String | AI model name (e.g., `claude-opus-4-5-20251101`, `gemini-2.5-pro`, `codex-mini-latest`)                                 |
| `provider` | String | AI provider identifier. Set by backend mappers: `ClaudeCode`, `GeminiCli`, `CursorIde`, `ClaudeCowork`, `CodexCli`.     |
| `agent`    | String | Coding assistant identifier (`claude-code`, `gemini-cli`, `cursor-ide`, `claude-cowork`, `codex-cli`, `github-copilot`) |

### Timing

| Data Point        | Type      | Description                                                   |
| ----------------- | --------- | ------------------------------------------------------------- |
| `requestTime`     | Timestamp | When the request was initiated (ISO 8601 / epoch nanoseconds) |
| `requestDuration` | Integer   | Total request duration in milliseconds                        |

### Attribution

| Data Point         | OTLP Attribute                           | Type   | Description                                                                                                                           |
| ------------------ | ---------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `subscriber`       | `user.email`                             | String | Developer email address for usage attribution (optional, user-configured)                                                             |
| `organizationName` | `organization.id` or `organization.name` | String | Organization or company name/ID for cost rollup (optional). The backend prefers `organization.name`; falls back to `organization.id`. |
| `productName`      | `product.id` or `product.name`           | String | Product or project name/ID for cost rollup (optional). The backend prefers `product.name`; falls back to `product.id`.                |
| `traceId`          | `session.id`                             | String | Session identifier — groups requests within a single coding session                                                                   |
| `transactionId`    | `transaction_id`                         | String | Unique identifier for each individual request (used for deduplication)                                                                |

{% hint style="info" %}
The **Data Point** column shows the name as stored in the analytics database. The **OTLP Attribute** column shows the key name in the raw telemetry payload. The backend mapper translates between these formats during ingestion.
{% endhint %}

### Operational Classification

| Data Point      | Type   | Description                                                                                                                                                                                                                                             |
| --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `operationType` | String | Request classification (e.g., `CHAT`)                                                                                                                                                                                                                   |
| `stopReason`    | String | Why the model stopped generating. Revenium enum values: `END`, `TOKEN_LIMIT`, `ERROR`, `CANCELLED`. See [Gemini Stop Reason Mapping](#stop-reason-mapping) and [Codex CLI Stop Reason Mapping](#stop-reason-mapping-1) for tool-specific normalization. |
| `errorReason`   | String | Error description if the request failed (empty on success)                                                                                                                                                                                              |

### Coding Assistant Account Linkage

| Data Point                      | Type   | Description                                                                        |
| ------------------------------- | ------ | ---------------------------------------------------------------------------------- |
| `coding_assistant_account_uuid` | String | Links telemetry to a specific coding assistant account for cross-session tracking  |
| `subscription_tier`             | String | Subscription plan identifier (see [Subscription Tiers](#subscription-tiers) below) |

***

## Claude Code Data Points

In addition to the [Common Data Points](#common-data-points) above, Claude Code captures the following:

### Subscription Tiers

Claude Code subscriptions tiers are optionally tracked when using the Revenium SDKs:

| Tier           | Description                                                   |
| -------------- | ------------------------------------------------------------- |
| `pro`          | Anthropic Pro plan                                            |
| `max_5x`       | Anthropic Max 5x plan                                         |
| `max_20x`      | Anthropic Max 20x plan                                        |
| `team_premium` | Anthropic Team Premium plan                                   |
| `enterprise`   | Anthropic Enterprise plan                                     |
| `api`          | Direct API usage (full API pricing, no subscription discount) |

### Data Collection Modes

Claude Code supports two data collection modes:

<table><thead><tr><th width="126.33984375">Mode</th><th>Description</th></tr></thead><tbody><tr><td><strong>Real-time</strong></td><td>Telemetry is exported automatically during each Claude Code session via OTLP hooks. Captures core token, cost, and timing metrics.</td></tr><tr><td><strong>Backfill</strong></td><td>The <code>revenium-metering backfill</code> command scans local Claude Code session logs (<code>~/.claude/projects/</code>) and sends historical usage data.</td></tr></tbody></table>

Backfill is idempotent — deterministic transaction IDs (SHA-256 hash of session ID, timestamp, model, and token counts) prevent duplicate records.

### Centralized Claude Code Configuration

For team-wide real-time telemetry, configure Claude Code once with managed settings instead of asking every developer to run local setup.

| Approach                      | Best for                                                                                                | Where configured                                                                      |
| ----------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| **Server-managed settings**   | Claude Teams or Enterprise organizations without MDM, or with unmanaged developer devices               | **Claude.ai → Admin Settings → Claude Code → Managed settings**                       |
| **Endpoint-managed settings** | Organizations with MDM, device-management, registry policy, or system-level managed-settings deployment | macOS managed preferences, Windows policy/registry, or system `managed-settings.json` |
| **Per-developer CLI setup**   | Individual developers, third-party Anthropic providers, one-off setup, or historical backfill           | `@revenium/cli` on each machine                                                       |

#### Organization-Wide Setup

Claude Code supports centrally-managed configuration through the Claude admin console. An administrator defines the settings once; Anthropic delivers them to every authenticated user on next startup. No per-developer install is required. Please see [Setup Claude Code](/track-and-control-costs/analyze-ai-tooling-spend/setup-claude-code)

***

## Gemini Data Points

Gemini CLI data flows into Revenium via the `@revenium/cli` npm package, which configures Gemini CLI's native OTLP export to send telemetry to Revenium's endpoint.

### Gemini CLI SDK Data Points

The CLI SDK captures the [Common Data Points](#common-data-points) listed above — token metrics, cost, model identity, timing, and attribution.

Gemini CLI operates in **real-time only** — there is no backfill capability. Telemetry is captured and exported as each Gemini CLI request completes.

### Stop Reason Mapping

Gemini CLI normalizes Google's finish reasons to Revenium's supported `StopReason` value:

| Gemini Finish Reason                                                         | Revenium StopReason         | Description                                                     |
| ---------------------------------------------------------------------------- | --------------------------- | --------------------------------------------------------------- |
| `STOP`                                                                       | `END`                       | Normal completion                                               |
| `MAX_TOKENS`                                                                 | `TOKEN_LIMIT`               | Token limit reached                                             |
| `SAFETY`, `BLOCKLIST`, `PROHIBITED_CONTENT`, `SPII`, `MODEL_ARMOR`           | `ERROR`                     | Content safety filter triggered                                 |
| `RECITATION`, `IMAGE_SAFETY`, `IMAGE_PROHIBITED_CONTENT`, `IMAGE_RECITATION` | `ERROR`                     | Recitation or image safety filter                               |
| `MALFORMED_FUNCTION_CALL`, `UNEXPECTED_TOOL_CALL`, `NO_IMAGE`                | `ERROR`                     | Tool call or image error                                        |
| `CANCELLED` / `CANCELED`                                                     | `CANCELLED`                 | Request canceled                                                |
| `FINISH_REASON_UNSPECIFIED`, `OTHER`, `IMAGE_OTHER`                          | *(caller-supplied default)* | Returns the default stop reason provided by the calling context |

***

## Cursor IDE Data Points

In addition to the [Common Data Points](#common-data-points) above, Cursor IDE captures the following through its Admin API sync:

### Billing Classification

| Data Point                      | Type   | Description                                                                                                 |
| ------------------------------- | ------ | ----------------------------------------------------------------------------------------------------------- |
| `billing.kind`                  | String | Cursor billing classification (`Included`, `Premium`, etc.) — determines whether usage counts against quota |
| `operation_type`                | String | Operation type from Cursor (e.g., request classification)                                                   |
| `stop_reason` / `finish_reason` | String | Finish reason from Cursor                                                                                   |

{% hint style="info" %}
When `billing.kind` is `Included`, Revenium sets `billingSkipped = true`, `skipReason = FREE_TIER`, and forces `totalCost` to `null` — indicating the request was covered by the subscription and incurred no additional cost.
{% endhint %}

### Setup Model

Cursor is configured through the Revenium dashboard: paste your Cursor **team** API key in **Connections > Providers > Cursor** and the backend syncs usage automatically every 5 minutes. No CLI installation or per-machine setup is required. A team API key is required (not a personal user key) because Revenium pulls from the `/teams/filtered-usage-events` endpoint.

For step-by-step instructions and troubleshooting, see [Setup Cursor](/track-and-control-costs/analyze-ai-tooling-spend/setup-cursor).

### Data Collection Mode

Cursor IDE usage data is collected periodically from Cursor's Admin API. Unlike Claude Code and Gemini CLI, data is not captured in real-time during each request — it is synced at regular intervals from Cursor's team usage API.

***

## Claude Cowork Data Points

In addition to the [Common Data Points](#common-data-points) above, Claude Cowork captures the same telemetry schema as Claude Code — token metrics, cost, model identity, timing, and attribution. Cowork traffic is identified by the `ClaudeCowork` provider and the `claude-cowork` agent identifier, and surfaces on its own **Claude Cowork** dashboard under AI Assistants.

### Setup Model

Claude Cowork is **enterprise / organization-administered** — not a per-user install. An organization administrator enables OTLP export once from the Claude for Work admin console (Claude Desktop → Organization → Co-work → Monitoring), pointing Cowork at Revenium's OTLP endpoint with a metering key (`rev_mk_*`). Anthropic then exports telemetry for every authenticated Cowork user in the organization — there is no `@revenium/cli` install and no per-machine setup.

For step-by-step admin instructions, the exact configuration values, and troubleshooting, see [Setup Claude Cowork](/track-and-control-costs/analyze-ai-tooling-spend/setup-claude-cowork).

### Data Collection Mode

Claude Cowork operates in **real-time only** — there is no backfill capability. Telemetry is captured and exported as each Cowork request completes.

### Billing Classification

Claude Cowork is **metered by usage** (provider-metered) rather than seat-based. The [AI Assistant pricing mode](/track-and-control-costs/analyze-ai-tooling-spend/configure-coding-assistant-billing-models) team setting controls whether Cowork telemetry counts as real API spend in Revenium-wide reporting or stays scoped to AI Assistant analytics.

***

## Codex CLI Data Points

In addition to the [Common Data Points](#common-data-points) above, Codex CLI data is captured through the `@revenium/cli` npm package, which configures Codex CLI's native OTLP export to send telemetry to Revenium's endpoint.

### Data Collection Mode

Codex CLI captures telemetry in **real time**, exported as each Codex CLI request completes, and also supports **backfill** of historical sessions via `revenium-codex backfill`. All Codex CLI traffic surfaces in Revenium under the unified `CodexCli` provider.

### Stop Reason Mapping

Codex CLI normalizes OpenAI's `finish_reason` values to Revenium's supported `StopReason` enum:

| OpenAI Finish Reason | Revenium StopReason         | Description                                                     |
| -------------------- | --------------------------- | --------------------------------------------------------------- |
| `stop`               | `END`                       | Normal completion                                               |
| `length`             | `TOKEN_LIMIT`               | Token limit reached                                             |
| `content_filter`     | `ERROR`                     | Content safety filter triggered                                 |
| `tool_calls`         | `END`                       | Model returned a tool/function call (treated as a normal stop)  |
| *(missing / other)*  | *(caller-supplied default)* | Returns the default stop reason provided by the calling context |

***

## GitHub Copilot Data Points

In addition to the [Common Data Points](#common-data-points) above, GitHub Copilot is exposed in the AI Assistants UI under the `github-copilot` agent identifier.

{% hint style="warning" %}
**Status:** GitHub Copilot Admin API ingestion is in active development. The agent identifier (`github-copilot`) is reserved end-to-end through the UI, but the dedicated backend mapper and tool-specific telemetry fields documented below will land in a follow-up release. Telemetry for the `github-copilot` agent reaches the analytics database via the Common Data Points only until the Admin API sync ships.
{% endhint %}

### Data Collection Mode

GitHub Copilot usage data will be collected periodically from GitHub's Copilot Admin API and exported to Revenium via OTLP, mirroring the Cursor IDE flow. Data will not be captured in real-time during each request — it will be synced at regular intervals from GitHub's administrative endpoints.

***

## Derived Fields

The following fields are **not sent by the SDKs** but are calculated by the Revenium backend during ingestion:

<table><thead><tr><th width="233.3125">Field</th><th>Derivation</th><th>Description</th></tr></thead><tbody><tr><td><code>inputTokenCost</code></td><td><code>inputTokenCount × model_input_cost_per_token</code></td><td>Cost attributed to input tokens</td></tr><tr><td><code>outputTokenCost</code></td><td><code>outputTokenCount × model_output_cost_per_token</code></td><td>Cost attributed to output tokens</td></tr><tr><td><code>cacheCreationTokenCost</code></td><td><code>cacheCreationTokenCount × model_cache_creation_cost</code></td><td>Cost attributed to cache creation</td></tr><tr><td><code>cacheReadTokenCost</code></td><td><code>cacheReadTokenCount × model_cache_read_cost</code></td><td>Cost attributed to cache reads</td></tr><tr><td><code>totalCost</code> (when not provided)</td><td>Sum of all token costs</td><td>Calculated when SDK sends zero or null cost</td></tr><tr><td><code>apiKey</code></td><td>Extracted from <code>x-api-key</code> HTTP header</td><td>Authentication key for tenant identification</td></tr><tr><td><code>credentialId</code></td><td>Extracted from <code>subscriber</code> JSON</td><td>Credential identifier for access control</td></tr></tbody></table>

***

## OTLP Transport Details

For teams implementing custom integrations or verifying data flow, here are the OTLP transport details:

### Endpoint

```
POST {base_url}/v1/logs
```

Where `base_url` is typically `https://api.revenium.ai/meter/v2/otlp`.

### Authentication

```
x-api-key: rev_mk_your_key_here
```

This is a metering key (`rev_mk_*`) — sufficient for OTLP telemetry ingest, which is what every AI coding-assistant integration on this page does. For workflows that also report business outcomes or manage Revenium resources, use a write-scope key (`rev_sk_*`) — see [API Key Permissions](/integrations/api-key-permissions).

### Payload Format

All integrations use the OTLP/HTTP JSON format (`application/json`):

```json
{
  "resourceLogs": [{
    "resource": {
      "attributes": [
        { "key": "service.name", "value": { "stringValue": "claude-code" } }
      ]
    },
    "scopeLogs": [{
      "scope": { "name": "claude-code", "version": "1.0.0" },
      "logRecords": [{
        "timeUnixNano": "1711324800000000000",
        "body": { "stringValue": "claude_code.api_request" },
        "attributes": [
          { "key": "session.id", "value": { "stringValue": "sess-abc123" } },
          { "key": "model", "value": { "stringValue": "claude-opus-4-5-20251101" } },
          { "key": "input_tokens", "value": { "intValue": 1500 } },
          { "key": "output_tokens", "value": { "intValue": 2000 } },
          { "key": "cache_read_tokens", "value": { "intValue": 500 } },
          { "key": "cache_creation_tokens", "value": { "intValue": 0 } },
          { "key": "total_input_tokens", "value": { "intValue": 2000 } }
        ]
      }]
    }]
  }]
}
```

{% hint style="info" %}
The example above shows a Claude Code backfill payload with the core token attributes. The real-time test/connectivity payload (via `revenium-metering test` in each relevant SDK if used) uses `stringValue` for token fields and additionally sends `cost_usd` and `duration_ms`. Gemini CLI and Codex CLI payloads follow the same OTLP structure with `service.name` set to `gemini-cli` / `codex-cli` and scope name set to `gemini_cli` / `codex_cli`. Cursor IDE is exported on the same OTLP transport after Revenium pulls it from Cursor's Admin API; GitHub Copilot will follow the same pattern once the Admin API sync ships.
{% endhint %}

***

## Related Documentation

* [AI Coding Dashboard](/track-and-control-costs/analyze-ai-tooling-spend) — Dashboard views and analysis features
* [Integration Options for AI Metering](/integrations/integrations) — Setup instructions for all integrations
* [OpenTelemetry Integration](/integrations/otlp-integration) — General OTLP integration guide
* [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) — Alerting on coding assistant metrics


# GitHub Integration

Connect your GitHub organization to surface PR attribution and productivity metrics alongside AI coding assistant usage in Revenium.

Connecting GitHub to Revenium adds output data — shipped pull requests — to the AI Coding Dashboard. Without GitHub, the dashboard measures AI assistant activity: sessions, tokens, cost. With it, you can cross-reference that spend against what developers actually deliver, surfacing per-developer productivity metrics and attributing pull requests to AI-assisted commits.

## What connecting GitHub adds

Once connected, the Claude Code **Adoption** tab's Value by User table gains three additional columns:

| Column              | Description                                                                                                 |
| ------------------- | ----------------------------------------------------------------------------------------------------------- |
| **PRs Merged**      | Total pull requests merged by this developer in the selected period                                         |
| **PRs with Claude** | PRs where at least one commit includes a Co-Authored-By trailer matching your configured detection patterns |
| **Cost/PR**         | Total AI spend divided by PRs merged — the cost side of a basic productivity ratio                          |

These columns let you ask: are high-spend developers also shipping the most? Which developers are getting the most delivered per dollar of AI spend? Is AI adoption actually showing up as more code delivery?

## Which tools support PR data

PR attribution currently appears on the **Claude Code** tab only. The detection mechanism is pattern-based rather than tool-specific (see [AI co-author detection patterns](#ai-co-author-detection-patterns) below), so commits from any tool that includes a matching Co-Authored-By trailer are counted. However, the PR columns are only wired into the Claude Code Value by User table — Cursor, Gemini CLI, and Claude Cowork tabs do not display PR data.

## Prerequisites

* A GitHub **fine-grained** personal access token with these read-only permissions:
  * **Repository permissions:** Pull requests, Metadata (auto-selected by GitHub)
  * **Organization permissions:** Members
* Developer email addresses in Revenium must match the email addresses on their GitHub commits for per-developer attribution to work

The connect screen provides a link that pre-selects these permissions for you. If your organization requires administrator approval for fine-grained tokens, the token will stay pending until an owner approves it.

{% hint style="info" %}
Classic personal access tokens are also accepted, using the `repo` and `read:org` scopes. Those scopes are considerably broader than Revenium needs, since `repo` grants write access to all repository content, and classic tokens are not subject to your organization's token approval policy or lifetime limits. We recommend a fine-grained token wherever possible.
{% endhint %}

## Setting up the integration

GitHub is managed under **Connections → Integrations** in the product, on the same tab as the [Slack](/integrations/slack) integration. Connect with a GitHub personal access token carrying the permissions listed in [Prerequisites](#prerequisites) above. The connection screen shows the last successful validation timestamp and offers a **Sync now** action; data refreshes on its natural cadence otherwise. Either integration on the tab can be reconfigured or disconnected without affecting the other.

### Connecting multiple organizations

You can connect more than one GitHub organization to a single Revenium account. Add each organization from the GitHub connect modal; each connection carries its own credential, and PR attribution is drawn from every connected organization. This suits teams whose code is split across separate GitHub organizations rather than concentrated in one.

### Choosing repositories with the repo picker

When you connect an organization, the connect modal presents a **repository picker** listing the repositories the connection can access, so you can select exactly which repositories to track instead of scanning everything. The picker refetches its list when you switch organizations, so it always reflects the repositories available in the organization you're currently configuring.

## Configuring the integration

Open the GitHub settings dialog from the integrations page to refine repository scope and detection patterns.

### Allowed repositories

You can also scope scanning to specific repositories through the **Allowed repos** field, listing them one per line in `owner/repo` format:

```
myorg/backend-api
myorg/mobile-app
```

Leave this field empty to scan all repositories available to the connection.

### AI co-author detection patterns

Revenium identifies AI-assisted commits by scanning each commit's Co-Authored-By trailer and author email for patterns you configure. A PR is attributed when **any commit** in it matches **any configured pattern**.

Patterns are specified one per line. Matching is case-insensitive substring matching on commit messages and exact matching on email addresses. Each pattern must be at least 3 characters.

The default pattern is:

```
noreply@anthropic.com
```

This matches the standard Co-Authored-By footer that Claude Code adds to commits. If your team uses additional tools or custom commit templates, add the corresponding patterns:

```
noreply@anthropic.com
cursor-ai
your-internal-bot@yourcompany.com
```

{% hint style="info" %}
Patterns are configured at the organization level and apply to all dashboards and all team members. There is no per-tool or per-team pattern configuration.
{% endhint %}

### Managing user mappings

Per-developer attribution depends on the email address on a developer's GitHub commits matching the email Revenium has on file. When those don't line up — or when someone commits under more than one address — you can adjust the mapping directly rather than leaving the attribution wrong.

* **Edit an existing mapping** to correct which Revenium user a GitHub identity resolves to.
* **Map multiple GitHub accounts to one corporate email**, so a developer who commits from more than one GitHub account still rolls up to a single person.

Consolidating accounts this way keeps per-developer metrics — PRs merged, PRs with AI assistance, and cost per PR — accurate for people who work across more than one GitHub identity.

## Team filtering and PR scope

The team filter on the Claude Code dashboard applies to AI completion metrics (sessions, tokens, cost). PR data is org-scoped: the PRs Merged and PRs with Claude columns always reflect the developer's activity across the entire organization (or across your allowed repositories list), not filtered by team. To limit PR scope to a specific team's repositories, add those repositories to the Allowed repos field.

## Troubleshooting

**No PR data appears after connecting:**

* Allow up to 15 minutes for the initial sync to complete
* Confirm the token carries the permissions listed in [Prerequisites](#prerequisites) above. A token missing **Pull requests** authenticates successfully but returns no PR data
* Verify the token is valid and not expired — Revenium shows validation status on the integrations page

**Coding assistant-attributed PR count is lower than expected:**

* A PR is attributed to an AI Coding assistant only if at least one commit contains a matching Co-Authored-By trailer. This is user or organization-configurable, and not all Claude Code sessions automatically produce these — check whether commits in those PRs include the trailer
* Confirm the repositories containing the expected PRs are accessible to your token (or listed in Allowed repos)
* Inspect commit metadata in the relevant repository to confirm whether Co-Authored-By trailers appear in the commits you expected to count

**Developer PR counts are not attributed correctly:**

* The email address on the developer's GitHub commits must match the email address Revenium has on file for that user
* GitHub allows per-commit email overrides — developers using a different email for AI-assisted commits will not be matched


# GitLab Integration

Connect your GitLab group to surface merge-request attribution and per-user productivity metrics alongside AI coding assistant usage in Revenium.

GitLab is supported for version-control attribution alongside GitHub. Connecting GitLab to Revenium adds output data — the merge requests your developers ship — to your AI coding metrics. Without a version-control integration, the dashboards measure AI assistant activity: sessions, tokens, cost. With GitLab connected, you can cross-reference that spend against what developers actually deliver, attributing merged merge requests to AI-assisted commits per developer.

Teams that host their code on GitLab now get merge-request attribution and per-user coding metrics, the same way GitHub-hosted teams get pull-request attribution.

## What connecting GitLab adds

Once connected, Revenium builds a per-developer GitLab merge-request table. Each row maps a GitLab user to a Revenium user and shows:

| Column              | Description                                                                           |
| ------------------- | ------------------------------------------------------------------------------------- |
| **GitLab User**     | The GitLab username the activity belongs to                                           |
| **MRs Merged**      | Total merge requests merged by this user in the selected period                       |
| **MRs with Claude** | Merge requests where at least one commit matches your AI co-author detection patterns |
| **Mapped Email**    | The Revenium user this GitLab user is mapped to, by commit email                      |

These let you ask: are high-spend developers also shipping the most? Which developers are getting the most delivered per dollar of AI spend?

## Prerequisites

* A GitLab personal access token with `read_api` and `read_user` scopes
* The GitLab group that contains the projects you want to track
* Developer commit emails that map to Revenium users, so per-developer activity can be attributed

## Setting up the integration

Add GitLab from the Integrations page: open the GitLab card and choose to connect, which opens the **Connect GitLab** dialog. The dialog asks for:

* **Name** — a label for the credential (for example, `my-company-gitlab`).
* **GitLab instance URL** — leave the default for gitlab.com, or enter your self-managed instance URL (for example, `https://gitlab.company.com`).
* **Group path** — the GitLab group containing your repositories (for example, `my-company` or `my-company/engineering`).
* **Personal access token** — a token with `read_api` and `read_user` scopes (`glpat-...`). The token is validated against GitLab before being stored, encrypted at rest, and never returned through the API.
* **Allowed projects** (optional) — restrict the integration to specific projects in `group/project` format, one per line. Leave empty to scan all projects in the group. Useful when your token has broad access but you only want merge-request data from selected projects.
* **AI co-author detection patterns** — see below.

## AI co-author detection patterns

Revenium identifies AI-assisted commits by matching patterns against the Co-Authored-By lines in commits. A merge request counts toward **MRs with Claude** when at least one of its commits matches a configured pattern. The default detects the standard Claude Code signature:

```
noreply@anthropic.com
```

Add additional patterns, one per line, if your team uses different signatures.

## Attribution across GitHub and GitLab

Both GitHub and GitLab are supported for version-control attribution. If your developers ship across both, connect each one: GitHub contributes pull-request attribution and GitLab contributes merge-request attribution, each matched to Revenium users by developer commit email.

## Troubleshooting

**No GitLab data appears after connecting:**

* The table reads "No GitLab merge request data available for this period" until a sync completes for the selected period — allow time for the initial sync
* Confirm the token is valid and carries the `read_api` and `read_user` scopes
* Confirm the Group path is correct and the token can read that group's projects

**MRs with Claude count is lower than expected:**

* A merge request counts only if at least one commit matches a Co-Authored-By detection pattern — not all coding-assistant sessions produce these, so check the commits in those merge requests
* If you set Allowed projects, confirm the merge requests you expect are in the listed projects

**A developer isn't attributed:**

* The Mapped Email links a GitLab user to a Revenium user. If a developer's commit email doesn't match a Revenium user, their activity won't be attributed — confirm the email mapping


# AI Insights

AI-detected anomalies, cost opportunities, and operational issues — with suggested actions for each finding.

AI Insights is a dedicated analytics surface that runs your AI usage data through Revenium's Recommendations Engine and surfaces the findings most worth acting on. Instead of reading dashboards and trying to spot what matters, Revenium analyzes your transaction history including costs, errors, and agent behavior, and hands you a prioritized list of recommendations with concrete suggested actions and the spend at stake.

Each recommendation is grounded in your actual data (no hypothetical advice), tagged with severity and category, linked to the specific transactions that triggered it, and ranked by potential monthly savings.

## Why this matters

AI usage data accumulates faster than most teams have time to read. Patterns that meaningfully affect spend or reliability — wasted spend, agents failing silently, model costs growing faster than the usage that drives them — are scattered across transactions that nobody scans end-to-end.

AI Insights surfaces those patterns automatically. Detectors run across every dimension of your usage and produce a prioritized list of findings, each grounded in your actual data with a potential monthly savings estimate, the affected transactions, and a concrete suggested action.

## How AI Insights works

The Recommendations Engine runs a multi-stage pipeline looking across dozens of dimensions for optimization opportunities. The in-depth analysis takes a few minutes to complete. You'll be notified within the application when the results are available to retrieve. These analyzes can also be triggered and retrieved via API.

## Reading the Insights page

### Summary cards

Four metric cards across the top of the page give you the headline view of the current run:

* **Potential Monthly Savings** — The sum of estimated monthly savings across all recommendations, if each one is acted on. These are estimates derived from your actual usage data, not guarantees.
* **Critical / High Severity** — Critical means immediate action is warranted with strong evidence of significant impact. High means a material problem that should be prioritized as soon as possible.
* **Top Category** — The recommendation category contributing the largest share of impact in this run (Waste, Spend Concentration, Reliability, or Efficiency). Minor issues are also consolidated under a "Worth a Look" category for lower priority issues.
* **Affected Spend** — The total AI spend linked to specific findings in the analyzed window. Potential Monthly Savings is the corresponding 30-day projection of recoverable spend; for 30-day analyzes it will be smaller than Affected Spend, while shorter windows (1d, 7d) may project monthly savings higher than the raw affected spend in that window.

### Recommendation cards

Each recommendation appears as a card with:

* **Severity badge** — Critical, High, Medium, Low, or Info.
* **Category badge** — Waste, Worth a look, Concentration, Reliability, or Efficiency.
* **Monthly impact** — A green badge showing the estimated monthly savings if non-zero.
* **Detector label** — The specific pattern that triggered the recommendation (e.g. "Error concentration", "Outdated model").
* **Title and body** — A plain-English explanation of what was detected. Long bodies truncate with a **Read more** link.
* **Affected entities** — The agents, models, credentials, or subscribers implicated in the finding.
* **Suggested action** — An expandable section with the specific change to make (swap model, adjust prompt, enable a setting, restructure the flow, etc.).
* **Feedback controls** — Thumbs up / thumbs down, plus a dismiss button with reason picker.

Switch between **By impact** (single ranked list across all categories) and **By type** (grouped by category) using the toggle at the top of the list.

### Sample transactions and trace linking

Expand any recommendation to see the sample transactions that triggered the finding — up to 20 transaction IDs per finding. For each sample you can:

* **Copy** the transaction ID to clipboard.
* **Open Trace** — Resolves the transaction to its enclosing trace and navigates to Trace Analytics so you can inspect the full request path, latency breakdown, and downstream calls.
* **Copy Transaction IDs** — Copies all transaction IDs if you wish to investigate these IDs in another system.

### Run history and time range

The meta bar above the cards lets you:

* **Switch runs** — Jump between past analyzes via the run history dropdown.
* **Choose a time range** — Scope the analysis window to the past 1 day, 7 days, or 30 days (default).
* **Run a new analysis** — Click **Analyze** to kick off a fresh run on the selected time range.

## Recommendation categories

Recommendations are grouped into five categories, each describing a different *kind* of problem.

### Waste

> Spend you can eliminate without changing what the workload does — enable a setting, upgrade to current-generation pricing, or stop redundant work. Success rate and capability stay the same.

Examples: an outdated model that has been superseded by a same-price newer version, a prompt that repeatedly misses cache, retry loops billing the same prompt three times.

### Concentration

> A single subscriber, credential, agent, or model accounts for a disproportionate share of spend, errors, or exposure — creating fragility and limiting your optimization leverage.

Acting on Concentration findings often unlocks downstream improvements — when one entity is responsible for a large share of issues, addressing it has outsized leverage even when the immediate dollar impact looks modest.

### Reliability

> The workload is failing, retrying, or degrading at a rate that is itself the problem. Fix improves success rate; cost usually drops as a side effect.

Reliability findings cover error concentration, throttling patterns, correlated error+retry, quality drops, and similar.

### Efficiency

> The cost per successful completion is high relative to what the task warrants. Swap a model, rewrite a prompt, or restructure a flow to produce the same result for less.

Efficiency findings flag places where the same outcome can be achieved for less spend.

### Worth a look

> Something notable you probably haven't seen yet — either a cost that appeared or grew faster than usage justifies, or an option you didn't know was available (like a same-price newer model).

These don't necessarily require action — they're surfaced because they're worth a glance.

## Types of issues AI Insights looks for

Findings span these broad areas:

* **Configuration waste** — workloads paying for outdated models, missed prompt caching, mismatched service tiers, or other settings that can be changed without affecting capability.
* **Failure-driven cost** — errors, retries, throttling, and reliability issues that are themselves driving spend.
* **Concentration risk** — a single subscriber, agent, credential, or model accounting for a disproportionate share of cost, errors, or exposure.
* **Cost-to-outcome misalignment** — workloads where the cost per successful result is high relative to the value of the result.
* **Better alternatives available** — newer or less expensive model options, or tasks better served by a different approach.
* **Unexpected growth** — cost or call volume growing faster than the underlying usage that drives it.
* **Cost outpacing usage** — spend that is climbing faster than the activity driving it, so cost per call is rising even when volume isn't.
* **Out-of-pattern spenders** — a single key, user, product, or agent that has broken from its own established spending pattern.
* **Attribution gaps** — spend that can't be tied back to a known agent, customer, product, or workflow.

## Use cases

* **Pre-renewal review** — Before a contract renewal or budget cycle, run a 30-day analysis to surface every Waste and Concentration finding for review.
* **Incident triage** — When an alert fires for a cost or error spike, an Insights run scoped to the last day or seven days will frequently identify the root finding (error concentration, retry waste, throttling) without manual log diving.
* **Quarterly review** — Compare runs across the quarter to track whether your findings are decreasing — i.e. whether the team is actually closing the optimization gaps.
* **New integration validation** — After connecting a new model, agent, or middleware, run Insights a week later to catch any unexpected fan-out, error patterns, or attribution gaps before they grow into problems.

## API integration

The AI Insights analysis pipeline is also accessible via the public REST API at `/api/v2/insights/*`. Use the API to build polling-based integrations, CI/CD gates, BI exports, or automated feedback loops.

**Quickstart (curl)**

```bash
# 1. Trigger a run — returns 202 immediately with a runId
RUN=$(curl -sS -X POST https://api.revenium.ai/api/v2/insights/runs \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"periodStart":"2024-01-01T00:00:00Z","periodEnd":"2024-01-31T23:59:59Z"}')
RUN_ID=$(echo "$RUN" | jq -r '.runId')

# 2. Poll until complete (status: completed / partial / failed)
while true; do
  STATUS=$(curl -sS "https://api.revenium.ai/api/v2/insights/runs/$RUN_ID" \
    -H "Authorization: Bearer $API_KEY" | jq -r '.status')
  echo "Status: $STATUS"
  [ "$STATUS" != "running" ] && break
  sleep 10
done

# 3. List recent runs (cursor-paginated)
curl -sS "https://api.revenium.ai/api/v2/insights/runs?limit=20" \
  -H "Authorization: Bearer $API_KEY"
```

**Endpoints**

| Method | Path                                    | Description                                        |
| ------ | --------------------------------------- | -------------------------------------------------- |
| POST   | `/api/v2/insights/runs`                 | Trigger a new analysis run (202 Accepted)          |
| GET    | `/api/v2/insights/runs`                 | List runs with cursor pagination and filters       |
| GET    | `/api/v2/insights/runs/:runId`          | Get a single run with findings and `dashboard_url` |
| POST   | `/api/v2/insights/feedback`             | Record feedback on a recommendation                |
| GET    | `/api/v2/insights/runs/:runId/feedback` | List feedback for a run                            |
| GET    | `/api/v2/insights/investigators`        | List available detectors                           |

**Rate limits**: write endpoints (`POST /insights/runs`, `POST /insights/feedback`) share a 5 requests/minute/team bucket. Read endpoints share a 100 requests/minute/team bucket. Deprecated `/recommendations/*` aliases share the same buckets as their canonical `/insights/*` successors. Rate-limit headroom is returned in `RateLimit-Limit`, `RateLimit-Remaining`, and `RateLimit-Reset` response headers.

**Errors**: All error responses use the RFC 7807 `application/problem+json` format with `type`, `title`, `status`, `detail`, and `code` fields.

**Pagination**: `GET /insights/runs` returns `{data: [...], next_cursor: string|null}`. Pass `?cursor=<next_cursor>` to fetch the next page.

**Filters** for `GET /insights/runs`: `?status=completed`, `?since=2024-01-01T00:00:00Z`, `?until=2024-01-31T23:59:59Z`, `?triggered_by=api`

**Deep links**: Every run detail response includes `dashboard_url` — a direct link to the Insights UI page for that run.

**Deprecated aliases**: The previous `/api/v2/recommendations/*` paths are duplicate routes that use the same handlers as `/api/v2/insights/*`. Alias responses include `Deprecation: true`, `Sunset: Fri, 13 Nov 2026 00:00:00 GMT`, and a `Link` header pointing to the canonical `/api/v2/insights/*` successor.

See the interactive API reference at `/api/v2/docs` for full schema details.

## Frequently asked questions

**Do I get charged for analysis runs?** Analysis runs are included in your Revenium subscription at no additional cost.

**How often should I run an analysis?** Weekly is a reasonable cadence for active workloads. For lower-traffic teams, monthly is often enough.

**What if I don't have enough data yet?** The engine works best with at least a few days of meaningful traffic. With very low volume, Worth-a-look and Concentration findings dominate; Waste and Efficiency findings need more data to be confident.

**How are monthly savings estimated?** Savings are projected from the affected-spend slice over the analyzed window, scaled to a 30-day estimate, and adjusted by an estimated capture rate per detector. They're estimates, not guarantees.


# Monitor Latency & Performance

Knowing your AI executed successfully is a low bar. What matters is whether it executed well - and whether the performance you're seeing today is better or worse than it was last week. Revenium's Performance section is where slow agents get caught, degrading models get identified, and inefficient workflows get fixed before they become expensive habits.

Use **Intelligence > Performance** for execution metrics. For cost-first task analysis, open **Costs & Revenue > Tasks**.

***

## Review task spend in Costs & Revenue

Open **Costs & Revenue > Tasks** when the investigation starts with spend rather than execution performance. The redesigned Tasks view keeps four task-cost surfaces together.

### Spend summary

The summary at the top shows total task spend for the selected period and how it changed versus the previous one.

### Cost trend

The cost trend defaults to cost per run, with a **Cost-per-run / Total-cost** toggle so you can switch between per-run efficiency and total task spend across the selected period.

### Spend concentration

A breakdown chart shows how task spend is concentrated — whether a few tasks dominate or it's spread evenly.

### Task breakdown

A table beneath the charts lists each task with its individual spend.

Use the spend view to identify the task that needs attention, then use the Performance task guidance below when the investigation shifts to throughput, completion, duration, or failed runs.

See the **Costs & Revenue** section for the shared cost-analysis workspace and date-range context.

***

### <i class="fa-stopwatch">:stopwatch:</i> Catch Reliability Problems Before Your Users Do

The Tasks view gives you the first signal that something is wrong: completion rate, broken down into successful, timed out, and failed - over time, not just as a snapshot. A completion rate that looks fine today can be masking a window of degradation that happened last Tuesday. The over-time view is what catches that.

When tasks do fail, the **Failed Tasks** table tells you immediately what failed, on which agent, using which model and provider, why it stopped, and how long it ran before it did. You're not hunting through logs - everything you need to start an investigation is in one place.

***

### <i class="fa-traffic-light-slow">:traffic-light-slow:</i> Find Out Which Tasks Are Actually Slow

Not all slowness is equal. **Duration by Task Type** surfaces which operations are taking significantly longer than others. If code analysis is running at ten times the duration of a chat response, that's either a prompt length issue, a model selection problem, or a workflow that needs restructuring - and you won't know which until you can see the comparison clearly.

**Time to First Token** adds the dimension that raw duration misses: the latency your users actually experience. A model that's fast to complete but slow to start feels broken, even if the total response time is acceptable. Tracking TTFT by model over time means you'll spot a provider degradation or model regression as it's happening, not after users have noticed.

<figure><img src="/files/pXHsJ2bBx7zYvZniXUC9" alt="" width="563"><figcaption></figcaption></figure>

***

### <i class="fa-robot">:robot:</i> Hold Individual Agents Accountable

Aggregate metrics hide individual misbehaviour. The Agents view breaks throughput, completion rate, and execution duration down per agent, so an agent that's consistently slower or less reliable than its peers is immediately visible rather than averaged away.

The **Agent Model Comparison** table is where model choice decisions get validated. If you've switched an agent from one model to another, this table shows you the before and after - requests, average duration, TTFT, failure rate, and quality score - side by side. It's the difference between assuming a model change improved things and knowing it did.

**Reliability by Agent** ranks failure rate per agent from highest to lowest. One agent with a disproportionate failure rate is the kind of signal that gets missed in aggregate reporting and found here.

***

### <i class="fa-bone-break">:bone-break:</i> Find the Runs That Are Breaking Your P99

Most traces are fine. The expensive ones - the outliers that are distorting your average and quietly degrading your user experience - live in the tail. The Traces view surfaces them.

The gap between your average duration and your P99 duration tells you how much variance exists in your system. A P99 that's ten times your average means a real proportion of your users are having a dramatically worse experience than your headline metrics suggest. **Performance Anomalies** classify those outliers automatically into Critical (P99), High (P95), and Moderate (P75) tiers, each with an explanation of what's happening and a direct link to filter and investigate the specific traces responsible.

**Four callouts cut straight to the most important signals:** your **slowest trace type** by P95 duration, your **most transaction-heavy trace type**, the trace type with the worst P99/P50 ratio (**the most unpredictable**), and the **trace type that has degraded most** since the previous period. If something has changed in your system, one of those four numbers will tell you.

***

### <i class="fa-eyes">:eyes:</i> Spot Agents That Are Looping

Slowness isn't the only way a workflow can become expensive. The Efficiency view tracks transaction count per trace - how many calls each execution is generating. An agent that's suddenly producing five times its usual transaction count isn't slower in wall-clock time, but it's likely stuck in a loop, making redundant tool calls, or failing to reach a clean exit condition.

**Circular Pattern Analysis** takes this further, automatically detecting whether any workflows have developed circular dependencies - agents or tools calling each other in a loop. This is the failure mode that can turn a $2 workflow into a $200 one before anyone notices. No circular patterns detected is the result you want; when they do appear, this is where you'll find them.

***

### <i class="fa-people-arrows">:people-arrows:</i> Understand How Your Agents Talk to Each Other

For multi-agent architectures, performance isn't just about individual agents - it's about how they interact. The Agent Interaction view tracks patterns, costs, and performance metrics for agent-to-agent calls within a trace, making it possible to see whether the overhead of agent coordination is justified by the outcomes it produces.

This requires your instrumentation to pass `agent`, a shared `traceId` across all transactions in a workflow, and `parentTransactionId` to link agent calls together. See [Instrument Your Code](/track-and-control-costs/instrument-your-code) for setup details.


# Predict & Surface Anomalies

Most performance and cost problems don't announce themselves. They accumulate quietly in the tail of your distribution - a trace type getting gradually slower, an agent generating more transactions than it should, a cost outlier running a hundred times before anyone notices. By the time the problem is obvious, it's already expensive.

Revenium's anomaly detection runs continuously across your instrumented workflows, automatically classifying outliers by severity so you can find and fix the ones that matter before they compound. The goal isn't to alert you to every deviation - it's to surface the ones that are statistically significant, ranked by how urgently they need attention.

<figure><img src="/files/c7ExGHvb3RbOCoIZQrOv" alt="" width="563"><figcaption></figcaption></figure>

***

For prioritized recommendations across cost, reliability, efficiency, and recoverable spend, see [AI Insights](/optimize-performance/ai-insights). AI Insights runs a broader recommendation analysis and links findings back to the transactions and traces that triggered them.

***

### <i class="fa-chart-line-up">:chart-line-up:</i> Two Types of Anomaly

Anomaly detection covers two distinct dimensions of your AI's behavior, each accessible through the Traces view in their respective section.

**Cost anomalies** are in **Intelligence > Performance > Traces**. These compare the cost of individual traces against your historical baseline, flagging executions that are significantly more expensive than expected - whether that's because a model was called more times than usual, a more expensive model was used unexpectedly, or a workflow ran far longer than its typical path. A single cost anomaly can be a one-off; a pattern of them against the same trace type is almost always a prompt or architecture issue worth fixing.

**Performance anomalies** are in **Intelligence > Performance > Traces**. Under the Performance sub-view, anomalies are flagged against trace duration - catching the executions that are taking significantly longer than your historical baseline, even when the completion rate looks healthy. Under the Efficiency sub-view, they're flagged against transaction count per trace, catching workflows that are generating far more calls than expected. This is often the earliest signal of a looping agent - visible here as an efficiency anomaly before the cost impact becomes significant enough to show up elsewhere.

Both surfaces use the same severity classification and the same investigation path, so however you arrive at an anomaly, the process from there is identical.

***

### <i class="fa-cabinet-filing">:cabinet-filing:</i> How Anomalies Are Classified

Every anomaly is automatically assigned a severity based on where it sits in the statistical distribution of your traces:

* **Critical (P99)** - the top 1% of outliers, exceeding the 99th percentile threshold. These require immediate attention and are the first place to look when something has changed in your system.
* **High (P95)** - the top 5%, exceeding the 95th percentile. These should be reviewed and optimized - often they represent the same underlying issue as Critical anomalies, just less extreme instances of it.
* **Moderate (P75)** - the top 25%, exceeding the 75th percentile. These are worth monitoring closely. A Moderate anomaly today that keeps recurring is a High anomaly waiting to happen.

The threshold isn't a fixed number you configure - it's derived from the actual distribution of your traces. A Critical anomaly means something genuinely abnormal for your specific workload, not just a value that crossed an arbitrary limit someone set months ago. As your system changes, the thresholds adapt with it.

When anomalies are present, an inline indicator on the main metric card shows the total count and flags any Critical anomalies specifically, so the most urgent signal is always visible without having to scroll to the anomaly section.

***

### <i class="fa-searchengin">:searchengin:</i> Finding and Filtering Anomalies

Each anomaly section shows three clickable cards - one per severity tier - displaying the count of anomalous traces, an explanation of what's happening at that level, and suggested next steps. The cards aren't just a summary: clicking one filters the anomaly table directly to that severity, so you can focus on Critical traces first without the Moderate ones creating noise. Click again to return to the full view.

The anomaly table gives you everything you need to decide where to look first - when the trace occurred, its Trace ID, type and name, which metric triggered the anomaly, the actual measured value, and the threshold it exceeded:

| Column     | Description                                               |
| ---------- | --------------------------------------------------------- |
| Date/Time  | When the anomalous trace occurred                         |
| Trace ID   | Unique identifier (clickable to view trace details)       |
| Type       | Trace type category                                       |
| Name       | Trace name                                                |
| Metric     | Which metric triggered the anomaly                        |
| Actual     | The measured value that exceeded the threshold            |
| Threshold  | The percentile threshold value that was exceeded          |
| Percentile | Badge showing which percentile was exceeded (P75/P95/P99) |

Traces flagged at multiple severity levels - appearing as both P99 and P95 rows - are the ones most likely to represent a genuine underlying problem rather than a one-off outlier. Clicking any row opens the full Trace Detail View, where you can see exactly what happened inside that execution and why it deviated from the norm.

***

### <i class="fa-question">:question:</i> What to Act On First

Not every anomaly demands the same response. A useful starting point is to look at Critical anomalies first and ask whether the same Trace ID or trace type appears across multiple severity rows - if it does, that's a consistent problem, not a fluke. From there, check whether the anomaly is isolated to a single date or recurring across a period: a one-time spike often has an external explanation, while a recurring pattern usually points to something structural in the workflow or prompt.

Moderate anomalies are worth reviewing periodically rather than immediately - but if the count in that tier is growing week over week, that's the signal to move them up your priority list before they become Critical.

***

### <i class="fa-coins">:coins:</i> Cost Anomalies in Depth

The Cost tab pairs anomaly detection with a full breakdown of where spend is going. At the top, four metric cards summarize **Total Cost**, **Average Cost**, **P95 Cost**, and **Trend** (percentage change vs previous period, with absolute delta). Four insight cards then call out the most expensive trace type, the one with the biggest cost increase, the one with the most P95+ outliers, and the most cost-efficient trace type - so the prioritisation work is done for you.

The **Cost Trends** chart plots cost over time with one line per trace type — clicking a legend entry filters the table below. The **Cost by Operation Type** card breaks total spend across AI operation types (Chat, Embed, Image, Audio) with a sorted, color-coded bar — useful for spotting that "we're spending most on chat completions, but image generation is rising fastest." The dropdown only shows operation types with data in the selected window, so empty categories don't clutter the view.

Setting the grouping control to **Trace type** groups the cost table by trace type with Total Cost, Average Cost, P95 Cost, P99 Cost, and Trend. Rows expand to show the individual traces inside each type — and from there, clicking a single trace opens the Trace Detail View. The Cost Anomalies section underneath the trends chart filters anomalies specifically on `TOTAL_COST`, so you only see cost-related outliers; the inline indicator on the Total Cost metric card scrolls you straight there.

***

## Explain a spend spike by day

Spend charts in **Top Movers** and **AI by Employee** mark days that require investigation. Hover a marker for context, or select the day to open its Day Explainer. The selected day is kept in the URL so the same investigation can be reopened or shared.

### Read the baseline

The Day Explainer compares spend and token usage on the selected day with the rest of the selected period. Use that comparison to understand whether the change came from more usage, a change in effective rate, or both.

### Identify the leading contributors

The explainer identifies the leading employee or model contributors where that data is available. It also shows changes in model mix and rate so you can distinguish a usage increase from a more expensive usage pattern.

### Open transactions or share the day

From the drawer, open the selected day's transactions to inspect the underlying activity. Use the copy-link action to share the same day and context with a teammate.

### Take action for an employee contributor

A budget action appears only when a contributor is recognized as an employee. It is not shown for every spike or every contributor. The action is available only when Guardrails is enabled for the tenant.

For the surrounding cost workflow, see the **Costs & Revenue** section. For employee analysis and Guardrail hand-off, see [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend#ai-by-employee).

***

### <i class="fa-stopwatch">:stopwatch:</i> Performance Anomalies in Depth

The Performance tab tracks execution time across your traces. The four metric cards at the top - **Average Duration**, **P95 Duration**, **P99 Duration**, **Trend** - tell you immediately whether performance is drifting and how much variance is hiding in the tail. The four insight cards highlight the slowest trace type by P95, the most transaction-heavy trace type, the most inefficient (highest P99/P50 ratio), and the trace type with the biggest negative performance trend vs the previous period.

The **Performance Trends** chart breaks duration over time per trace type. Performance Anomalies underneath filter on `TRACE_DURATION` so only duration outliers appear. The Performance by Trace Type table is expandable: each row drills down into individual traces, each clickable through to the Trace Detail View.

The combination of these surfaces is what makes "slow agents getting slower" visible — a single P99 spike is one investigation; the same trace type appearing in P99 and P95 rows over a recurring period is a workflow that needs structural attention.

***

### <i class="fa-rotate">:rotate:</i> Efficiency Anomalies & Circular Patterns

The Efficiency tab tracks transaction count per trace - how many calls each execution generates. **Average Transactions**, **P95 Transactions**, and **P99 Transactions** sit at the top alongside a Trend metric. Insight cards surface the most efficient trace type, the least efficient, the one with the highest variability, and the one with the most outliers.

The **Efficiency Trends** chart plots transaction counts over time, with optional P95/P99 percentile overlays and a switch between line and scatter views.

The most valuable section sits underneath: **Circular Pattern Analysis**, a dedicated panel that detects loops in your traces — agents calling each other in repetitive sequences that often indicate broken exit conditions, missing caching, or a planner that can't decide. Each detected pattern shows:

* The call sequence (e.g. `Agent A → Agent B → Agent A`).
* Occurrence count.
* Total wasted duration and cost.
* Severity badge (Critical, Major, Minor) — filterable inline.
* Hop count (how many calls form the loop).

Patterns are ranked by impact, with summary metrics for **Patterns Detected** and **Total Waste** at the top. Use this as the primary signal for "should this workflow be restructured?" - circular patterns are the failure mode that turns a $2 workflow into a $200 one before anyone notices.

The Efficiency Anomalies section below the pattern panel filters anomalies on `TRANSACTION_COUNT`, surfacing traces with unusually high call counts that may not yet have triggered a circular pattern but are headed that way.

***

### <i class="fa-people-arrows">:people-arrows:</i> Agent Interaction Patterns

For multi-agent architectures, the Agent Interaction view tracks agent-to-agent calls within a trace. Four metric cards summarize **Agents** (unique active agents), **Interactions** (total agent-to-agent calls), **Total Cost** (cumulative cost of all agent interactions), and **Avg Interactions/Agent**.

The centrepiece is the **Agent Activity Matrix** — an interactive grid where rows are "from" agents and columns are "to" agents, with cells showing the chosen metric (Call Count, Total Cost, or Avg Duration). Color intensity scales with magnitude, the rightmost Total column shows each agent's total activity, and self-interaction cells (the diagonal) are dimmed and disabled. Switch between Absolute mode (colours from raw values) and Relative mode (colours from each agent's proportion of total activity) to spot different patterns: Absolute shows which agents are most active in your system; Relative shows which agent pairs dominate each agent's outbound traffic.

Hover any cell for raw value, activity classification (Low → Extreme), comparison vs median, percentage of agent's total activity, and typical-range context. Sort agents alphabetically or by Total Activity, and filter to a specific subset for focused investigation.

The **Agent Interactions** table below the matrix lists every from-agent → to-agent pair with Call Count, Total Cost, and Avg Duration columns. This is the surface for cost-attribution conversations: which agent pairs are driving spend, and is the orchestration overhead justified by the outcomes it produces?

***

### <i class="fa-diagram-project">:diagram-project:</i> Trace Detail View

When you click a trace from any tab, the Trace Detail View opens a complete picture of that one execution.

The header shows the **Trace Type** badge, **Trace ID** (the same `traceId` you pass in your API calls), **Task Type**, and **Agent**. Metric badges underneath display Total Cost, Duration, Time to First Token, Total Tokens, Transaction Count, and Success/Error counts. Context badges complete the picture: Subscriber, Organization, Product, Environment, Provider(s), Model(s).

A **Transaction Timeline** waterfall renders every transaction as a horizontal bar — bar length scales with duration, colours indicate model/provider, and tooltips show full transaction metadata on hover. Bottlenecks reveal themselves visually: a single bar consuming most of the timeline is the call that's setting the trace's wall-clock duration.

The **Dependency Tree** is the more powerful surface. It renders the parent-child relationships between transactions (set via `parentTransactionId`), showing how a trace actually executed:

* **Nodes** show agent name, task type, model, individual duration and cost, and the cumulative path duration and cost from the root.
* **Edges** show parent → child flow.
* **Critical Path** highlights the longest execution path — the chain of calls that determined the trace's overall duration.
* **Bottleneck Indicators** mark transactions that ran significantly longer than the trace's average (the threshold is roughly 2.5× average duration).
* **Lane Summaries** at the bottom of the tree aggregate metrics for each path: total duration, total cost, node count, and whether the path is on the critical path.

The tree also classifies the workflow into a pattern type:

* **Linear** - sequential execution, no branching.
* **Converging Paths** - parallel branches that share a common parent.
* **Multi-Root** - multiple independent execution trees in a single trace (often a sign of unrelated work being mis-correlated under one Trace ID).

Click any node to open a **Transaction Details Drawer** with the full call payload. **Optimization Potential** surfaces explicitly when a non-critical path is significantly faster — telling you how much time you could save by speeding up the critical path.

Underneath the tree, four breakdown cards give you the aggregate views: **Cost by Model**, **Cost by Provider**, **Token Breakdown** (input vs output), and **Duration by Task Type**. A complete **Transaction Details Table** lists every transaction with full metadata, exportable to CSV.

***

### <i class="fa-gear-code">:gear-code:</i> Setting Up Traces

Anomaly detection and the Trace Detail View only work as well as the metadata you pass when sending AI transactions. To get the most value:

* **Trace ID** — use consistent trace IDs to group related transactions into a workflow. Don't reuse a Trace ID across unrelated executions; do reuse it across the spans of one execution.
* **Trace Type** — categorize workflows (e.g. `chat-completion`, `document-analysis`) so aggregations are meaningful at the trace-type level.
* **Task Type** — label the operation each transaction performs.
* **Agent** — identify which agent or service produced the transaction so the Agent Interaction matrix has signal.
* **Parent Transaction ID** — set parent-child relationships to enable the Dependency Tree. Without this, you'll still get cost and duration metrics, but the tree collapses into a flat list and Critical Path detection isn't available.

For the full instrumentation pattern see [Instrument Your Code](/track-and-control-costs/instrument-your-code).

***

> **Through MCP, conversationally.** Anomaly review is recurring work. Check whether anything new has surfaced, look for patterns that keep coming back, decide what's worth acting on this week. An AI assistant connected to Revenium via the MCP Server can run that review on demand or on a schedule. Ask "any new anomalies since Monday and which customers do they affect?", "have we had recurring spend anomalies on any specific model this month?", or "set an alert if any customer's spend rises more than 20% week over week." The agent runs the queries, surfaces the patterns, and tells you what changed. Useful for keeping the review going when nobody has time to log into the dashboard.


# Debug Logs & Traces

A cost spike on a dashboard, a slow response a customer complained about, an agent workflow that didn't finish - in each case the question is the same: what actually happened, and where did it go wrong? Without structured transaction data, answering that means stitching together provider logs, application traces, and cost reports that were never designed to talk to each other. By the time you've reconstructed the picture, the same problem has already run hundreds of times more.

Revenium captures every AI transaction with full financial and attribution context attached. The logs and trace views are where you stop guessing and start knowing - which call was expensive, which workflow it belonged to, which customer triggered it, and where in a multi-step run things went off track.

### <i class="fa-list-ul">:list-ul:</i> Transaction Logs as a Single Source of Truth

The log in **Data > Logs** records every AI call that has flowed through Revenium, with cost, model, duration, and attribution all visible in the same row. There's no separate system for "what it cost" and "who ran it" - they're the same record, queryable in real time with auto-refresh on.

Filters at the top let you narrow by time window, metric type, or any column you've added through Manage Columns. The **Include AI coding assistant logs** toggle separates AI development tool traffic - things like Claude Code - from your application's own AI workloads, which matters more than it sounds. Coding assistants generate a high volume of transactions and can dominate the log if you're trying to isolate something else.

Beyond standard LLM completions, the same view also covers:

* **Product Transactions** : usage events that generate line items for billing (either to your customers, or for cross-charging AI usage to other business units)
* **System** : platform-level activity
* **Tool Registry** : cost-generating external tools called by agents (i.e. usage-based APIs like Firecrawl or third-party services like Stripe Identity)
* **Exports** : downloadable data for finance or analytics workflows

Every row links straight into the transaction detail, so moving from "this looks abnormal" to "here's exactly why" never requires leaving the page.

### <i class="fa-rectangle">:rectangle:</i> Everything Revenium Knows About a Single Transaction

Open the detail panel on any row and Revenium shows you the full record of what happened on that one call. This is the layer beneath your dashboard - useful when an aggregated metric raises a question that only the underlying data can answer.

The detail covers:

* **Token usage** broken down across input, output, reasoning, cached, and cache creation - so you can see whether the cost was driven by prompt size, response length, or whether cached context is being reused efficiently
* **Cost** split between input and output rather than shown as a blended figure, which makes it obvious what was actually expensive
* **Timing** across every phase of the call - request time, time to first token, full duration, tokens per second - which lets you tell apart a slow model from a slow network from a slow upstream prompt chain
* **Attribution** to the organization, subscriber, product, agent, and squad responsible - so cost ownership is immediate rather than reconstructed after the fact

If a call is missing attribution data, that itself is useful information. It tells you the workflow that triggered it isn't fully instrumented, and the fix is to update the metering payload to include the missing identifiers.

From the detail panel, **Open full trace view** drops you into the workflow this transaction belonged to.

### <i class="fa-arrow-right">:arrow-right:</i> Seeing How a Workflow Actually Ran

Individual transactions are the atomic unit, but problems usually live at the workflow level. An agent run that lasted hours and cost tens of dollars isn't explained by any single call - it's explained by the sequence of calls, the agents involved, and which steps consumed the most time and money.

The Trace view assembles that sequence. The summary header gives you the headline figures for the run - total cost, total duration, transaction count, success/error ratio, and the models, providers, and task types involved. Below that, two visualisations show the workflow from different angles:

* **The Transaction Timeline** is a Gantt chart of every transaction in the trace, sequenced chronologically and color-coded by agent. Each bar shows the duration and cost of that step. In multi-agent runs the timeline makes handoffs and bottlenecks immediately visible - which agent ran when, which step took longest, which one cost the most - without having to do any arithmetic.
* **The Dependency Tree** shows the structural pattern of the run - sequential, parallel, multi-root - and the cost and duration of each branch. This is the right view when you need to know whether the cost is concentrated in one agent or genuinely distributed across the workflow, because the answer changes what you fix.

Aggregated breakdowns sit beneath both, summarizing cost by model, cost by provider, the input/output token ratio, and time spent by task type - all scoped to this single trace, not your account-wide averages.

### <i class="fa-layer-group">:layer-group:</i> Grouping Traces by Job

A single business process is usually made up of more than one trace. An agentic job that qualifies a lead, or a workflow that resolves a support ticket, can span several related trace types — each captured as its own trace even though they all serve the same outcome. Looked at one trace at a time, the steps that belong together stay scattered, and a cost or latency anomaly in one step is hard to read against the process it's part of.

Grouping traces by job collapses those related trace types into a single group, so you can see and compare the steps of one business process together instead of as isolated traces.

#### How job grouping works

Revenium ties a trace to a job through the job identifier attached when the underlying transactions are metered. Traces that share the same job identifier belong to the same business process; traces without one remain ungrouped. This is the same job model used on the ROI surface — see [Analyze Decision Costs](/instrument-your-agents/analyze-decision-costs) for how jobs are defined and how the identifier is supplied when metering.

Set the grouping control to **Job** and the cost and anomaly breakdown combines the related trace types under the business process they belong to, so a whole job reads together; set it to **Trace type** to keep each execution type on its own.

#### Using the grouping control

On the Traces cost view, a grouping control switches how costs and anomalies are broken down:

* **Trace type** isolates anomalies within a single execution type — the right view when you're looking at one kind of step.
* **Job** combines the multiple trace types involved in the same business process or outcome, so the cost and anomalies for a whole job read together instead of scattered across its steps.

Job is the view to reach for when the question spans a whole process rather than a single call — comparing the trace types that make up one outcome, and spotting which step carries the cost or the delay against the related steps around it.

### <i class="fa-bug">:bug:</i> Where to Start When Something Goes Wrong

Investigations almost always run broad-to-narrow. Start in the transaction log, filter by whatever you know about the problem - the subscriber who complained, the time window of the spike, the trace type that's been flagged - and look for the rows that stand out on cost or duration. Open the transaction detail to confirm what you're looking at, then follow the trace link to see the workflow context around it.

The pattern that tends to emerge is that expensive or slow traces aren't random. The same trace type, the same agent, or the same task type appears repeatedly at the top of the cost distribution. When that's the case, the fix is almost always in the prompt or workflow logic for that specific path - not in the infrastructure, and not in the model choice. The role of the logs and traces is to get you to that conclusion in minutes rather than hours.

### <i class="fa-comments">:comments:</i> Reading the Prompt Behind a Transaction

When a transaction's cost, latency, or output looks wrong, the numbers only tell you *that* something happened - the prompt tells you *why*. Open any transaction's detail panel and, where prompt data is available, the **Prompt Data** section opens a full-screen viewer of the exact conversation that produced the call.

The viewer breaks the call into three parts:

* **System Prompt** - the instructions that defined the model's behavior for this call.
* **Input Messages** - the conversation sent to the model, split message-by-message and tagged by role (system, user, assistant, tool) so a long multi-turn exchange is easy to scan.
* **Output Response** - the model's generated reply.

Each section carries its own character count and its share of the request's token total, so you can see at a glance whether a bloated system prompt, a long input history, or the response itself drove the token count - and copy any section to the clipboard for closer inspection. Very large prompts are truncated at 50,000 characters per field, and the viewer flags when that has happened so you don't mistake a cut-off prompt for the whole story.

Because prompt content is sensitive, access is governed by two independent controls:

* **Team prompt capture** must be enabled in the team's **AI Settings** for prompts to be recorded at all - with it off, there is simply no captured content to show.
* **The "Can View Prompt Data" permission** controls *who* may read that content. Users without it see a locked placeholder rather than the prompt; Tenant Administrators have access implicitly. Both controls, and why prompt access is deliberately separated from ordinary cost data, are covered in [Manage Users & Teams](/account-and-resources/manage-users-and-teams).

> **Through MCP, conversationally.** The cost-investigation work this page describes is also accessible to an AI assistant connected to Revenium via the MCP Server. Instead of clicking through filters, you describe the problem in natural language. Ask "why did my costs spike yesterday?", "which customer drove the increase this week?", or "is one model accounting for most of the unusual spend?" and the agent breaks the data down across providers, models, customers, agents, or API keys, and explains what it finds. Useful when the question is exploratory rather than known.


# Export Cost & Usage Data (FOCUS)

Your AI cost data doesn't stay in Revenium. Finance runs on spreadsheets, FinOps platforms, and cloud cost tools that expect a standard shape - and until AI spend lands there in the same format as the rest of the bill, it stays invisible to the people who allocate budgets and reconcile invoices. Revenium exports every AI transaction in the **FOCUS** format - the FinOps Open Cost and Usage Specification - so AI usage sits alongside your cloud spend without a bespoke integration in between.

There are two ways to get the data out, both in **Data > Logs** under the **Exports** tab: a one-off download for ad-hoc analysis, and a scheduled delivery straight to your own Amazon S3 bucket for pipelines that run without anyone in the loop.

### <i class="fa-download">:download:</i> Download a FOCUS file on demand

The **FOCUS Export** card produces a file in your browser from whatever range and shape you choose. Three controls decide what comes out:

* **Date Range** - the window of transactions to include.
* **Rollup By** - the level of aggregation. Leave it at **Transaction-level** for one row per AI call, or roll the data up by **Agent**, **Squad**, or **Organization** to get one summarized row per dimension with cost and tokens already totaled.
* **Export Stream** - which shape of data to produce (see below).

Click **Download FOCUS CSV** and the file downloads directly. Very large ranges are capped per download; when a range exceeds the limit the export completes with a partial set and the confirmation tells you to narrow the date range to capture everything. Rows that are missing the timestamps FOCUS requires are skipped and counted in the same confirmation, so a short export is always explained rather than silent.

#### Export streams

The **Export Stream** setting tailors the output to where the data is going:

| Stream           | What it produces                                                     | Built for                                           |
| ---------------- | -------------------------------------------------------------------- | --------------------------------------------------- |
| **Unified**      | The full FOCUS v1.0 record set, every column                         | General FinOps ingestion                            |
| **Usage Only**   | Date, product, customer, usage quantity and unit - no dollar amounts | Usage-metering tools such as Cloudability           |
| **Revenue Only** | Date, service, customer, revenue amount                              | Revenue-tracking tools such as Apptio               |
| **Split**        | Both the Usage Only and Revenue Only files in one action             | Pipelines that consume usage and revenue separately |

### <i class="fa-cloud-arrow-up">:cloud-arrow-up:</i> Schedule exports to Amazon S3

The **Scheduled Exports** card removes the manual step entirely: Revenium writes FOCUS files to an S3 bucket you own, on a schedule, so a downstream pipeline can pick them up without anyone triggering a download. Each destination you add appears in the list with its bucket path, schedule, region, format, and the time and status of its last run.

Choose **Add Export Destination** and provide:

| Field                 | Required | Notes                                                                                  |
| --------------------- | -------- | -------------------------------------------------------------------------------------- |
| **Destination**       | Yes      | Amazon S3                                                                              |
| **Export Name**       | Yes      | A label for the destination, e.g. *Production FinOps Export*                           |
| **Bucket Name**       | Yes      | The S3 bucket name, without the `s3://` prefix                                         |
| **Path Prefix**       | No       | An optional folder path within the bucket, e.g. `revenium/focus/`                      |
| **Region**            | Yes      | The AWS region the bucket lives in                                                     |
| **Access Key ID**     | Yes      | An AWS access key ID (begins with `AKIA` or `ASIA`)                                    |
| **Secret Access Key** | Yes\*    | The matching secret. The IAM user needs `s3:PutObject` permission on the target bucket |
| **Schedule**          | Yes      | **Hourly**, **Daily**, or **Weekly**                                                   |
| **File Format**       | Yes      | **CSV** or **Parquet**                                                                 |
| **Rollup By**         | No       | Same aggregation choices as the on-demand download                                     |
| **Export Stream**     | No       | Same stream choices as the on-demand download                                          |

When you save a destination with credentials, Revenium tests the connection to the bucket before storing it, so a bad key or a missing permission surfaces immediately rather than at the first scheduled run.

{% hint style="info" %}
Credentials are write-only. When you edit an existing destination, the Secret Access Key field stays blank - leave it blank to keep the stored credential, or enter a new value to replace it.
{% endhint %}

Each saved destination gives you three actions:

* **Export Now** - trigger a delivery immediately instead of waiting for the schedule, useful for verifying the pipeline end to end.
* **Edit** - change any setting, including rotating the credentials.
* **Delete** - remove the destination and stop all scheduled exports to it.

### <i class="fa-table">:table:</i> What's in a FOCUS file

The **Unified** stream follows the FOCUS v1.0 specification: standard columns describe the charge (`BilledCost`, `EffectiveCost`, `ListCost`, `ListUnitPrice`, `BillingCurrency`), the period (`ChargePeriodStart`, `ChargePeriodEnd`, `BillingPeriodStart`, `BillingPeriodEnd`), and the provenance of each line (`Provider`, `PublisherName`, `ServiceCategory`, `ServiceName`, `SkuId`, `ResourceId`, `ResourceName`). AI usage is measured in the standard pricing fields - `PricingQuantity` carries the token count and `PricingUnit` is `Tokens`.

On top of the specification, Revenium adds AI-specific extension columns, each prefixed with `x_` as FOCUS requires for vendor extensions:

| Column                    | Meaning                                        |
| ------------------------- | ---------------------------------------------- |
| `x_ModelName`             | The model that produced the completion         |
| `x_AiInputTokens`         | Input (prompt) tokens                          |
| `x_AiOutputTokens`        | Output (completion) tokens                     |
| `x_AiCacheCreationTokens` | Tokens written to the provider's prompt cache  |
| `x_AiCacheReadTokens`     | Tokens served from the provider's prompt cache |

Attribution metadata - product, agent, squad, and region - travels in the standard FOCUS `Tags` column as structured data, so allocation survives the export. Amounts use your account's default billing currency. When you roll the export up by a dimension, each row aggregates the cost and tokens for that dimension over the period rather than listing individual calls, and the rows are ordered by cost so the largest contributors sit at the top.


# Tutorial: Build Usage-Based Billing

Turning AI usage into revenue is one of the hardest problems in monetising an AI product. You have variable per-request costs from your providers, a subscription plan you want customers to pay for, and an overage model for when they go beyond what's included - and all three need to reconcile, invoice correctly, and support dozens of customers on different plans at the same time. Building that from scratch takes months. Revenium gives you the full billing engine, the metering pipeline, and the subscription logic out of the box, so the question stops being "how do we build this?" and becomes "how do we want to price it?"

This tutorial walks through a working usage-based billing configuration end to end. Every step can be done in the UI or automated via the API - the UI is faster for initial setup and day-to-day operations, the API is what you'll reach for once customer signups, plan changes, and billing operations need to happen automatically as part of your product. Each step calls out what's available programmatically and links to the relevant section of the [API reference](https://revenium.readme.io) so you know where to look.

<figure><img src="/files/cHl5kCOGjJ6FXo8RB5uX" alt="" width="563"><figcaption></figcaption></figure>

### <i class="fa-brain-circuit">:brain-circuit:</i> The Example We'll Use

We'll work through a realistic scenario: a software company selling AI-powered document summarisation. Their product offers two services - a lightweight summary using a cheap model, and a deeper research service using an expensive reasoning model. They want to sell this as a subscription with a fixed monthly fee that includes a set amount of usage, then charge per-use overages once that's exhausted.

This shape - fixed fee plus metered overages - covers the vast majority of usage-based AI pricing models, so what you build here applies directly to most real products.

### <i class="fa-object-ungroup">:object-ungroup:</i> The Objects That Make Billing Work

Four objects do the work in Revenium's billing system, and every configuration step maps to one of them:

* **Sources** are the systems sending usage data. For an AI product this is the SDK or metering API calls from your application.
* **Products** are what you sell. A product combines one or more sources with pricing, invoicing periods, and billing rules.
* **Subscriptions** are issued when a customer buys a product - they link a specific customer to a specific plan.
* **Subscribers** are the customers themselves.

The chain runs in one direction: a subscriber owns a subscription, which grants access to a product, which meters usage from one or more sources. When a metering event arrives, Revenium follows that chain to determine who to bill and how much. Every object in this chain has full API coverage, so the whole setup can be automated when you're ready.

### <i class="fa-play">:play:</i> Step 1: Confirm Your Usage Data Is Flowing

Nothing else in the billing stack works without clean metering data, so this is the first thing to check. If you've completed [Instrument Your Code](/track-and-control-costs/instrument-your-code) you're most of the way there, but for billing specifically every call must carry:

* `subscriber.id` (nested under the `subscriber` object) - the end customer
* `productName` - the commercial tier they're on
* `organizationName` - the top-level account, when customers belong to companies with multiple users

Without these, Revenium still captures cost and token data, but it can't map usage to a subscription — which means it can't bill for it. Head to **Data > Logs** and check that recent transactions show the Organization and Subscriber columns populated. For the full field list and SDK syntax, see [SDK Setup → Usage Metadata](/integrations/sdk-setup#usage-metadata).

**Via API:** the metering API is the direct ingestion route if you're not using an SDK. There are dedicated endpoints for [AI completions](https://revenium.readme.io/reference/meter_ai_completion), [images](https://revenium.readme.io/reference/meter_ai_images), [video](https://revenium.readme.io/reference/meter_ai_video), [audio](https://revenium.readme.io/reference/meter_ai_audio), [tool calls](https://revenium.readme.io/reference/meter_tool_event), and [generic custom events](https://revenium.readme.io/reference/meter_event) - plus full [OpenTelemetry (OTLP) support](https://revenium.readme.io/reference/otlp_metrics) for teams that already emit telemetry through existing observability stacks. All of them accept the three identifier fields above.

### <i class="fa-tags">:tags:</i> Step 2: Create Your Product

Head to **Configuration > Revenue Sources** and open the **Products** tab. Revenium will have auto-created a default product for any metering calls it's already seen - you can either edit one of those or click the **+** button to create a new one.

#### The Core Fields

Every product has the same required fields at the top:

* **Product Name** - what customers see on invoices and what your team sees in dashboards.
* **Sources** - the data sources that feed usage into this product. Select AI for AI metering data, or any other source type you have connected.
* **Currency** - the currency all charges on this product will be invoiced in.
* **Recurring Charge** - the fixed fee per invoicing period. For the summarisation example, this is the $199/month subscription price.

Above the pricing section, four optional modules can be toggled on: **Provider Notifications** (cc internal addresses on all customer emails), **One Time / Setup Fee**, **Free Trial**, and **Custom Metadata**. Turn these on only when you need them.

#### Configuring Usage-Based Pricing

Under **Configure Usage-Based Pricing** you set two top-level choices:

* **Metered Element** - what you're charging on. "Total Cost" charges based on the AI cost Revenium has calculated - pass-through with or without a markup. Alternatively you can charge on any metering element defined in the Usage Meters tab under Revenue Sources: tokens, pages, characters, credits consumed, or any custom unit.
* **Aggregation Method** - how values are combined within an invoicing period. "Sum Element Values Received" is the default. Other options (average, maximum, count of occurrences, count of unique values, match-specific-value) each fit different pricing shapes.

Then you define **Pricing Tiers**. Each tier has:

* **Tier Name** - your internal label (e.g. "First 1,000", "1,000+").
* **Tier Max Value** - the upper bound. The final tier is always Unlimited.
* **Unit Rate** - price per unit within this tier.
* **Fixed Cost / Tier** - optional flat charge that applies when a customer enters this tier, on top of unit rates.

A tier structure for the summarisation example:

* **Tier 1**: First 1,000 units at $1.50 per unit
* **Tier 2**: 1,001+ (Unlimited) at $1.35 per unit

Add more tiers with **Add Pricing Tier**, or add entirely separate pricing metrics - charging on tokens *and* transactions, for example - with **Add Pricing Metric**. Enabling **Notify at tier threshold** sends automated emails when a percentage of each tier is consumed.

#### Invoicing, Schedule, and Payment Options

* **Invoicing Period** - monthly, annual, custom intervals, or the short 5-minute testing periods that let you validate a full billing cycle in an hour.
* **Invoice Schedule** - In Advance (recurring fees at period start) or In Arrears (everything at period end). Usage fees are always in arrears.
* **Payment Options** - Invoice Only, Invoices with External Payment Updates, or Stripe-Enabled Payments.

**Via API:** [products](https://revenium.readme.io/reference/get_product) can be created, updated, and managed programmatically, including pricing tiers and all invoicing rules. [Metering elements](https://revenium.readme.io/reference/get_metering_element_definition) have their own endpoints, so custom pricing units can be provisioned alongside the products that use them. For teams running custom or fine-tuned AI models with non-standard pricing, tenant-specific [AI model pricing overrides](https://revenium.readme.io/reference/batch_save_pricing_dimensions) are also available.

### <i class="fa-users">:users:</i> Step 3: Create the Subscriber and Subscription

Subscriptions live under **Configuration > Billing**, then the **Subscriptions** tab. This is the action that actually activates billing for a customer.

Click **+** and fill in:

* **Customer Name** - an existing organization or a new one
* **Product Selection** - the product from Step 2
* **Subscriber's Email** - the end user receiving invoices
* **Subscriber Credentials** - leave blank for auto-creation
* **Subscription Name** - a label used internally and on invoices
* **Subscription Start Date** - when billing begins

Toggle **Enable extended config** for the optional components: Expiration Date, Custom Metadata, Allow Immediate Cancellations, and Notifications / Audience Filters.

Once saved, the subscription is live. From that moment, metering events that attribute to this subscriber + product combination get rated against this plan.

#### When One Customer Has Multiple API Keys

In B2B scenarios a single customer company often needs multiple API keys - one per team or application. Revenium handles this with **Subscriber Credentials**: multiple credentials attached to the same subscription. The customer receives one consolidated invoice, but internal usage can still be broken out by key. If metering events include a subscription ID without an explicit credential, Revenium auto-creates one.

**Via API:** this is the step most teams automate first. Customer signup in your own product can trigger a chain of calls to Revenium to provision the [organization](https://revenium.readme.io/reference/get_organization) (for B2B customers), create the [subscriber](https://revenium.readme.io/reference/get_subscriber), issue the [subscription](https://revenium.readme.io/reference/get_subscription) against the right product, and optionally provision specific [credentials](https://revenium.readme.io/reference/get_credential). Plan upgrades, downgrades, and cancellations all happen through the same endpoints - and real-time quota-consumed and billed-amount lookups are available if you want to surface that data inside your own product.

### <i class="fa-desktop">:desktop:</i> Step 4: Test Before You Go Live

Before pointing real customers at this configuration, test it end to end. This is where the 5-minute invoicing period earns its keep.

Create a test subscription for your own account, temporarily set the product's invoicing period to **5 Minutes (randomized synthetic transactions)**, and let it run for an hour. Every five minutes Revenium will close out an invoice, reset usage counters, and generate notifications exactly as it will in production - compressed into a timeframe where you can actually watch it happen.

Check **Billing > Invoices** to watch invoices appear. Verify:

* Recurring charges appear correctly
* Usage charges accumulate against tiers
* Overage rates kick in at the right threshold
* Totals match what you expect

**Via API:** automated end-to-end billing tests can fire metering events, list the resulting [invoices](https://revenium.readme.io/reference/list_invoices), and assert on the billed amount at the subscription level. A 5-minute period plus API-driven assertions makes it practical to validate billing logic as part of CI rather than as a manual pre-launch check.

### <i class="fa-credit-card">:credit-card:</i> Step 5: Connect Payments

For Stripe-Enabled Payments, connect Stripe under **Configuration > Billing > Payment Gateways**. Click **+** and provide:

* **Name** - an internal label
* **Payment Provider** - Stripe
* **Tax Behavior** - how Stripe handles tax on invoices
* **Secret API Key** and **API Publishable Key** - from your Stripe dashboard

Once saved, the gateway becomes available as a payment option on any product. Invoices charge automatically against the card on file, with payment status tracked back into Revenium so you can see paid, pending, and failed without reconciling between two systems.

For invoice-only billing, no payment setup is needed.

### <i class="fa-eyes">:eyes:</i> Step 6: Customize What Customers See

Under **Configuration > Billing > Notification Templates** you can customize every email Revenium sends to customers - New Invoice, Subscription Created, Subscription Canceled, Free Trial Notification, Quota Warning, Quota Tier Warning, Successful Payment, Payment Failed, Subscription Expiration. Each can be toggled on or off and edited individually.

Upload an **Email Notification Logo** so invoices and emails carry your branding rather than Revenium's. For most businesses this should be one of the first things configured, because customers see these emails long before they see any dashboard.

### <i class="fa-toolbox">:toolbox:</i> What You've Built

With the six steps complete, you have a working usage-based billing system. Every AI call is metered, routed to the right customer's subscription, and priced against the right plan in real time. Invoices generate automatically, combining recurring fees and overages. Customers pay via whichever method you've configured, and the Costs & Revenue dashboards give full visibility into usage, revenue, and margin per customer.

This is also the foundation for everything else in the monetisation stack. Pricing rules, free trials, setup fees, volume discounts, named-customer audiences, commerce portal publishing, and product-level SLAs are all additions to the configuration you've just built - not separate systems.

Once the setup is live, the API becomes the better surface for anything you want to integrate elsewhere: pulling [billing analytics](https://revenium.readme.io/reference/list_workspace_metrics) into finance dashboards, surfacing consumption displays inside your own product, monitoring [budget pacing](https://revenium.readme.io/reference/get_budget_progress) across all customers, reporting [profit margin](https://revenium.readme.io/reference/get_api-v2-analytics-profit-margin-per-customer-1) by customer or product, or triggering on-demand billing data refreshes.


# Create Pricing Models & Products

Real-world AI pricing models rarely stay simple for long. A customer might want a flat recurring fee plus overages on tokens, or volume discounts that kick in at specific tiers, or per-feature charges alongside a base subscription. Most billing engines force you to pick one shape and live with it; Revenium's product configuration is built from a small set of composable building blocks, which means almost any pricing model you can design fits into the same structure without custom code.

This page is a reference for every pricing capability available on a product. Skim it once to understand what's possible, then come back to the relevant section when you're configuring a specific pricing model.

### <i class="fa-dollar-sign">:dollar-sign:</i> The Two Pricing Primitives

Two building blocks cover the pricing surface. Almost every pricing model you can design is a combination of these:

* **Pricing Tiers** - the most common building block. Usage ranges with a per-unit rate and/or a fixed per-tier charge.
* **Metering Elements** - custom units of usage beyond transaction counts. Tokens, pages, characters, minutes, credits, or anything else your product consumes.

### <i class="fa-stairs">:stairs:</i> Pricing Tiers - The Default Building Block

Tiers are how most pricing models express the basic shape of "a certain amount included, then charged per unit above that." Each tier defines a usage range and the price within that range:

* **Tier Name** - your internal label (e.g. "First 1,000", "1,000+").
* **Tier Max Value** - the upper bound. The final tier is always Unlimited.
* **Unit Rate** - price per unit within this tier.
* **Fixed Cost / Tier** - an optional flat charge applied when a customer enters this tier, on top of unit rates.

A simple two-tier structure might look like: first 1,000 units at $1.50 per unit, then 1,001+ at $1.35 per unit. Tiers can be stacked as deep as you need, and you get two distinct charging modes to choose between:

* **Charge per tier** - each transaction is priced at the rate of the tier it falls into. Transaction 1,200 is charged at the overage rate; transaction 800 is still at the included-unit rate.
* **Highest tier reached** - once a customer reaches a higher tier during the period, all their transactions for that period are re-rated at the higher tier's price.

Per-tier pricing is the standard choice for most AI products - it's what customers intuitively expect. Highest-tier-reached is a stronger volume incentive and works well for predictable-usage enterprise deals, but can produce surprising invoices for variable workloads.

You can also combine multiple pricing metrics on a single product. Adding a second metric (with **Add Pricing Metric**) gives it its own tier structure, which is how you express "charged on input tokens *and* output tokens" or "charged per transaction *and* per unique active user" in one product.

### <i class="fa-list-timeline">:list-timeline:</i> Pricing on Units Other Than Transactions

Transaction-count pricing ("$X per request") is the simplest model, but it's rarely the right one for AI products where per-request cost varies by orders of magnitude depending on prompt length, model, or output size. **Metering Elements** solve this by letting you charge on any value passed in the metering payload.

Head to **Configuration > Revenue Sources > Usage Meters** to create a metering element. Each one has a key name (the field Revenium looks for in your payloads), a description, and a data type - number or string. Revenium creates common AI-related elements automatically (Input Tokens, Output Tokens, Character Count, Credits Consumed, Duration Seconds, Resolution, Quality), but you can add any custom unit your product uses.

Once the element exists, you can reference it on a product's pricing configuration. The key is the **Aggregation Method** - how the values received during an invoicing period get combined into a single billable number:

* **Sum Element Values Received** - totals every value reported during the period. The default for cost and token metering.
* **Average of All Values Received** - averages across the period. Useful for things like average response quality or latency.
* **Maximum of All Values Received** - the highest value seen. Useful for tiered resource access ("you're billed at the highest resolution tier you used this month").
* **Count Element Occurrences** - counts how many times the element appeared with any value. Useful for feature usage billing.
* **Count Unique Values Received** - counts distinct values. Useful for "per active user" or "per unique customer" billing.
* **On each occurrence of specific value** - fires a charge every time a specific value shows up. Example: $2 every time the `country` field equals "Germany".
* **On first occurrence of specific value** - fires once per period, the first time a specific value appears. Useful for one-time activation charges triggered by usage.

A single product can combine pricing on multiple elements. Click **Add Pricing Metric** to add a second (or third) element with its own aggregation method and tier structure. This is how you express "$0.001 per input token and $0.003 per output token" as a single product.

### <i class="fa-retweet">:retweet:</i> Recurring Charge Behavior

Two fields control how the fixed monthly/annual fee is applied:

* **Invoice Timing** - charge the recurring fee at the start or end of each invoicing period. Customer prepayment is common; post-payment is usually for enterprise contracts with net terms.
* **Allow immediate cancellations and pro-rated invoices** - when a subscription is canceled mid-period, either the subscription remains active through end-of-period (default) or it cancels immediately and a pro-rated invoice is generated for the partial period.

### <i class="fa-table">:table:</i> Custom Metadata

Arbitrary key-value pairs attached to the product. Metadata isn't used by Revenium's billing engine directly, but it's returned on product queries and shows up in analytics, which makes it useful for product categorisation, internal tagging, or passing values through to downstream finance systems.

### <i class="fa-tags">:tags:</i> Free Products

It's valid (and often useful) to create products with no pricing. Three common reasons:

* **Internal reporting** - grouping AI usage by internal team or project without invoicing it. Gives you the same analytics surface as a paid product.
* **Free tiers** - limited usage that's included at no charge. The structure lets you build freemium funnels without building the billing logic yourself.
* **Chargebacks** - internal cost allocation across business units. Revenium tracks the AI cost, but doesn't generate a customer invoice.

To create one, simply leave the pricing section blank when configuring the product. You'll usually also want to disable **Send Invoices to Subscription Owners** so the customer doesn't receive zero-dollar invoices.

### <i class="fa-ruler-combined">:ruler-combined:</i> Designing Pricing - A Practical Approach

When you're designing a new pricing model, the order that tends to work is:

1. **Start with metering elements.** What are you actually charging for? Transactions? Tokens? Minutes of audio? Pages processed? Get the unit right before thinking about the rate.
2. **Add tiers.** Most pricing models fit a "first N units included, then per-unit overage" shape. Start there.
3. **Add a recurring charge.** The fixed subscription fee that covers the included usage.

The biggest mistake teams make is over-complicating the initial pricing model. Launch with the simplest structure that works, then add complexity as you learn what customers actually value. Revenium's configuration is flexible precisely because pricing changes frequently in practice - changing a tier structure on a live product is a form change, not a code change.

### <i class="fa-code">:code:</i> Via API

Most of what's on this page can be configured programmatically. [Products](https://revenium.readme.io/reference/get_product) and [metering element definitions](https://revenium.readme.io/reference/get_metering_element_definition) both have full CRUD endpoints - useful when you want to manage many products, version-control pricing configuration in a repo, or deploy pricing changes through an automated workflow rather than the UI.


# Manage Customers & Credentials

Most billing problems don't come from the billing engine - they come from the customer layer beneath it. A customer who should be getting one consolidated invoice ends up with five. An internal team's AI usage never gets attributed back to them. A support engineer needs to know which subscription generated a spike, but there's no clean way to trace from a metering event back to the account that caused it.

Revenium's customer model is built around four objects - Organizations, Subscribers, Credentials, and Statements - that together answer four related questions: *Who's the customer? Who's using the service? Which API key is this call coming from? What do they currently owe?* Getting this model right upfront is what makes the rest of billing and analytics work cleanly.

All four live under **Configuration > Customers**, as tabs across the top of the page.

### <i class="fa-users">:users:</i> The Customer Hierarchy

The four objects map to four levels of granularity:

* **Organizations** represent the top-level customer account. An external company buying your product, or an internal business unit being allocated costs.
* **Subscribers** are individual users or service accounts within an organization. They're the entity that generates usage.
* **Credentials** are the unique identifiers - typically API keys - that a subscriber uses to access your service. A single subscriber can hold multiple credentials.
* **Statements** are the financial view - outstanding balances and unpaid invoices per customer, aggregated across everything below.

The flow runs downward: an organization has one or more subscribers, each subscriber holds one or more credentials, and statements roll up the financial state of everything underneath. A metering event arriving with a credential ID gets traced back through the chain to land on the right subscription and the right statement.

### <i class="fa-building">:building:</i> Organizations

Head to **Configuration > Customers > Organizations** to see every customer account you have. The list shows Name, ID, Parent ID, and External ID - with the ID columns being Revenium's stable hash identifiers that survive renames.

Click **New Org** to add one. Creation happens across three steps:

#### General

* **Name** (required) - what the organization is called. Shown in dashboards, invoices, and analytics.
* **Parent** - optional. Setting a parent nests this organization under another one, which is how you express structures like a parent company with multiple subsidiaries or a business unit with sub-teams. Omit it for top-level organizations.
* **External Id** - optional identifier for mapping to an external system (your CRM, ERP, or customer database). Useful when you want to correlate Revenium records with records elsewhere.
* **Currency** - the default currency for this organization's billing. Defaults to USD.
* **Associated Domains** - optional list of email domains tied to this organization. Useful for B2B scenarios where you want subscribers with matching email domains to be recognized as belonging to this organization.
* **Storefront URL** - optional URL for linked commerce portal configurations.

#### Billing

Address and billing contact information used on invoices and statements:

* **Address 1** and **Address 2** - street address
* **Country**, **State**, **City**, **Zip** - geographic fields
* **Billing Phone Number** - contact number for billing queries
* **Billing Email** - where invoices and billing notifications are sent
* **Remittance Instructions** - free-text field for payment instructions that should appear on invoices

None of these are required to create the organization. They're prompted at creation because it's easier to fill them in once upfront than to come back later - but they can be skipped and added on edit.

#### Metadata

**Custom Metadata** lets you attach arbitrary key-value pairs to the organization. Each entry is a Field Name plus a Field Value, and you can add as many as you need with the **+** button. Metadata isn't used by Revenium's billing engine directly, but it's returned on API queries and surfaces in analytics - useful for internal tagging, segmentation, or passing attributes through to downstream finance systems.

### <i class="fa-basket-shopping">:basket-shopping:</i> Subscribers

**Configuration > Customers > Subscribers** lists every individual user or service account across all organizations. The table shows Organization/Email, First Name, Last Name, and Subscriber ID.

Click **Add Subscriber** to create one. The form is a single step:

* **First Name** and **Last Name** - optional identification fields.
* **Email** (required) - this is the primary identifier for the subscriber and is what metering events should reference when they want to tie usage to a specific person or service account.
* **Subscriber ID** - optional custom identifier. If not supplied, Revenium generates one.
* **Organizations** (required) - which organization this subscriber belongs to. Defaults to UNCLASSIFIED if unset.

The UNCLASSIFIED organization is Revenium's default bucket for subscribers whose organization hasn't been specified. If you see a lot of activity landing there, it's a signal that your metering events are missing organization identifiers - which is worth fixing for attribution and analytics clarity.

### <i class="fa-key">:key:</i> Credentials

A credential is how a specific API key or token identifier gets tied to a subscriber and, optionally, a subscription. The **Credentials** tab lists every credential across the system with columns for Created, Subscriber, Credential Name, Organization/Subscriber, and Credential ID.

Click **New Credential** to add one:

* **Subscriber Credential Name** (required) - your internal label for this credential. Typically describes which application or team the key is for (e.g. "Mobile App Production Key" or "Data Science Team - Staging").
* **Subscriber E-Mail** (required) - which subscriber owns this credential. Pick from the subscribers in the system.
* **Organization** (required) - which organization the credential belongs to. Normally matches the subscriber's organization.
* **Credential ID** (required) - the actual unique identifier your application will include in metering events. This is what ties an incoming metering event to this credential. Commonly an API key, OAuth client ID, or JWT identifier.
* **External Secret** - optional secret associated with the credential. Not surfaced in metering events.
* **Subscription** - optionally attach this credential to a specific subscription. If not set, the credential exists standalone and will be auto-associated when the first metering event arrives.
* **Tags** - optional free-form tags for filtering and grouping.

The key design point: multiple credentials can belong to a single subscriber, and multiple credentials can be attached to the same subscription. This is what makes B2B scenarios work cleanly - a customer company gets one subscription, issues multiple API keys to their internal teams, and you can both consolidate billing into one invoice *and* report usage separately per key.

#### When to Create Credentials Explicitly

If a metering event arrives with a subscription identifier but no matching credential, Revenium auto-creates one. That's fine for simple cases, but there are two reasons to create credentials explicitly:

* **Provisioning specific API keys in advance** - when your application issues keys to customers ahead of first use, so the credential exists before any metering event arrives.
* **Adding metadata** - names, tags, external secrets, or explicit subscription links aren't created automatically, so explicit creation is how you get those attached.

### <i class="fa-file-invoice">:file-invoice:</i> Statements

The **Statements** tab gives a customer-level financial summary. The table shows Customer, Outstanding Balance, and Open Invoices - with every customer in the system listed, regardless of whether they currently owe anything.

The **Unpaid Invoices** link on each row opens the filtered invoice view for that customer - useful when chasing outstanding payments or investigating a specific account.

This is the view to send to anyone asking "what do our customers currently owe us?" without giving them access to individual subscription or transaction detail.

### <i class="fa-object-group">:object-group:</i> Designing Your Customer Model

Two decisions matter more than the rest:

**One subscription per customer, or one per use case?** In B2B scenarios, most teams start with one subscription per customer company and handle internal team attribution through credentials. This gives one invoice per company, while still letting you report usage and cost per team. Creating multiple subscriptions per customer makes sense when different teams genuinely buy different products, or when contractual terms vary per subscription.

**How far down to nest organizations?** Revenium supports parent/child organization hierarchies. For external customers, a flat structure is usually enough. For internal cost allocation across a large organization, nested orgs let you roll up costs from teams → departments → divisions cleanly. Don't over-model this upfront - it's easier to introduce hierarchy later than to flatten it.

### <i class="fa-code">:code:</i> Via API

Everything on this page can be managed programmatically, which matters most when customer signups and provisioning need to happen automatically as part of your own product. Full endpoints for [organizations](https://revenium.readme.io/reference/get_organization), [subscribers](https://revenium.readme.io/reference/get_subscriber), and [credentials](https://revenium.readme.io/reference/get_credential) cover create, read, update, delete, and list operations. [Invoices](https://revenium.readme.io/reference/list_invoices) are available via API for teams pulling statement data into their own admin tools.

The typical B2B signup flow on the customer side is four chained calls: create the organization, create the subscriber under it, issue a subscription (covered in [Build Usage-Based Billing](/monetize-your-ai/tutorial-build-usage-based-billing)), and optionally create explicit credentials for each API key the customer needs. Store the IDs returned from these calls against your own customer records and the rest of billing happens automatically from that point.


# Strict Ingestion Mode

Require metering data to reference objects that already exist in your account, so unrecognized records are held for review instead of entering automatically.

Strict ingestion mode is an optional, per-account setting that requires every metering payload to reference objects — products, subscribers, credentials, organizations, and subscriptions — that already exist in your account. It is turned off by default. When you turn it on, Revenium stops creating new objects automatically from incoming metering data, so any record that references something unrecognized is held for your review instead of quietly entering your account.

***

## How strict ingestion works

By default, when a metering event refers to one of those objects that Revenium hasn't seen before, Revenium creates it automatically so no usage is lost. Strict ingestion mode changes that trade-off for accounts that want tighter control over what enters their data.

When strict ingestion mode is on:

* Every incoming metering event is checked against those objects that already exist in your account.
* Events whose references all resolve are ingested normally.
* Events that reference something unknown — or whose name and identifier point at different objects — are not ingested. Each is recorded as an ingestion failure with a specific reason, so you can see exactly what needs fixing.

When a record is held back, it and the reason it failed are kept so you can correct it and resubmit it. Held records are retained for 30 days; if a record is not corrected within that window, it is permanently deleted — so review and resubmit held records before then.

{% hint style="info" %}
Strict ingestion mode is off by default. While it is off, Revenium continues to create unrecognized references automatically, so no configuration is required to keep metering flowing. Turning it on is a deliberate choice for accounts that prioritize data governance and want to prevent unrecognized data from entering automatically.
{% endhint %}

## Turning it on

Strict ingestion mode is controlled per account and can be enabled by an administrator with permission to manage your account settings. Turn it on when you want incoming metering data validated against your existing objects, and turn it off at any time to return to automatic creation. The setting applies to metering events received after it is enabled.

## What gets held back

When strict ingestion mode is on, a metering event is held back if any of the objects it references can't be matched in your account. Each held record is labeled with the reason it failed:

* **Product not found** — the payload references a product that doesn't exist in your account.
* **Product name/ID mismatch** — the product name and identifier in the payload point to different products.
* **Subscriber not found** — the payload references a subscriber that doesn't exist.
* **Subscriber name/ID mismatch** — the subscriber name and identifier point to different subscribers.
* **Credential not found** — the payload references a subscriber credential that doesn't exist.
* **Organization not found** — the payload references a consuming organization that doesn't exist.
* **Organization name/ID mismatch** — the organization name and identifier point to different organizations.
* **Subscription relationship not found** — no subscription links the referenced subscriber to the referenced product.
* **Required reference missing** — the payload leaves out a reference that strict ingestion requires.

Each reason is a stable, named category, so you can filter and triage held records by exactly what went wrong.

## Reviewing and resubmitting held records

From the ingestion failures list for your account, you can:

* See held records, newest first, and filter them by failure reason.
* Identify what's missing or mismatched — for example, a product or subscriber that needs to be created, or a payload that referenced the wrong identifier.
* Correct the underlying object or the sending integration, then resubmit the affected metering so it ingests cleanly.

Because each held record keeps its original details and its failure reason, reviewing and resubmitting is a routine cleanup step.


# Automate Invoicing & Payments

Once products and subscriptions are in place, the billing lifecycle takes over. Every invoicing period, Revenium needs to generate invoices against real usage, send them to the right customers, track whether they're paid, handle the occasional refund or credit, and keep every party informed through branded email notifications. Done manually, each of these steps is a support ticket waiting to happen. Done well, the lifecycle is invisible - invoices arrive, payments clear, and the only time a human gets involved is when something genuinely unusual happens.

Revenium automates the full cycle. This page walks through each part of the billing lifecycle under **Configuration > Billing**, so you know what to configure, what to monitor, and where to go when something needs attention.

### <i class="fa-credit-card">:credit-card:</i> Subscriptions - Where the Cycle Starts

Every invoice in Revenium traces back to a subscription. The **Subscriptions** tab is the authoritative view of every active customer relationship, showing Name, Product, Organization, Subscriber, Recurring Charge, and Subscription Period in one sortable list.

Two things about this view are worth calling out.

The first is that subscriptions don't only get created manually - they can also be **auto-discovered** or **auto-generated**. When a metering event arrives with a new subscription identifier, Revenium creates the subscription automatically so that no billable usage is ever dropped. You'll see these in the list with names like "Auto discovered subscription for..." or "Auto generated subscription for...". They start with "Activation Pending" status until fully configured, which is a useful signal for anyone reviewing provisioning: if a customer is live but their subscription is still pending activation, the manual configuration step hasn't happened yet.

The second is that the **Subscription Period** column tells you where each subscription is in its billing cycle. This is often the first place to look when a customer reports an invoicing issue - if the dates don't line up with expectations, the problem is usually in the subscription configuration rather than in the invoice generator.

#### Adding a Subscription Manually

Click the **+** button to add one. The base configuration needs:

* **Customer Name** - which organization this subscription belongs to
* **Product Selection** - the product the customer is buying
* **Subscriber's Email** - the end user receiving invoices and notifications
* **Subscriber Credentials** - optional; leave blank for auto-creation when the first metering event arrives
* **Subscription Name** - the label that appears on invoices and in internal dashboards
* **Subscription Start Date** - when billing begins

Four optional components sit alongside the base config: **Expiration Date** (for fixed-term contracts), **Custom Metadata**, **Allow Immediate Cancellations**, and **Notifications / Audience Filters**. Toggle them on when a subscription needs them rather than configuring them pre-emptively.

### <i class="fa-file-invoice">:file-invoice:</i> Invoices - The Financial Audit Trail

The **Invoices** tab is a full history of every invoice Revenium has generated, filterable by date range and sortable on any column. Columns include Timestamp, Customer, Subscription Owner, Product Name, Total Amount, Refund Amount, and Payment Configuration - giving you a single view that answers "when was it generated, who was it for, what was on it, has it been refunded, how is it being paid?"

Three controls make this view genuinely useful in practice:

* **Date range picker** - default view covers a recent window, but for historical queries or annual reconciliations you can scope to any period.
* **Show Failed Payments Only** - toggle that filters to only invoices where payment has failed. This is the list to work through when a finance team asks "what's outstanding?" - it filters out the noise of successfully paid invoices.
* **Advanced Search** and **Export** - search finds specific invoices across large datasets without scrolling; export pulls invoice data out as CSV for downstream finance or reconciliation workflows.

When an invoice doesn't look right, clicking through into it shows the line-item breakdown - recurring charges, usage charges per tier, any setup fees or one-time charges, taxes, and the final total. This is the record you send to customers disputing a bill, and the record you reference when something needs to be refunded.

### <i class="fa-arrow-u-turn-up-left">:arrow-u-turn-up-left:</i> Refunds - Issuing Credits

Things occasionally go wrong. A customer gets double-charged, a promotional credit needs to be applied, a pricing error needs to be corrected. The **Refunds** tab handles these cases, with a Credit History showing Timestamp, Created By, Product, Refund Amount, View Notes, and Actions.

Click **Issue Refund** to open the refund form:

* **Refund or Credit Type** - Issue a credit to be applied in a future invoice. This credits the customer's account so the amount comes off their next invoice, rather than generating an immediate payment reversal.
* **Customer** (required) - the customer the credit applies to
* **Subscription** (required) - the specific subscription to apply the credit against
* **Refund Amount** (required) - the value of the credit, in the subscription's currency
* **Creator** - auto-populated with the logged-in user; this is what shows up in the Created By column and in any audit trail
* **Refund Notes** - free-text context explaining why the credit was issued. Worth taking the time to fill in properly - this is what you'll thank yourself for when a customer asks six months later why a credit appeared on their account

Once saved, the credit is logged in the Credit History tab and will be applied automatically to the customer's next invoice on that subscription.

The Export option lets you pull the full credit history out for finance reconciliation, and the date range filter makes it easy to scope to a specific period for quarterly or annual reviews.

### <i class="fa-mailbox">:mailbox:</i> Notification Templates - Making Email Work for You

Every automated email Revenium sends to a customer goes out through a configurable template. The **Notification Templates** tab is where you customize what customers actually see when invoices arrive, subscriptions change, or payments fail.

#### Brand the Emails First

At the top of the page is **Email Notification Logo**. Upload your own logo here so that all emails carry your branding rather than Revenium's default. For most businesses this should be the first thing configured - customers see these emails long before they see any dashboard, and a branded invoice email looks significantly more professional than a generic one.

#### The Templates

Revenium ships with a template for every type of event a customer might need to hear about. Each one can be toggled on or off independently, and each can be previewed, edited, or test-sent from the Actions column:

* **New Invoice** - sent at the end of each invoicing period with the invoice attached
* **Subscription Update** - sent when a customer upgrades or downgrades to a different product
* **Subscription Canceled** - sent when a subscription is deactivated, whether through end-of-term or for other reasons
* **Subscription Created** - sent to confirm a new subscription and list the included assets
* **Free Trial Notification** - sent when a subscription's free trial period is ending
* **Quota Warning** - sent when a configured percentage of a product's quota has been consumed
* **Quota Tier Warning** - for volume-based pricing models, sent when a configured percentage of a tier's quota has been consumed
* **Successful Payment** - sent when payment is received for a monetized product with a linked payment provider
* **Payment Failed** - sent when a payment from a connected payment provider fails
* **Subscription Expiration Notice** - sent to product owners and subscribers when a subscription is set to expire

#### Editing a Template

Clicking into any template opens a view showing the email's current state - subject line, body, and where customer-specific values get substituted. Bodies use template variables like `{Recipient}`, `{Storefront Url}`, and `{Revenium Organization Name}` to personalise each message.

A typical New Invoice template body reads:

> Hi {Recipient},
>
> The invoice for your API usage is attached.
>
> If you have any question about the charges, please visit the help section of the API storefront {Storefront Url}
>
> Thanks, – The {Revenium Organization Name} Team

Edit these to match your own brand voice, support process, and tone. The defaults are functional but generic - a customized template tends to convert significantly better on payment actions and generates fewer support queries about what an email is asking the customer to do.

#### Send Test Emails Before Going Live

The Actions column includes a send icon that lets you fire a test email to yourself or a teammate. Use it whenever you've edited a template - it's much easier to spot a broken variable or awkward phrasing in your own inbox than in a customer's.

### <i class="fa-ruler-combined">:ruler-combined:</i> Designing an Invoicing Process

When putting this together for the first time, the order that works best is:

1. **Brand your emails** - upload the logo and edit the templates before any real customer invoice goes out
2. **Validate one subscription end-to-end** - use a 5-minute invoicing period (from the [Build Usage-Based Billing tutorial](/monetize-your-ai/tutorial-build-usage-based-billing)) to cycle through invoice generation, notification delivery, and payment tracking in under an hour
3. **Set up failed-payment monitoring** - plan who responds when the Show Failed Payments Only view shows a failure, not if
4. **Document your refund process** - decide upfront who has permission to issue credits and what the reasoning needs to include, so the Refund Notes field gets filled in properly from the start

Most billing problems come from skipping one of these steps. An un-branded template undermines the invoice. An un-tested subscription discovers problems at month-end instead of day one. An unclear refund process means credits get issued without context and nobody remembers why.

### <i class="fa-code">:code:</i> Via API

The whole lifecycle is available programmatically for teams integrating invoicing and payments into their own systems. [Subscriptions](https://revenium.readme.io/reference/get_subscription) have full CRUD endpoints so signups, upgrades, and cancellations can all happen through your product rather than through the UI. [Invoices](https://revenium.readme.io/reference/list_invoices) can be listed and inspected via API - useful for pulling invoice data into finance dashboards or customer-facing billing pages. Real-time [subscription billed amount](https://revenium.readme.io/reference/get_subscription_billed_amount) and [quota consumption](https://revenium.readme.io/reference/get_subscription_quota_consumed) endpoints let you surface current balance and usage inside your own product without waiting for the next invoicing cycle.


# Payment Integration

Generating invoices is one half of the billing cycle. Collecting payment against them is the other. Without automation, every invoice means chasing a payment manually, reconciling when it lands, and following up when it doesn't - work that scales linearly with customer count and is exactly the wrong kind of work for a growing business to be doing.

Revenium integrates with Stripe for automated card-on-file payments. Once configured, invoices generated by Revenium are charged automatically to the customer's stored payment method, with payment status flowing back into Revenium so the Invoices view always reflects what has actually been paid. There's no reconciliation between two systems because there's only one system.

This page walks through setting up the integration and explains how payment configuration flows through to products and subscriptions.

### <i class="fa-cc-stripe">:cc-stripe:</i> Stripe Is the Supported Provider

Payment Gateways in Revenium support Stripe as the payment provider. If you're already using Stripe for payment collection elsewhere, this integration slots in against the same account - no separate merchant setup, no duplicate card-on-file storage. If you're not using Stripe yet, you'll need to create a Stripe account before configuring the integration; the keys you need come from your Stripe dashboard.

### <i class="fa-credit-card">:credit-card:</i> Setting Up the Payment Gateway

Head to **Configuration > Billing** and open the **Payment Gateways** tab. The list is empty until you add one; click the **+** button to create a new payment gateway configuration.

The Add Payment Gateway form needs:

* **Name** (required) - an internal label for this configuration. Shows up in the Configuration Name column once saved, and in the Payment Options dropdown on products. Something descriptive like "Stripe - Production" or "Stripe - EU Entity" works well, especially if you might end up with multiple Stripe accounts for different business units or regions.
* **Payment Provider** (required) - Stripe is the only option in the dropdown.
* **Tax Behavior** (required) - how tax is handled on invoices charged through this gateway:
  * **None** - no tax is applied. Use this if you're not using Stripe Tax.
  * **Inclusive** - the invoice total already includes tax; tax amount is calculated backwards from the total.
  * **Exclusive** - tax is added on top of the invoice total at charge time.
* **Secret Api Key** (required) - from your Stripe dashboard. This is the sensitive key; Revenium uses it server-side to create charges.
* **Api Publishable Key** (required) - also from the Stripe API keys page. Used for any client-side checkout flows.

Once saved, the gateway appears in the Payment Gateway list with Provider, Configuration Name, and Owner columns. Your own name appears as Owner - useful in teams where multiple people configure payment setups and you need to know who to ask about a particular configuration.

### <i class="fa-tags">:tags:</i> Connecting the Gateway to a Product

Configuring the gateway doesn't by itself activate automated payments - it makes the option available. To actually charge customers automatically, the product they're subscribed to needs to be pointed at it.

On each product that should use automated card payments, set the **Payment Options** field (in the product's invoicing configuration) to **Stripe-Enabled Payments**, and select the gateway you just created. From that point on, invoices generated against subscriptions on this product are charged automatically against the customer's saved card.

This is a per-product choice rather than an account-wide switch. That matters because it means you can have some products on automated Stripe charging, others on invoice-only billing (where Revenium generates the invoice and you collect payment yourself), and others on external payment updates (where your own accounting system tells Revenium when invoices are paid). Different customers on different products can be billed in different ways without separate infrastructure.

### <i class="fa-play">:play:</i> What Happens After Setup

Once Stripe is configured and products are pointed at it, the lifecycle runs itself:

* At the end of each invoicing period, Revenium generates an invoice against the customer's subscription
* The invoice is automatically charged to the customer's saved Stripe payment method
* Stripe attempts the charge, with automatic retries for common failures handled according to your Stripe configuration
* Payment status flows back into Revenium and surfaces in the **Billing > Invoices** view
* On failure, the **Payment Failed** notification template triggers an email to the customer
* On success, the **Successful Payment** template fires if enabled

The **Show Failed Payments Only** toggle on the Invoices tab becomes the most useful view to monitor once this is running - it filters out the noise of successfully paid invoices and shows only the ones that need attention.

### <i class="fa-record-vinyl">:record-vinyl:</i> Recording Payments Collected Outside Revenium

Not every customer is on automated Stripe billing. Enterprise contracts are often paid by wire transfer, bank ACH, or procurement systems outside Stripe's world. For these, the **Invoices with External Payment Updates** payment option on a product tells Revenium to generate the invoice but wait for external confirmation that it's been paid. When the payment lands in your system, you mark it as received in Revenium - either manually through the UI or programmatically via the API (see below).

This mixed-mode approach - automated Stripe for SMB customers, externally-tracked payments for enterprise - is common in practice and is what the three Payment Options on products are designed to support.

### <i class="fa-code">:code:</i> Via API

Stripe gateway configuration is a one-time UI operation and doesn't have a dedicated API - the Stripe credentials are sensitive enough that pushing them through an automated flow isn't the usual pattern. Everything downstream of that setup, however, is available programmatically.

**Attaching a payment gateway to a product.** When you create or update a product via the [Products API](https://revenium.readme.io/reference/get_product), the payload includes a `paymentConfigurationId` field. Set this to the ID of the Payment Gateway you configured in the UI, and any subscription created against that product will automatically bill through the connected Stripe account. This is how teams managing many products programmatically wire them all to the same (or different) payment configurations without repeating UI setup for each one.

**Subscriptions inherit their payment configuration from their product.** The [Subscriptions API](https://revenium.readme.io/reference/get_subscription) doesn't take a payment configuration at subscription-create time because it doesn't need to - the subscription uses whatever configuration is attached to the product it references. When you migrate a customer to a different product with a different payment configuration, payment routing changes automatically as part of that migration.

**Recording externally-collected payments.** For products on the invoice-only or external-payment-update flow, the [Payment Received](https://revenium.readme.io/reference/invoice_payment_correction) endpoints let you record when a payment arrives, link it to a specific invoice, and keep Revenium's record of outstanding balances accurate. This is the right endpoint to call from your accounting or treasury system when a bank transfer clears.

**Setting a default payment method at the tenant level.** The [tenant default payment method](https://revenium.readme.io/reference/setdefaultpaymentmethod) endpoint sets which payment method is used as the fallback when a product or subscription doesn't specify one directly. Useful for setting a house default across multiple products without updating each one individually.


# Overview

This section is for teams bringing their own AI agents or agentic applications onto Revenium so they can measure cost, performance, tool usage, and outcomes.

If you want Claude, Cursor, Codex, Gemini CLI, or another personal assistant to help you use Revenium or complete setup, start with [Connect Your Agent](/get-started/quickstart/connect-your-agent). If you need exact implementation details for SDKs, provider connections, OTLP, MCP, Revvy CLI, LiteLLM, or API keys, use [Integrations](/integrations/integrations).

## In This Section

* [Agent Instrumentation Guide](/instrument-your-agents/agent-instrumentation-guide)
* [Analyze Decision Costs](/instrument-your-agents/analyze-decision-costs)
* [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage)
* [AI Outcomes](/instrument-your-agents/agent-outcomes)


# Agent Instrumentation Guide

Agent workflows break the assumptions that most observability tools are built on. A standard LLM integration is simple: one prompt, one response, one cost. An agent is something else entirely - a chain of reasoning steps, tool calls, handoffs between sub-agents, and occasionally human escalations, all working together to deliver a single business outcome that may or may not have anything to do with whether the underlying model calls succeeded.

Tracking this properly is hard for reasons that compound. Token costs are the smallest part of what an agent actually costs to run - in production workflows, external tool calls are commonly ten times the token spend. Agents loop in ways that aren't visible until someone checks the aggregate numbers at the end of the month. Decision paths that look identical at the transaction level have wildly different cost profiles once you account for which tools they triggered. And the thing that actually matters - did the agent close the sale, deflect the support ticket, complete the task - doesn't show up anywhere in technical logs at all.

Revenium treats agents as first-class workloads rather than slightly more elaborate LLM calls. This page explains the conceptual model, what it lets you see that infrastructure monitoring doesn't, and where to go in the product and API for each piece.

### <i class="fa-arrows-retweet">:arrows-retweet:</i> What Makes Agent Workloads Hard to Observe

Four problems show up in every serious agent deployment, and each one needs a different kind of instrumentation to see properly.

**Tool costs dwarf token costs.** A customer service agent that pulls a credit report from Experian at $25 per lookup spends more on one external API call than it does on thousands of tokens. Agents that call multiple services on each run - CRM lookups, document processing, data enrichment, maps, databases - generate cost profiles where the LLM spend is a rounding error. Without structured tool tracking, all of this is invisible to any monitoring that only watches what flows through the model provider.

**Agents loop without anyone noticing.** A reasoning step that fails once is fine. A reasoning step that fails and triggers a retry, which triggers another external API call, which feeds back into another reasoning step that also fails, can easily run dozens of times before the workflow either succeeds or gives up. The token cost per iteration is small. The tool cost per iteration is not. Without trace-level visibility, a looping agent looks identical to a well-behaved one in aggregate dashboards.

**Multi-agent handoffs are opaque.** When agent A calls agent B which calls agent C, reconstructing that call tree from raw logs means reading timestamps and guessing at relationships. The interesting questions - which handoff is slowest, which agent spawns the most sub-calls, where does cost concentrate across the workflow - are impossible to answer without explicit parent/child relationships between calls.

**Technical success and business outcomes are different things.** An agent can execute flawlessly on every single step and still fail to close the sale, deflect the ticket, or complete the task it was built for. A 100% technical success rate on a lead qualification workflow tells you nothing about whether leads are actually getting qualified. Observing agents properly means measuring outcomes, not just executions.

### <i class="fa-object-group">:object-group:</i> The Four Dimensions Revenium Uses

The instrumentation model maps to the four levels at which agent work actually happens:

**The transaction.** One AI call with full metadata - which agent made it, which model it used, what it cost, how long it took, and (crucially) what its parent transaction was. The `agent` and `parentTransactionId` fields are what let Revenium reconstruct who-called-whom across multi-agent workflows without guessing.

**The trace.** A sequence of related transactions that together make up one workflow run, grouped by `traceId`. This is the unit at which loops become visible, bottlenecks show up, and cost distribution across steps can be analyzed. A single trace might span one agent making ten calls, or ten agents each making one call - the grouping is what matters.

**The job.** The business-level unit of work that a single trace, or many traces, contributes toward. `agenticJobId` ties technical execution to a real-world outcome - a support ticket resolution, a lead qualification, a document review. Jobs are what you measure ROI on, because jobs are what your business actually cares about.

**The squad.** A named, coordinated group of agents executing together as a unit. Different from ad-hoc multi-agent workflows - a squad is an explicit concept that Revenium tracks as its own entity, with aggregated metrics across executions and full timeline views of agent coordination within each run.

These four dimensions don't form a single strict hierarchy. Transactions and traces are a clean technical stack - each trace contains multiple transactions. Jobs and squads sit on separate axes: a job is a *business* grouping that collects whichever transactions contributed to one outcome (possibly spanning one trace, possibly many), and a squad is an *orchestration* grouping that aggregates executions of a named multi-agent unit. The same transaction can carry a traceId, an agenticJobId, and belong to a squad execution simultaneously - they're independent dimensions that each answer a different question. You instrument at whichever levels match the questions you need to answer: trace for "what happened inside this workflow run", job for "did this decision produce a business outcome", squad for "how are my coordinated multi-agent units performing".

### <i class="fa-unlock">:unlock:</i> What This Unlocks That Token-Only Observability Doesn't

Once this structure is in place, five things become legible that would otherwise require ad-hoc log reconstruction every time:

**Tool costs alongside token costs.** Revenium's Tool Registry captures every external tool, API, or service an agent calls - with its own pricing model, its own attribution chain, and full visibility into the cost iceberg beneath the tokens. In the typical production workflow this is the majority of the spend, not the minority.

**Agent-to-agent call patterns.** Because `parentTransactionId` links every call to the one that triggered it, Revenium can render an agent interaction matrix - which agents call which, how often, how much it costs, and how long it takes. The critical path through a multi-agent workflow becomes a chart rather than a detective exercise.

**Circular patterns.** Traces that loop show up as an explicit anomaly class rather than a slightly-higher-than-average cost. An agent calling itself, or two agents calling each other in an unproductive handshake, is a distinctive pattern that can be detected structurally and surfaced before it compounds.

**Business ROI per job type.** With outcomes reported against `agenticJobId`, Revenium can tell you not just what an agent cost, but whether it delivered - and how that compares across job types. A support-ticket agent can have a 60% deflection rate at $0.15 per ticket versus $50 for a human agent, and that ratio appears in the product as a clean ROI figure rather than something a finance team has to build in a spreadsheet.

**Human-in-the-loop cost accounting.** Escalations to human reviewers cost real money in time. Registering human effort as a custom tool in the Tool Registry and metering each escalation properly means the full cost of a workflow - including the minutes a human spent on it - flows into the same ROI calculation as the token and tool costs. Escalated outcomes keep their full business value, and the human time shows up as a cost, which is the only way the economics come out right.

### <i class="fa-robot">:robot:</i> Where Agent Workloads Surface in the Product

Three areas of the UI are scoped specifically for agent work:

**Performance > Agents** is the aggregate view - total throughput, agent completion rate, reliability per agent, duration breakdowns, and cross-model comparison. The place to look when the question is "which of my agents is performing well and which isn't?"

**Performance > Traces > Agent Interaction** shows how agents communicate within traces. This is where the agent interaction matrix, critical path analysis, and circular pattern detection live. The place to look when the question is "what's actually happening inside this workflow?"

**Data > Squads** aggregates multi-agent workflow executions by named squad, with status distribution, trace counts, and execution timelines. The place to look when you're running explicit multi-agent coordination and want to see how the whole squad performed rather than the agents individually.

### <i class="fa-fill">:fill:</i> Deeper Coverage in the Section

Four related pages go deeper on specific aspects of agent instrumentation.

[AI Outcomes](/instrument-your-agents/agent-outcomes) covers outcome reporting — CONVERTED, ESCALATED, DEFLECTED, and CUSTOM — posted after each job run so Revenium can calculate ROI, deflection rates, and cost per conversion. This is where the business-value side of the ledger lives. Start here if your question is "are these agents paying for themselves?"

[Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage) covers the Tool Registry in depth - registering tools, configuring pricing models for them, metering tool events, and analyzing the cost iceberg where tool spend dominates token spend. This is the page to work through once the transaction-level instrumentation is in place and you're ready to capture the rest of the cost picture.

[Analyze Decision Costs](/instrument-your-agents/analyze-decision-costs) covers the Jobs system and outcomes tracking. Jobs are Revenium's higher-level abstraction for "one decision" - the business-level unit of work that groups transactions and traces together and gets measured against a business outcome. This is where ROI, conversion funnels, value ratios per job type, and the correct handling of escalation costs all live. Essential reading if you're using LangChain, CrewAI, or any orchestration framework where "did the workflow deliver" matters more than "did each call succeed".

[MCP Server Setup](/integrations/mcp-server) addresses the reverse direction: hooking your own AI agents - Claude, Cursor, custom assistants - to Revenium itself via Model Context Protocol, so they can query cost data, investigate spikes, configure alerts, and reason about AI economics natively inside their own context. Different problem entirely from instrumenting your agents' output; this is about instrumenting the agents that work with your Revenium data.

### <i class="fa-code">:code:</i> Via API

Agent instrumentation uses five sections of the Revenium API working together. The [AI Metering endpoints](https://revenium.readme.io/reference/meter_ai_completion) accept the standard completion payload with the `agent`, `transactionId`, `parentTransactionId`, and `traceId` fields that make the dimensional model work. The [Tool Metering endpoint](https://revenium.readme.io/reference/meter_tool_event) captures external tool costs against registered tools with full attribution. The [Jobs API](https://revenium.readme.io/reference/report_job_outcome) handles business-outcome reporting against `agenticJobId`. The [Squads endpoints](https://revenium.readme.io/reference/list_squad_executions) surface aggregated metrics for multi-agent coordinated executions. And the [AI Traces endpoints](https://revenium.readme.io/reference/list_ai_traces) expose trace-level analytics including agent interaction tables, interaction matrices, critical path analysis, and circular pattern detection - the underlying data behind the agent-specific UI surfaces.

For per-agent cost and performance analytics, the [Analytics API](https://revenium.readme.io/reference/get_performance_metrics_by_agent) exposes cost-by-agent, performance-by-agent, task-performance-by-agent, and task-completion endpoints that power the dashboards but are also usable directly for custom reporting or external integrations.


# Setup — Claude Code desktop app (OTel telemetry to Revenium)

Configure OpenTelemetry in the Claude Code desktop app so its AI usage is metered in Revenium — the desktop app does not configure this automatically the way the CLI does.

Set the values below once and your Claude Code desktop app usage is metered in Revenium alongside your CLI usage.

## Configure the desktop app

These settings are not under the app's settings screen, which is where most people look first. They belong to the environment the session runs in:

1. In the Claude desktop app, open the **Code** tab and start a **New session**.
2. Click the environment selector — it shows **Local** — and open its settings using the gear icon beside **Local**.
3. Add the Revenium OTLP settings below there.
4. Fully quit and relaunch the app.

Anthropic's own [desktop app quickstart](https://code.claude.com/docs/en/desktop-quickstart) covers the Code tab and choosing an environment if you are new to the app.

## Settings to add

Use a **Revenium metering key (`rev_mk_*`)**, not an Anthropic/OpenAI provider key — the Revenium key authenticates telemetry ingest.

```ini
CLAUDE_CODE_ENABLE_TELEMETRY=1
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.revenium.ai/meter/v2/otlp
OTEL_EXPORTER_OTLP_HEADERS=x-api-key=rev_mk_your_tenant_yourkey
OTEL_EXPORTER_OTLP_PROTOCOL=http/json
OTEL_LOGS_EXPORTER=otlp
OTEL_METRICS_EXPORTER=none
OTEL_LOGS_EXPORT_INTERVAL=5000
```

Field meanings are identical to the CLI managed-settings page (endpoint = Revenium OTLP; header = your metering key; protocol `http/json`; logs exporter `otlp` is how Revenium receives per-call telemetry; metrics `none` because Revenium bills from log events only; logs export interval 5000 ms, a 5-second flush).

*Optional:* `OTEL_RESOURCE_ATTRIBUTES` for your own internal sub-segmentation. Desktop sessions are already distinguishable in Revenium by `service.name=claude-code-desktop` (set automatically), so no source tag is required for correct attribution.

## Verify your configuration

Run a short Claude Code desktop session; usage should appear in Revenium after the next telemetry flush. If nothing appears, check: the metering key is active, the OTLP endpoint matches your Revenium environment, and the app was fully quit and relaunched after the change.

## Why this is needed

Optional background — you do not need this to complete the steps above.

Claude Code CLI installs pick up your organization's Revenium telemetry configuration from your team's managed settings, so the CLI is metered as soon as you sign in. The desktop app reads its configuration from the environment a session runs in rather than from those managed settings, so the same values are entered there once, by hand. After that, desktop sessions are ingested and attributed in Revenium the same way CLI sessions are.


# Analyze Decision Costs

For agent workflows, the unit of cost that matters isn't the token or the call - it's the *decision*. A support agent that handles 1,000 tickets incurs 1,000 decision costs, each of which involved some combination of LLM calls, tool invocations, and occasionally human escalations. The token cost of a single LLM call tells you almost nothing about whether the agent is profitable. The cost of the whole decision - from triggering event to business outcome - is the number that answers whether the workflow is worth running.

Revenium models this as a **Job**: a higher-level abstraction that sits above transactions and traces, identified by an `agenticJobId` you supply when metering. A single job groups everything that contributed to delivering one business outcome - potentially many LLM calls, many tool invocations, and any human time that got pulled in along the way. Once outcomes are reported against those jobs, you can see the economics at the level that actually matters: did this category of decision make money, lose money, or break even.

This works the same regardless of how the agent is built. LangChain chains, CrewAI crews, custom orchestration - Revenium doesn't care which framework assembled the workflow, because you're the one assigning the `agenticJobId` when you meter. The framework decides how the agent runs; you decide what counts as "one decision" for economic purposes.

The analysis surface lives under **Intelligence > Costs & Revenue > ROI Dashboard**.

> **Term Reference**
>
> * **Execution Status** reflects technical workflow completion (`SUCCESS`, `FAILED`, `CANCELLED`).
> * **Outcome Type** captures the business result (`CONVERTED`, `DEFLECTED`, `ESCALATED`, `UNSUCCESSFUL`, `CUSTOM`).
> * **Outcome Value** is the monetary value the workflow generated or saved.

### <i class="fa-ruler">:ruler:</i> What the Dashboard Measures

The ROI dashboard is built around one equation that the Value Composition card makes explicit:

**Business Value = Revenue from Conversions + Costs Avoided from Deflections**

Two things produce value. A **conversion** is when a job delivered a positive outcome that generated revenue - a closed sale, a completed sign-up, a successful resolution where the customer was charged. A **deflection** is when a job completed a unit of work that would otherwise have required a more expensive path - a support ticket handled without escalation to a human agent, an automated review that replaced manual work. Conversions and deflections are the two economic outcomes that justify an agent existing.

Against that value, three kinds of cost are tracked, visible on the Cost Composition card:

* **Token Costs** - the AI provider spend for LLM calls
* **External Tools** - spend on registered tools that agents called during the job (see [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage))
* **Human Escalation** - time spent by human reviewers, metered as a custom tool (Engineering Time in the example workspace)

These three categories combine into **Total Costs**. The Value Composition card shows four headline metrics together: **Total Costs**, **Business Value**, **Net Value** (Business Value minus Total Costs — positive means profitable, negative means over-spending), and the **Value Ratio** (Business Value ÷ Total Costs — how many dollars of value each dollar of cost produced). The Value Ratio is the figure the dashboard leads with, because it answers the question every AI product leader actually asks: *are these agents paying for themselves?*

### <i class="fa-filters">:filters:</i> The Two Conversion Funnels

The Overview has two funnels side by side, and the distinction between them is the key insight the page is built around.

**Conversion Funnel** (the revenue side): Total Jobs → Successful → Converted. The first drop-off is technical - some jobs failed execution. The second drop-off is the interesting one - jobs that ran without technical errors but didn't deliver the business outcome they were trying to produce. The ratio of Successful → Converted is the **Conversion Rate**.

**Cost Avoidance Funnel** (the deflection side): Total Jobs → Successful → Deflected. Same shape, different outcome. Successful jobs either converted, deflected, or did neither. The Deflection Rate measures how often technical success produced cost savings rather than revenue.

A job that's technically successful but doesn't convert *and* doesn't deflect is one that ran cleanly and produced no economic value. These are usually the most interesting jobs to investigate, because they represent spend without return - the agent did its work competently and no business outcome came out the other end. The gap between "successful" and "converted or deflected" is where the optimization opportunity lives.

### <i class="fa-up">:up:</i> How Outcomes Get Reported

Each job ends with an outcome being reported against it. The API supports five outcome types:

* **CONVERTED** - the job delivered a positive business outcome that generated revenue (a closed sale, a completed signup, a charged resolution)
* **DEFLECTED** - the job successfully completed work that would otherwise have required a more expensive path (a ticket handled without human escalation, an automated review that replaced manual effort)
* **ESCALATED** - the job required human escalation to complete. The business value still gets reported at full value; the human cost gets metered separately
* **UNSUCCESSFUL** - the job ran technically without error but did not achieve the business goal, and was not escalated
* **CUSTOM** - any outcome type your organization defines that doesn't fit the four standard categories. Useful for domain-specific outcomes that don't map cleanly to convert/deflect/escalate - tiered qualification scores, partial completions, multi-stage deal progressions

Jobs that haven't yet had an outcome reported display in the UI as **Pending** - this is a UI-side status indicator, not an outcome type you can post through the API.

Outcomes carry both a value and a currency - USD by default, with support for EUR, CAD, GBP, JPY, and other major currencies. Useful when you operate internationally and want ROI calculations to respect the currency of each market rather than blending everything into a single base currency.

**Outcomes are immutable.** Once a job's outcome is reported, it can't be changed - attempting to report again returns a 409 Conflict. This is deliberate: the business outcome of a job is historical fact, and allowing edits would undermine the integrity of every ROI calculation built on top. If a reported outcome turns out to be wrong, it's wrong in the record, and future jobs get the corrected reporting.

Execution Status and Outcome Type are independent dimensions. Execution Status captures whether the technical work completed without error (SUCCESS, FAILED, or CANCELLED); Outcome Type captures what the job produced in business terms. A job can be SUCCESS with an outcome of CONVERTED, or SUCCESS with an outcome of UNSUCCESSFUL (ran cleanly, business goal missed), or any other combination. The reason these are separate is that technical execution and business outcome are different questions - and conflating them is how teams end up thinking an agent is "working" when it isn't actually delivering.

### <i class="fa-list">:list:</i> The All Jobs View

The **All Jobs** tab under ROI gives you the drill-down - every job execution in the selected time window, filterable by Job Type, Status, Outcome, and Value Range, searchable by Job ID or name. Each row shows Job ID, Name, Type, Status, Outcome Type, Job Value, and when it was created.

Clicking through to an individual job shows the complete execution history - every transaction that contributed to the job, every tool call, the full cost composition, and the job's final business value. This is the path you take when the aggregate numbers raise a question: why did this specific job cost what it did, and what did it actually produce?

### <i class="fa-list-timeline">:list-timeline:</i> Per-Job-Type Analysis

The Overview includes a **Job Types by Value Ratio** table that ranks every job type in your system by how profitable it is. Value Ratio, Net Value, Total Cost, Cost per Outcome, Conversion count, Deflection count, Job count, and Success Rate all sit next to each other - so you can tell at a glance which job types deliver most economically, which deliver consistently but cost too much, and which run successfully but fail to produce outcomes.

Job types with an N/A value ratio are usually ones where outcomes haven't been reported yet - the technical execution is happening but the business layer isn't closing the loop. Seeing these is itself useful: it tells you which job categories need outcome reporting wired up before their economics can be measured.

The **Value vs Cost Analysis** chart underneath shows the same per-job-type breakdown visually - one bar per job type split between Business Value, Token Cost, External Tools, and Human Escalation, with Value Ratio overlaid as a star. The chart makes a specific pattern obvious: job types where cost is dominated by Human Escalation rather than tokens are usually candidates for investigation, because human time scales linearly with volume in a way that token and tool costs don't.

### <i class="fa-square-check">:square-check:</i> Handling Escalated Outcomes Correctly

A common mistake when reporting outcomes is to discount the value of escalated jobs to account for human involvement. A support ticket worth $143 that got escalated to a human agent might be reported with half the value, on the theory that the human did half the work.

This produces misleading ROI. The right approach keeps value and cost as independent dimensions:

* **Keep the `outcomeValue` at full value** - the business result was still delivered, even if a human helped
* **Meter the human effort as a tool cost** - register an "Engineering Time" tool in the Tool Registry and meter the duration of the human session (see [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage) for the pattern)
* **Let the ROI formula do the work** - Total Cost increases with tool costs, value stays accurate, and ROI comes out right

Discounting value hides where the cost went. Metering human time as a tool cost surfaces it where it belongs - in the cost side of the equation. The Value Ratio and ROI numbers reflect the real economics of the workflow, including the parts of it that humans performed.

### <i class="fa-timeline-arrow">:timeline-arrow:</i> Business Value Over Time

The **Business Value Over Time** chart plots value generated by each job type across the date range. Spikes tell you which job types drove revenue or cost savings on specific days. Flat lines across multiple job types alongside a spike in one means that job type accounted for the day's value. Patterns in this chart often align with external events - deploys, campaign launches, support volume changes - and knowing which job type drove the change is usually more useful than knowing that total value went up.

> **Through MCP, conversationally.** Tracking agent job ROI is one of the capabilities the MCP Server explicitly supports. Once an AI assistant is connected to Revenium, you can ask the kind of questions this dashboard exists to answer without opening it. "What's the ROI on our agents this week?", "which agent is generating the most business value right now?", or "are AI costs trending up faster than the value they're producing?" The agent runs the queries, breaks the data down across providers, models, customers, agents, or API keys, and tells you what's changed. Useful when the question is recurring, like a weekly ROI check, rather than a one-off investigation.

### <i class="fa-gear-code">:gear-code:</i> Telemetry Fields for Job Tracking

Include the agentic job fields on every completion payload that should roll up into a job. Any transactions sharing the same `agenticJobId` automatically group under that job — costs, tokens, and transaction counts aggregate in real time.

{% hint style="info" %}
The snippet below shows the **additive** `agenticJob*` fields only. Add them to your existing completion payload (alongside the required `model`, token counts, timing fields, `requestDuration`, etc. from the [direct API example in the quickstart](/get-started/quickstart/5-minute-quickstart#instrument-your-own-code-or-api-traffic)) — don't POST this fragment on its own or the request will fail validation.
{% endhint %}

```json
{
  "agenticJobId": "support-ticket-12345",
  "agenticJobType": "support-ticket",
  "agenticJobName": "Handle Support Ticket #12345",
  "agenticJobVersion": "1.0.0",
  "model": "gpt-4o-mini",
  "provider": "openai",
  "totalCost": 0.05
}
```

| Field               | Required    | Constraint                         | Purpose                                                                                                     |
| ------------------- | ----------- | ---------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `agenticJobId`      | Yes         | string, max 256 chars              | Unique identifier for this job execution. The grouping key for everything that contributes to one decision. |
| `agenticJobType`    | Recommended | string, max 128 chars (lowercased) | Job category — drives the Job Types by Value Ratio table.                                                   |
| `agenticJobName`    | Recommended | string, max 512 chars              | Human-readable name shown in the dashboard.                                                                 |
| `agenticJobVersion` | Recommended | string, max 64 chars               | Tracks job evolution; useful for A/B comparing prompt or workflow changes.                                  |

Revenium creates the job entity the first time it sees a new `agenticJobId`, so no separate "create job" call is required.

***

### <i class="fa-rectangle-api">:rectangle-api:</i> Reporting Outcomes via API

After a job completes, post the outcome to the Jobs endpoint:

```bash
curl -X POST "https://api.revenium.ai/profitstream/v2/api/jobs/{jobId}/outcome?teamId={yourTeamId}" \
  -H "x-api-key: $REVENIUM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "executionStatus": "SUCCESS",
    "outcomeType": "CONVERTED",
    "outcomeValue": 500.00,
    "metadata": "{\"customerId\": \"123\", \"notes\": \"Upgraded to premium\"}"
  }'
```

| Field             | Required | Allowed Values                                                  |
| ----------------- | -------- | --------------------------------------------------------------- |
| `executionStatus` | Yes      | `SUCCESS`, `FAILED`, `CANCELLED`                                |
| `outcomeType`     | Optional | `CONVERTED`, `ESCALATED`, `DEFLECTED`, `UNSUCCESSFUL`, `CUSTOM` |
| `outcomeValue`    | Optional | Monetary value (number)                                         |
| `outcomeReason`   | Optional | Plain text (≤ 2048 chars) — why the job failed or was cancelled |
| `metadata`        | Optional | JSON string with additional context                             |

**Send `outcomeReason` whenever you report `FAILED` or `CANCELLED`.** It is the field the Jobs UI reads: the All Jobs table flags the status with an alert icon that reveals the reason on hover (and an opt-in **Reason** column), and the job page shows it in full. A reason encoded inside `metadata` cannot be displayed, filtered or compared — Revenium does not guess at keys in free-form JSON.

**Response codes:** `200 OK` — outcome recorded; `409 Conflict` — outcome already reported (do not retry; `PATCH` the outcome instead); `404 Not Found` — job ID unknown.

Outcomes can also be reported from the UI: open a job from the All Jobs tab, click **Report Outcome**, fill in the form. If an outcome was already reported, the button becomes **Correct Outcome** — it takes a mandatory reason for the change and records every revision, which the job page then shows as an **Outcome History** trail.

***

### <i class="fa-list-check">:list-check:</i> Use Cases

#### Support Ticket Deflection

Track cost savings when AI handles tickets that would otherwise hit a human agent.

Typical economics: deflection rate 60–80%; AI cost per deflected ticket $0.05–0.15 vs $50 for a human; ROI in the tens of thousands of percent for deflected tickets.

#### Sales Lead Qualification

Measure conversion value and validate that AI qualification is paying for itself.

Typical economics: conversion rate 10–30%; AI cost per lead $0.10–1.50; ROI driven entirely by revenue per converted lead vs total cost across all qualified leads.

***

### <i class="fa-clipboard-list-check">:clipboard-list-check:</i> Best Practices for Job IDs and Naming

**Use meaningful, entity-derived `agenticJobId` values.** The ID should map to a real-world thing your business cares about, not a synthetic UUID:

Good job IDs usually include the business entity and workflow, such as a support ticket, order, pull request, or onboarding run. Avoid generic labels, random UUIDs with no business context, broad batch names that collapse many decisions into one job, and transaction-level IDs that make every metered call look like its own job.

**Use lowercase, hyphen-separated `agenticJobType` names.** Be specific (`loan-application-review`, not `review`), action-oriented (`lead-qualification`, not `leads`), and consistent across the codebase. Examples: `customer-support-chat`, `code-review-security`, `content-blog-generation`, `fraud-detection-realtime`.

**Always report outcomes — even for failed and escalated jobs.** Skipping outcome reporting on failures hides your true success rate, autonomy rate, and cost-per-successful-outcome. For failed jobs, post `executionStatus: FAILED` and omit `outcomeType` and `outcomeValue`. For escalated jobs, post `executionStatus: SUCCESS`, `outcomeType: ESCALATED`, and the **full** business value — the human cost gets metered separately as a tool cost (see [Handling Escalated Outcomes Correctly](#handling-escalated-outcomes-correctly) above).

**Be consistent in how you value outcomes.** Unit-economics analysis only works if the value side is methodologically clean.

| Job Type           | Value Strategy                                                                                                              |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------- |
| Support tickets    | Average human agent cost per ticket for deflected; full business value for escalated (with human time metered as tool cost) |
| Sales leads        | Actual contract value for conversions, or average deal size as proxy                                                        |
| Code reviews       | Developer time saved at $100–200/hour                                                                                       |
| Content generation | Attributed revenue from campaigns, or freelancer cost savings                                                               |

Use conservative estimates, document your methodology, keep it consistent across similar job types, and revisit the numbers periodically as actual data lands.

***

### <i class="fa-code">:code:</i> Via API

For current endpoint details, request and response schemas, and authentication requirements, use the [API reference](https://revenium.readme.io).

***

### See also

* [SDK code examples](https://github.com/revenium/revenium-python-sdk)
* [API reference](https://revenium.readme.io)


# Monitor Agent Tool Usage

Once agents are instrumented, the biggest cost problem left is usually the one that doesn't show up in the LLM provider bill. Production agents call external APIs, query databases, scrape web pages, process documents, route through MCP servers, and - often - hand off to human reviewers. Each of those calls costs something. Token costs are frequently the smallest line item in the ledger, and the ones that actually move the bill never pass through the model provider to be observed.

The Tool Registry is Revenium's answer to this. Anything that costs money when an agent triggers it can be registered as a tool, priced, and metered - giving you complete visibility into the cost iceberg sitting beneath your token spend. In production workflows that call external services, tool costs commonly run ten times the token costs. Without tracking them, you're optimizing a rounding error.

Head to **Configuration > Cost Sources** and open the **Tools** tab to see every tool registered for your account.

### <i class="fa-hammer">:hammer:</i> What the Tool Registry Tracks

Each registered tool carries five pieces of information that together make the cost visible and attributable:

* **Name** - the human-readable label for the tool. "Equifax Credit Reporting", "User Directory API", "Engineering Time (Human Intervention)".
* **Tool ID** - a unique identifier used in metering events. What your application passes when recording a tool call.
* **Type** - the tool category. See below for the categories available.
* **Provider** - the vendor or internal source. "equifax", "Entrust", "qualtrics", or "Internal" for tools your own team runs.
* **Status** - Active or Inactive. Lets you take a tool out of metering without deleting the registration, useful when you're rotating providers or phasing out an integration.

A search-by-name-or-ID field at the top, sortable columns, and per-row actions for view, edit, and delete round out what you can do with the list itself.

### <i class="fa-list">:list:</i> The Tool Categories

Tools fall into six categories, each matching a different kind of agent-triggered cost:

* **REST API** - external HTTP APIs your agents call. Credit report lookups, identity verification services, CRM endpoints, user directory lookups. Typically the largest per-call costs and the easiest wins for tracking.
* **MCP Server** - Model Context Protocol servers that extend agent capabilities. Legal research tools, web search, database query servers - increasingly the dominant integration pattern for agentic tooling.
* **AI Service** - AI-powered services beyond standard LLM completions. Sentiment analysis, image recognition, specialized classification, transcription.
* **SDK** - costs associated with SDK-based integrations your agent consumes, where the work happens inside a vendor library rather than a remote API.
* **Local Function** - code your team runs in-process that has associated costs. Useful for compute-heavy local operations you want to track alongside external spend.
* **Custom** - anything that doesn't fit the five other categories. Internal services, human review time, compliance workflows, manual verification steps. The category that makes the Tool Registry genuinely flexible, because "tool" in Revenium's sense is shorthand for *anything your agent does that costs money.*

A single agent typically calls tools across several of these categories in one workflow. Registering them uniformly means attribution and analytics work the same way regardless of the underlying tool type.

### <i class="fa-dollar-sign">:dollar-sign:</i> How Tools Get Priced

Each tool carries its own pricing configuration, independent of the products and subscriptions that wrap around it. Two pricing shapes cover almost every real-world case:

**Flat-rate pricing** is the simple case. Set a unit price, pick an aggregation method, done. Aggregation matters more than it sounds: for a tool like a web scraper you might want to sum every request, but for a compliance-review tool you might want to count occurrences, and for a latency-sensitive tool you might want to capture the maximum value seen in a period. The supported aggregations are sum, count, average, maximum, and distinct - each fitting a different cost-tracking intent.

**Volume-based tiered pricing** handles tools with real-world volume discounts. A web scraping service that charges $0.05 for the first 100 requests, $0.03 for the next 900, and $0.01 beyond that can be expressed tier-by-tier in the registry, and Revenium applies the correct rate automatically based on usage volume within the invoicing period. This is the same tier mechanism used in product pricing, applied to the cost side rather than the revenue side.

#### When Actual Cost Differs From Configured Pricing

Not every tool has predictable pricing. Some external services charge variable amounts based on the specific request - credit report depth, query complexity, response size, peak-hour multipliers. The Tool Event API includes an optional `costUsd` field that overrides the configured pricing and uses the supplied value directly as the charge for that specific call. This is how you handle tools whose cost can only be known at the moment of the call, rather than configured in advance.

Pass-through billing also works this way: when you're reselling a tool's cost to an end customer with a markup, sending the actual underlying cost through `costUsd` gives you a precise record of what to mark up, rather than relying on configured estimates.

### <i class="fa-eyes">:eyes:</i> What You See Once Tools Are Registered

Three views in the product are scoped specifically to tool spend, and each answers a different question.

**The Cost Iceberg by Agent** puts token costs and tool costs side by side, broken down by agent, with a tool-to-token ratio alongside each one. This is the view that makes the iceberg problem concrete: an agent where tool spend is 15× token spend looks immediately different from one where it's 2×, and the difference tells you something about what that agent actually does under the surface. A tool-heavy agent either legitimately needs external services to function, or it's looping through expensive calls it shouldn't be - and the ratio on its own usually hints at which.

**Tool Cost Over Time** breaks the total tool spend into individual tools across a date range, shown as separate series. The immediate use is spotting spikes - a run of expensive database queries at 2pm on a Tuesday, a sudden increase in external API usage after a deploy, a third-party service that's quietly becoming a large line item. More generally, it's how you answer "which tools are driving my cost trend?" without having to reconstruct it from raw events.

**Trace Cost Distribution** is a scatter plot where each dot is one trace, coloured by agent. Percentile lines (p50, p90, p95, p99) sit over the distribution, plus a configurable threshold line. This is where outliers become visible - the traces that spent dramatically more than typical, whether because they looped, picked up a rare expensive code path, or triggered an unusually long chain of tool calls. Colouring by agent makes it easy to see whether outliers are concentrated in one agent or spread across the fleet.

### <i class="fa-timer">:timer:</i> Human Time as a Tool

One of the genuinely useful patterns the Tool Registry enables is metering human-in-the-loop effort as if it were any other external service. A compliance review, a manual verification, an escalation to a support engineer - all cost real money in reviewer time, and all of them need to flow into the same cost accounting as the automated parts of the workflow.

The pattern is straightforward. Register a custom tool - for example, an "Engineering Time (Human Intervention)" tool with provider set to "Internal", priced per minute at the loaded hourly cost of the reviewer - then meter usage with the duration of each human session. The tool cost lands in the same attribution chain as everything else, flows into the same dashboards, and - critically - feeds into the ROI calculations that outcome tracking uses to measure the full economics of a workflow. A job that required human escalation to complete still delivered its full business value; the human time shows up as a cost, and the ROI formula handles the rest correctly.

The alternative - discounting the business value of escalated jobs to account for human involvement - is a common mistake that hides the true cost structure and produces misleading ROI. Keeping value and cost as independent dimensions is what makes the economics come out right.

### <i class="fa-water">:water:</i> Where Tool Costs Surface Elsewhere

Tool cost attribution uses the same dimensions as AI completion metering - organization, agent, product, subscriber, trace - which means tool costs flow into every surface where cost is shown by those dimensions:

* The **Provider Dashboard** shows tool costs aggregated alongside token costs at the top level, so the full spend picture for any provider grouping includes both.
* **Trace Analytics** shows tool calls within individual traces, next to the LLM calls they accompanied. The trace timeline reflects the actual order of operations - agent reasons, agent calls tool, agent reasons about result - rather than separating token and tool work into different views.
* **Cost & Performance Alerts** can fire on tool-based cost metrics the same way they fire on token spend. A sudden spike in external API cost, a tool that's exceeding its typical cost-per-call, a workflow where tool costs have crossed a threshold - all first-class alert conditions.

The effect is that registering a tool once makes its cost visible everywhere Revenium already aggregates cost. No separate dashboards, no duplicate attribution logic.

### <i class="fa-code">:code:</i> Via API

The [Tools endpoints](https://revenium.readme.io/reference/get_tool) handle CRUD for the registry itself - registering tools, updating their pricing, toggling them active or inactive, listing them by type. The [Tool Metering endpoint](https://revenium.readme.io/reference/meter_tool_event) captures usage events with full attribution - agent, organization, subscriber, trace, workflow - and supports the `costUsd` override for tools whose price varies per call.

Because tool costs carry the same attribution dimensions as AI completion metering, the [Analytics API](https://revenium.readme.io/reference/get_cost_metric_by_agents) exposes the same cost-by-agent, cost-by-organization, cost-by-product, and cost-per-customer breakdowns for tool spend - usable directly for reporting, finance integrations, or custom dashboards.


# AI Outcomes

Track the business outcome of every agent run — CONVERTED, ESCALATED, DEFLECTED, or CUSTOM — alongside cost and tool usage.

Most observability tools stop at technical execution. They tell you that an agent completed, how many tokens it used, and what it cost. They don't tell you whether the business goal was achieved.

AI Outcomes closes that gap. Every agent run ends with a reported outcome — CONVERTED, ESCALATED, DEFLECTED, or CUSTOM — posted alongside the execution cost. From that single data point, Revenium calculates ROI, deflection rates, cost per conversion, and the ratio of business value to spend. The ledger becomes legible.

The core insight is that **outcomes are financial events, not just metrics**. An agent that closes a $4,200 deal produces a financial record. An agent that deflects a support call that would have cost $50 to handle manually also produces a financial record. Aggregated across hundreds or thousands of runs, these records answer the question every AI product leader actually needs to answer: are these agents paying for themselves?

***

### <i class="fa-circle-exclamation">:circle-exclamation:</i> Why outcomes matter

A 100% technical success rate means nothing if the business goal fails.

Consider an AI sales agent that qualifies leads. Every LLM call succeeds. Every tool invocation returns data. The workflow completes cleanly. But only 8% of qualified leads convert to deals. Is the agent performing? The technical logs say yes. The economics say it depends entirely on what those conversions are worth against the total cost of running all 100% of the qualifying runs.

This is the calculation that Revenium's AI Outcomes is built around. Without outcome reporting, you have cost data with no value side. With it, the ROI dashboard can tell you not just what the agent spent, but whether it earned.

The same principle applies to support deflection, code review automation, document processing — any workflow where "did it run" is a different question from "did it deliver."

***

### <i class="fa-table">:table:</i> The outcome taxonomy

Four outcome types cover the range of business results that matter across agentic workflows.

| Outcome       | When to use                                                                                                                                                            | What it signals                                                                                                             |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **CONVERTED** | The agent achieved the business goal and generated value — a deal closed, a support ticket resolved without escalation generating a measurable saving, code merged     | Positive economic return: revenue created or cost meaningfully displaced                                                    |
| **ESCALATED** | The agent handed off to a human to complete the job                                                                                                                    | Human involvement required; report full business value and meter human time separately as a tool cost so ROI stays accurate |
| **DEFLECTED** | The agent completed work that would otherwise have required a more expensive path — a support call handled self-serve, an automated review that replaced manual effort | Cost avoidance: the value is what the alternative would have cost                                                           |
| **CUSTOM**    | A business result your organization defines that doesn't map to the above — tiered qualification scores, partial completions, multi-stage deal progressions            | Domain-specific outcomes with tenant-defined naming and value                                                               |

**UNSUCCESSFUL** is a fifth `outcomeType` value, posted the same way as the four above — the job ran without technical error but produced no business outcome and was not escalated. Post `executionStatus: SUCCESS` with `outcomeType: UNSUCCESSFUL`.

**Pending** is a UI-only status — it appears when a job has not yet had an outcome reported. It is not a value you post through the API.

**Outcomes are report-once, then corrected through an audited update.** A second `POST` to the same job returns `409 Conflict` — reporting is not idempotent and must not be retried blindly. To change an outcome that was already reported, `PATCH /jobs/{jobId}/outcome` with a `reason` explaining the correction. The reason is mandatory, and every revision is retained and readable through `GET /jobs/{jobId}/outcome/history`. Business outcomes are historical facts and ROI depends on them, so they are never silently overwritten — but a genuine mistake (an SDK that reported `CANCELLED` on a client-side timeout, say) can be fixed without losing the original record.

Note `reason` and `outcomeReason` are different fields: `reason` explains why you are *changing the record*, `outcomeReason` explains why the *job itself* failed.

**Execution status and outcome type are independent dimensions.** `executionStatus` captures whether the technical work completed (`SUCCESS`, `FAILED`, `CANCELLED`). `outcomeType` captures what the job produced in business terms. A job can be `SUCCESS` / `CONVERTED`, or `SUCCESS` / `UNSUCCESSFUL` (ran cleanly, business goal missed), or `FAILED` / `ESCALATED`. The separation is intentional — conflating them is how teams end up thinking an agent is working when it isn't delivering.

***

### <i class="fa-code">:code:</i> How to emit outcomes

Outcome reporting uses the Python SDK's `AgenticOutcomeClient`. With the SDK, the pattern is four calls in sequence: register the job, meter LLM completions as they happen, meter tool events as they happen, then report the terminal outcome when the job ends.

If you are using direct metering payloads instead of the SDK, you do not need a separate create-job call. Revenium creates the job entity the first time it sees a new `agenticJobId`; see [Analyze Decision Costs](/instrument-your-agents/analyze-decision-costs#reporting-outcomes-via-api) for the direct API flow.

**Install the SDK:**

```bash
pip install revenium-python-sdk
```

**The four-call pattern in outline:**

```python
from revenium_middleware.agentic_outcomes import AgenticOutcomeClient, AgenticOutcomeSettings

settings = AgenticOutcomeSettings(api_key="rev_sk_...")  # write-scope key required

with AgenticOutcomeClient(settings) as client:
    client.create_job(job_id, name=..., type=..., environment=...)   # 1. register the job
    client.emit_completion({...})                                     # 2. meter each LLM call
    client.emit_tool_event({...})                                     # 3. meter each tool call
    client.report_outcome(job_id, {"executionStatus": "SUCCESS",
                                   "outcomeType":     "CONVERTED",
                                   "outcomeValue":    4200.00})       # 4. close with outcome
```

**Key fields on the outcome payload (call 4):**

| Field             | Required | Allowed values                                                             |
| ----------------- | -------- | -------------------------------------------------------------------------- |
| `executionStatus` | Yes      | `SUCCESS`, `FAILED`, `CANCELLED`                                           |
| `outcomeType`     | Optional | `CONVERTED`, `ESCALATED`, `DEFLECTED`, `UNSUCCESSFUL`, `CUSTOM`            |
| `outcomeValue`    | Optional | Monetary value (number). USD by default; EUR, GBP, CAD, JPY supported      |
| `outcomeReason`   | Optional | Plain text (≤ 2048 chars). Why the job failed or was cancelled             |
| `metadata`        | Optional | JSON string. Carry any additional context — customer ID, deal stage, notes |

**Always send `outcomeReason` when you report `FAILED` or `CANCELLED`.** It is the field the Jobs UI reads to show why a job ended badly, so a failure reported without it shows up as a bare red badge with no explanation. Put the reason there rather than inventing a key inside `metadata` — a reason buried in free-form JSON cannot be displayed, filtered, or compared across integrations.

```python
client.report_outcome(job_id, {"executionStatus": "FAILED",
                               "outcomeReason":   "Upstream agent timed out after 300s"})
```

**Full payload reference:** the complete field list for `emit_completion`, `emit_tool_event`, and `report_outcome` lives in the [API reference](https://revenium.readme.io/reference/report_job_outcome) and in the runnable SDK examples (linked below). Treat those as canonical; this page is the conceptual walkthrough.

**Write-scope API key required.** Outcome reporting writes financial records. Use a key with write permissions (`rev_sk_...`), not a read-only or metering-only key. See [API Key Permissions](/integrations/api-key-permissions) for the key tier reference.

Response codes: `200 OK` — recorded; `409 Conflict` — already reported (do not retry; `PATCH` instead); `404 Not Found` — job ID unknown (the SDK retries automatically — see retry timing below).

***

### <i class="fa-clock-rotate-left">:clock-rotate-left:</i> Job Outcomes and Retry Timing

If you post a job outcome immediately after sending metering data, the outcome request can briefly return `404`. Metering ingestion creates the job record asynchronously, so the outcome lookup may run before the job exists.

The SDK handles this with exponential backoff:

* Maximum attempts: `10`
* Initial delay: `2.0s`
* Maximum delay: `90s` (sized to absorb backend `ErrorPatternRateLimitFilter` penalties up to 60s and honor server-sent `Retry-After`)
* Configuration: `AgenticOutcomeSettings.outcome_retry_*`

Do not add a second retry loop around the SDK call unless you have a specific reason. Await the SDK call and let it handle the short creation race.

***

### <i class="fa-gauge-high">:gauge-high:</i> What you'll see in the dashboard

Reported outcomes feed the **Intelligence > Costs & Revenue > ROI Dashboard** in real time.

The headline figure is the **Value Ratio** — dollars of business value produced per dollar of agent cost. This is visible at the aggregate level, per job type, and drillable to individual job executions. Two funnels break down where outcomes land:

* **Conversion Funnel** — Total Jobs → Successful → Converted. The gap between Successful and Converted is the population that ran cleanly but didn't deliver a business outcome. These are the jobs where optimization opportunity lives.
* **Cost Avoidance Funnel** — Total Jobs → Successful → Deflected. Measures how often successful technical execution produced cost savings rather than revenue.

**Failed and cancelled jobs explain themselves through `outcomeReason`.** In the **All Jobs** tab the status of such a job carries an alert icon that reveals the reason on hover, and a **Reason** column can be switched on from *Manage Columns* when you are scanning a batch of failures. Opening the job shows the reason in full. A job whose integration reported no reason says so explicitly instead of leaving a bare red badge — that hint is the cue to start sending the field.

**Corrections are visible, not silent.** A job that already has an outcome offers **Correct Outcome** instead of *Report Outcome*: it takes the mandatory change `reason`, and once saved the job page grows an **Outcome History** trail with every revision — status, value, `outcomeReason`, who changed it and why.

For trace-level debug — the individual LLM calls and tool events inside a job — see [Debug Logs & Traces](/optimize-performance/debug-logs-and-traces). The Analyze Decision Costs page covers the full ROI dashboard in depth, including how to handle escalated outcomes, how to value deflections, and how to read the Job Types by Value Ratio table.

***

### <i class="fa-rectangle-code">:rectangle-code:</i> Example scenarios

The Revenium Python SDK ships three reference implementations that demonstrate the full four-call pattern across different workflow types:

**AI Sales Agent** — a sales lead qualification workflow with three LLM steps (prospecting, qualification, close), two enrichment tool calls (ZoomInfo, Apollo), and a human SDR escalation path. Deterministic outcome mix: 12% conversion rate, full deal value reported on CONVERTED outcomes.

**AI Customer Support Agent** — a support ticket workflow across three scenario types (triage, resolution, escalation handling) with KB search and CRM tool calls. Outcome mix: 80% DEFLECTED (self-serve deflection value = avoided human agent cost), 8% ESCALATED, 12% CONVERTED (upsell during support session).

**AI Coding Workflow** — five scenario types (PR review, test generation, incident RCA, release gate, dependency risk analysis) with repo search, CI, and GitHub tool calls. Outcome mix: 72% CONVERTED (autonomous task completion), 10% ESCALATED (human engineering takeover), 18% CUSTOM (task canceled).

These are available in the [Revenium Python SDK examples](https://github.com/revenium/revenium-python-sdk/tree/main/examples/agentic_outcomes) (`sales.py`, `coding.py`, `support.py`). Each file is self-contained and can be adapted directly to a real workflow by swapping in actual LLM calls and tool events in place of the demo data generators.

***

### <i class="fa-link">:link:</i> Related

* [Analyze Decision Costs](/instrument-your-agents/analyze-decision-costs) — the ROI dashboard in depth: conversion funnels, Value Ratio, how to handle escalated outcomes correctly, and per-job-type analysis
* [Agent Instrumentation Guide](/instrument-your-agents/agent-instrumentation-guide) — the full instrumentation model: transactions, traces, jobs, squads, and what each level unlocks
* [Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage) — registering external tools and metering tool events so tool costs appear alongside token costs in the ROI calculation
* [AI Insights](/optimize-performance/ai-insights) — anomaly detection and recommendations that surface after outcome data accumulates
* [Debug Logs & Traces](/optimize-performance/debug-logs-and-traces) — trace-level view of individual LLM calls and tool events within a job


# Integration Options

Use this page to choose the right way to connect data, tools, and workflows to Revenium. The detailed setup lives in the child pages so this page stays scannable.

## Choose an Integration Path

Start with the path that matches what you are connecting:

| Goal                                                                                     | Best starting point                                                                                                                  |
| ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| Add metering to application code                                                         | [SDK Setup](/integrations/sdk-setup)                                                                                                 |
| Meter + backfill AI Assistants such as Claude code, Cowork, Gemini, Copilot, Cursor, etc | [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend) +<https://github.com/revenium/revenium-cli-node>                  |
| Connect OpenAI, Anthropic, or other provider billing accounts                            | [Provider Integrations](/integrations/provider-integrations)                                                                         |
| Send standard OpenTelemetry data                                                         | [OTLP Integration](/integrations/otlp-integration)                                                                                   |
| Send custom payloads directly to Revenium                                                | [API Reference](https://revenium.readme.io)                                                                                          |
| Let an AI coding assistant read Revenium docs while you integrate                        | [Context7 and AI Docs Access](/integrations/context7)                                                                                |
| Let an AI agent query or operate Revenium through tools                                  | [MCP Server](/integrations/mcp-server)                                                                                               |
| Use Revenium from the command line                                                       | [Revvy CLI](/integrations/revvy-cli) + use [Revenium CLI ](https://github.com/revenium/revenium-cli-node)for AI assistant onboarding |
| Connect team workflow systems                                                            | [Slack](/integrations/slack)                                                                                                         |

The canonical API domain for examples in this documentation is `https://api.revenium.ai`.

## What Lives Here

Please see [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend)section for AI assitant integrations

| Page                                                         | Use it for                                                                                                    |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- |
| [SDK Setup](/integrations/sdk-setup)                         | Python, Node.js, Go, LangChain, n8n, and other middleware setup.                                              |
| [API Key Permissions](/integrations/api-key-permissions)     | Choosing the right key type and understanding current scoped-key limits.                                      |
| [Provider Integrations](/integrations/provider-integrations) | Connecting provider accounts for billing and historical usage import.                                         |
| [API Data Sources](/integrations/api-data-sources)           | Understanding application data sources and integration identifiers.                                           |
| [OTLP Integration](/integrations/otlp-integration)           | OpenTelemetry endpoints, authentication, GenAI attributes, and examples.                                      |
| [Context7 and AI Docs Access](/integrations/context7)        | Letting AI coding assistants retrieve Revenium docs and schemas.                                              |
| [MCP Server](/integrations/mcp-server)                       | Connecting MCP-compatible agents to Revenium.                                                                 |
| [Revvy CLI](/integrations/revvy-cli)                         | Guided command-line setup and codebase instrumentation.                                                       |
| [Slack](/integrations/slack)                                 | Route AI cost alerts, anomaly notifications, and reports to Slack channels.                                   |
| [API Reference](https://revenium.readme.io)                  | Trying direct API calls and reading schema-level details.                                                     |
| Need custom payloads or a non-SDK path?                      | Start with [OTLP Integration](/integrations/otlp-integration) or [API Reference](https://revenium.readme.io). |


# SDK Setup

Use SDK Setup when you are instrumenting an application directly with Revenium SDKs, middleware, API keys, and integration identifiers. Start here if you are adding metering to code you own.

## What You Need

* A Revenium API key with the right scope for your integration.
* Your tenant, team, and environment identifiers.
* The API base URL for your workspace.
* A choice of integration path: SDK, middleware, OTLP, MCP, Revvy CLI, or direct API.

## Recommended Next Steps

1. Review [API Key Permissions](/integrations/api-key-permissions) before creating production keys.
2. Choose an implementation path from [Integration Options](/integrations/integrations).
3. Use [Provider Integrations](/integrations/provider-integrations) for billing-provider account connections.
4. Use [OTLP Integration](/integrations/otlp-integration) if your stack already emits OpenTelemetry.

## <i class="fa-python">:python:</i> Python SDK

Install only the providers you need:

| Provider                           | Install command                                        |
| ---------------------------------- | ------------------------------------------------------ |
| OpenAI or Azure OpenAI             | `pip install "revenium-python-sdk[openai]"`            |
| Anthropic or Anthropic via Bedrock | `pip install "revenium-python-sdk[anthropic]"`         |
| Google Gemini                      | `pip install "revenium-python-sdk[google-genai]"`      |
| Google Vertex AI                   | `pip install "revenium-python-sdk[google-vertex]"`     |
| LiteLLM                            | `pip install "revenium-python-sdk[litellm]"`           |
| LiteLLM Proxy                      | `pip install "revenium-python-sdk[litellm-proxy]"`     |
| Ollama                             | `pip install "revenium-python-sdk[ollama]"`            |
| Perplexity                         | `pip install "revenium-python-sdk[perplexity-openai]"` |
| Fal.ai                             | `pip install "revenium-python-sdk[fal]"`               |
| LangChain                          | `pip install "revenium-python-sdk[langchain]"`         |

You can install multiple extras together, for example:

```bash
pip install "revenium-python-sdk[openai,anthropic,langchain]"
```

## <i class="fa-node">:node:</i> Node.js Middleware

Use the unified middleware package and provider sub-paths:

| Provider              | Package                              |
| --------------------- | ------------------------------------ |
| OpenAI / Azure OpenAI | `@revenium/middleware/openai`        |
| Anthropic             | `@revenium/middleware/anthropic`     |
| Google Vertex AI      | `@revenium/middleware/google/vertex` |
| Google AI SDK         | `@revenium/middleware/google/genai`  |
| Perplexity            | `@revenium/middleware/perplexity`    |
| LiteLLM               | `@revenium/middleware/litellm`       |

Install from npm:

```bash
npm install @revenium/middleware
```

## <i class="fa-golang">:golang:</i> Go SDK

Install:

```bash
go get github.com/revenium/revenium-go-sdk
```

Minimal OpenAI wrapper:

```go
import (
    "os"

    "github.com/revenium/revenium-go-sdk/openai"
    openai_sdk "github.com/openai/openai-go"
)

client := openai.Wrap(openai_sdk.NewClient(), openai.Config{
    APIKey: os.Getenv("REVENIUM_API_KEY"),
})
```

## Frameworks and Agent Tooling

| Framework or tool                                          | Start here                                                                                                                                                            |
| ---------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| LangChain                                                  | Use the Python `langchain` extra, or use [OTLP Integration](/integrations/otlp-integration) if your app already emits OpenTelemetry.                                  |
| n8n                                                        | Use the Revenium n8n middleware packages for OpenAI or Anthropic agents.                                                                                              |
| OpenInference / OpenLLMetry                                | Use [OTLP Integration](/integrations/otlp-integration).                                                                                                               |
| Claude Code, Gemini CLI, Cursor, and other AI coding tools | Use [Context7 and AI Docs Access](/integrations/context7), [MCP Server](/integrations/mcp-server), or [Revvy CLI](/integrations/revvy-cli) depending on the workflow. |
| JetBrains IDEs (IntelliJ, PyCharm, GoLand, etc.)           | Use [Revvy CLI](/integrations/revvy-cli) for guided instrumentation — scans your codebase, finds AI call sites, and walks through SDK setup.                          |

## Usage Metadata

SDKs accept optional usage metadata for billing, attribution, and alerting. The fields accepted on `POST /meter/v2/ai/completions` are:

| Field                  | Purpose                                                                                                        |
| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
| `organizationName`     | Top-level customer account. Required — the legacy `organizationId` alias is silently dropped.                  |
| `productName`          | Commercial tier or SKU. Required — the legacy `productId` alias is silently dropped.                           |
| `subscriber`           | Object: `{ id, email, credential: { name, value } }` — the end customer plus their specific API key.           |
| `agent`                | Agent name making the call; powers per-agent cost views and the Tool Registry.                                 |
| `traceId`              | Links sequential AI calls into a single execution path for Trace Analytics.                                    |
| `taskType`             | Categorises the work the agent was doing (qualification, support, code review, etc.).                          |
| `subscriptionId`       | The Revenium subscription this call rates against.                                                             |
| `responseQualityScore` | `0.0–1.0` evaluation score from RAGAS, LLM-as-judge, human review, or other quality signals.                   |
| `ticketId`             | Optional support-ticket or work-item identifier, for tying metered usage back to the ticket that generated it. |

At minimum, pass `organizationName` + `productName`. Add `subscriber.id` to attribute usage and cost to individual end users, and `agent` and `traceId` to unlock agent-level cost views and Trace Analytics. The remaining fields are optional.

`ticketId` is currently available in the Python SDK and the Node.js and Go middleware packages.

For OpenTelemetry attribution, see the `revenium.*` attributes in [OTLP Integration](/integrations/otlp-integration#deep-attribution-with-revenium-attributes).

## Related

* [API Reference](https://revenium.readme.io)
* [Revvy CLI](/integrations/revvy-cli)
* [Context7 and AI docs access](/integrations/context7)


# LiteLLM Proxy Setup

Meter a self-hosted LiteLLM proxy in real time by registering Revenium as a proxy callback. Revenium connects to your existing LiteLLM proxy — it does not host LiteLLM. The callback runs inside your proxy and reports each call to Revenium as it happens.

There are two ways to meter a LiteLLM proxy, and they suit different needs:

* **Proxy callback (this page)** — real-time metering. Every call through the proxy is reported to Revenium as it completes. Requires a small change to your proxy configuration.
* **Provider integration** — scheduled sync with no code change. Revenium pulls spend and usage from your proxy's admin API on a schedule. See [Provider Integrations](/integrations/provider-integrations#litellm).

## What you need

* A LiteLLM proxy you operate, with a `config.yaml` you can edit and restart.
* A Revenium metering API key.
* Python available in the environment that runs your proxy.

## 1. Install the callback

Install the Revenium SDK with the LiteLLM proxy extra into the same environment as your proxy:

```bash
pip install "revenium-python-sdk[litellm-proxy]"
```

## 2. Register the callback in your proxy config

Add the Revenium callback to `litellm_settings` in your proxy `config.yaml`:

```yaml
litellm_settings:
  callbacks: ["revenium_middleware.litellm.proxy.middleware.proxy_handler_instance"]
```

## 3. Set the metering key

Provide your Revenium metering API key to the proxy environment:

```bash
export REVENIUM_METERING_API_KEY="your_revenium_metering_api_key"
```

Then restart the proxy so it loads the callback.

## 4. Send a test transaction to confirm capture

Send one request through your proxy and confirm it appears in Revenium. This is the step that tells you exactly what your proxy captures — the callback follows what your LiteLLM version logs, so a test transaction is the reliable way to confirm coverage for the request formats you use.

```bash
curl -s "$LITELLM_PROXY_URL/chat/completions" \
  -H "Authorization: Bearer $LITELLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "your-configured-model",
    "messages": [{"role": "user", "content": "Confirm metering is active."}]
  }'
```

Within a minute the call appears in your Revenium metering data. If it does not, confirm the callback line is present in `config.yaml`, the metering key is set in the proxy environment, and the proxy was restarted after the change.

## Adding attribution

To attribute each call to a customer, product, agent, or task, pass Revenium metadata as request headers. Your application sends these alongside its normal proxy request:

```
x-revenium-trace-id
x-revenium-task-type
x-revenium-organization-name
x-revenium-product-name
x-revenium-agent
x-revenium-subscriber-email
x-revenium-subscriber-id
```

## What the callback captures

The callback meters calls that pass through your proxy, in real time, covering every model and provider your proxy routes to. What is captured follows what your LiteLLM version logs — use the test transaction above to confirm coverage for your specific request formats.

{% hint style="info" %}
**LiteLLM configuration note.** Proxy callbacks fire on the proxy's standard call path. They do **not** fire when the proxy runs with `use_chat_completions_url_for_anthropic_messages: true` — a LiteLLM setting with a known upstream issue ([BerriAI/litellm#27518](https://github.com/BerriAI/litellm/issues/27518), fix in [PR #27609](https://github.com/BerriAI/litellm/pull/27609)). If your proxy uses that setting, confirm capture with a test transaction before relying on the callback.
{% endhint %}

## Choose one metered path per workload

If a workload is already metered another way — for example Claude Code reporting its own usage over OpenTelemetry — meter it in **one** place. Two metered writers for the same calls report the usage twice, because they submit independently with no shared transaction identifier. Pick the proxy callback **or** the client telemetry for a given workload, and use the other only for the detail it uniquely adds.

Comparing what your provider **bills** against what Revenium **meters** is a separate, designed capability: billed and metered figures are held independently and shown side by side for reconciliation and coverage-health, never added together. Connecting your LiteLLM proxy as a [provider integration](/integrations/provider-integrations#litellm) for billed data is always safe alongside real-time metering.


# API Key Permissions

Revenium API keys use scoped prefixes for metering, write access, and read-only integrations. Choose the narrowest scope your integration needs.

Revenium API keys authenticate SDKs, middleware, OpenTelemetry exporters, CLI tools, MCP servers, and administrative integrations. Each scoped key prefix shows what the key is allowed to do. Use the narrowest key that supports the workflow you are configuring.

## Key Types

Every Revenium scoped API key carries a prefix indicating its permission scope:

| Prefix    | Scope               | Recommended use                                                                                                                                          |
| --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rev_mk_` | Metering-only       | Production applications, SDK ingestion, middleware, and OpenTelemetry exporters that only need to send metering events.                                  |
| `rev_sk_` | Write / full-access | MCP servers, administrative scripts, outcome-reporting workflows, provisioning tools, and integrations that need to create or modify Revenium resources. |
| `rev_rk_` | Read-only           | Dashboards, reports, audit tools, and internal automation that only needs to read Revenium data.                                                         |

## Choosing the Right Scope

Pick the narrowest scope that the integration needs:

* Use a metering-only (`rev_mk_`) key for SDK, middleware, and OTLP integrations that only send usage or telemetry data.
* Use a write/full-access (`rev_sk_`) key for MCP servers, account automation, provisioning scripts, and outcome-reporting workflows.
* Use a read-only (`rev_rk_`) key for dashboards, reports, or audit tooling that should not create or modify resources.

When a page gives integration-specific guidance, follow that page's key scope. For example, [OpenTelemetry Integration](/integrations/otlp-integration) uses `rev_mk_`, while [MCP Server](/integrations/mcp-server) uses `rev_sk_`.

## Read-only access for users

The scopes above govern **API keys**. Read-only access also exists at the **user** level: a **Read-Only** role grants a person view-only access to Revenium — they can see the data their scope allows but cannot create, modify, or delete resources. This is the user-account counterpart to a read-only (`rev_rk_`) key. In this release the Read-Only role is assigned through the API rather than the admin UI. See [Manage Users & Teams](/account-and-resources/manage-users-and-teams#roles) for details.

## Creating and Managing Keys

Keys are managed on the **Connections → SDK Setup** page in the Revenium UI:

* **Create** — The Create Key dialog lets you pick the scope (Full Access / Read Only / Metering Only) and name the key before it's issued.
* **View** — The Revenium API Keys table shows each key's name, its scope, the last four characters of the secret, expiry, creator, and creation date. Only the last four characters of the secret are shown after creation — the full value is displayed only once, when the key is created.
* **Rename** — Click the pencil icon in the Actions column (or the key's name) to rename a key inline. Names are free-form and meant to describe where the key is used (e.g., "Production ingestion — us-east", "Finance dashboard").
* **Delete** — Use the delete icon in the Actions column to revoke a key.

## Key Format

Scoped keys have the shape:

```
{PREFIX}_{TENANT_ID}_{SECRET}
```

Where `PREFIX` is one of `rev_mk_`, `rev_sk_`, or `rev_rk_`; `TENANT_ID` is your encoded organization identifier; and `SECRET` is the secret key material.

{% hint style="warning" %}
**Treat API keys as secrets.** Do not commit keys to source control, paste them into chat logs, or share them in screenshots. Full-access keys can modify and delete resources; metering-only keys can still generate billable events. Revoke any key you suspect has been exposed.
{% endhint %}

## Related

* [Connections](/integrations/integrations) — overview of Provider Connections and SDK Integrations.
* [Integration Options for AI Metering](/integrations/integrations) — which SDK to use for which stack.
* [OpenTelemetry Integration](/integrations/otlp-integration) — using Revenium with standard OTEL exporters.


# Rate Limits

Revenium applies generous rate limits to keep usage predictable for agents and integrations. Limits are scoped per account and grouped into three buckets, each with its own ceiling and observable response headers.

## Buckets and limits

Every authenticated request is mapped to one of three buckets based on the path. Each bucket has its own request-per-second limit.

| Bucket      | Paths                                                                                                                                                                      | Limit         |
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `metering`  | `/meter/v2/**` (REST metering: AI completions, events, tool, API) and `/v2/otlp/**` (OTLP signals)                                                                         | 1,000 req/sec |
| `analytics` | AI Metrics, AI Traces, billing analytics, chart and cost-attribution reads                                                                                                 | 100 req/sec   |
| `platform`  | All other `/profitstream/v2/api/**` and `/v2/sdk/**` endpoints (CRUD on subscriptions, tenants, sources, integrations, alerts, models, anomalies, plus SDK auth endpoints) | 50 req/sec    |

Limits are per account, not per API key. If your integration uses multiple keys under the same account, they share the bucket budget.

## Response headers

Four headers appear on every authenticated response that resolves to a bucket, regardless of status code (`2xx`, `4xx`, `5xx`, `204`).

| Header                  | Meaning                                                                                 |
| ----------------------- | --------------------------------------------------------------------------------------- |
| `X-RateLimit-Limit`     | Maximum requests allowed in the current window for this bucket                          |
| `X-RateLimit-Remaining` | Requests remaining in the current window. Reaches `0` at the limit, never goes negative |
| `X-RateLimit-Reset`     | Unix epoch (seconds) when the current window resets                                     |
| `X-RateLimit-Bucket`    | Which bucket this request mapped to: `metering`, `analytics`, or `platform`             |

Use `Remaining` to throttle preemptively. Use `Reset` to schedule your next batch. Use `Bucket` so a metering call does not back off because a platform call was busy.

Limits reset each second. Use `X-RateLimit-Reset` to see exactly when.

## When you hit the limit

A request that exceeds the bucket budget returns `429 Too Many Requests` with two additional headers and a JSON body.

**Additional headers:**

| Header                       | Meaning                                                                                                    |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `Retry-After`                | Seconds to wait before retrying. Integer, always present                                                   |
| `X-RateLimit-Limited-Reason` | Why the limit fired. Values: `bucket-rate` (bucket exhaustion) or `error-pattern` (repeated 4xx responses) |

**Response body:**

```json
{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded for bucket metering. Retry after 1 second.",
    "bucket": "metering",
    "doc_url": "https://docs.revenium.io/integrations/rate-limits"
  }
}
```

The `bucket` field is present when `Limited-Reason` is `bucket-rate`. For `error-pattern`, the body still has `type`, `code`, `message`, and `doc_url`, but no `bucket`.

## Error-pattern protection

Beyond per-bucket budgets, Revenium temporarily slows callers that produce sustained `4xx` errors. This protects accounts from runaway misconfigured integrations spamming the API with broken requests.

Sustained `4xx` over a short window triggers a temporary block. Each consecutive violation doubles the cooldown, capped at one hour. `Retry-After` reflects the remaining cooldown. `X-RateLimit-Limited-Reason` will be `error-pattern`.

Fix the underlying request (auth, missing fields, invalid IDs) and the cooldown clears on its own.

## Recommended client behavior

1. **Read the headers.** Treat `X-RateLimit-Remaining` and `X-RateLimit-Reset` as authoritative. If `Remaining` is low, slow down before you hit `0`.
2. **Honor `Retry-After`.** On `429`, wait at least that many seconds before retrying. Do not retry sooner.
3. **Use exponential backoff with jitter on repeat 429s.** Start at the `Retry-After` value and add randomized jitter to avoid thundering-herd retries with other clients in your account.
4. **Differentiate by `Limited-Reason`:**
   * `bucket-rate`: you are sending too fast. Throttle by `Remaining`.
   * `error-pattern`: you are sending broken requests. Fix the request shape, not the rate.
5. **Separate metering from platform calls.** The metering bucket has 20x the platform budget. A busy `platform` flow should not slow down `metering`.

If you have a use case that needs sustained higher throughput on a specific bucket, [contact support](mailto:support@revenium.io) so we can review the integration.


# Idempotency

Network timeouts and aborted connections make it hard to know whether a metering POST actually landed. Replaying the call could mean double-counted usage, which then has to be cleaned up by hand. Revenium accepts a Stripe-style `Idempotency-Key` header on metering write endpoints so retries are safe by default.

## How it works

Send a unique, client-generated string in the `Idempotency-Key` header on a metering POST. Revenium caches the response (status code and body) for 24 hours keyed by your account and that key. Any retry that reuses the same key replays the cached response without re-executing the request. Use a fresh key for every distinct call, and reuse the same key only when retrying that exact call.

The header is opt-in. Requests without it pass through unchanged.

## Supported endpoints

Idempotency applies to every REST metering POST endpoint.

| Method | Path                       |
| ------ | -------------------------- |
| `POST` | `/meter/v2/ai/completions` |
| `POST` | `/meter/v2/ai/images`      |
| `POST` | `/meter/v2/ai/audio`       |
| `POST` | `/meter/v2/ai/video`       |
| `POST` | `/meter/v2/apis/requests`  |
| `POST` | `/meter/v2/apis/responses` |
| `POST` | `/meter/v2/events`         |
| `POST` | `/meter/v2/tool/events`    |

OTLP endpoints (`/v2/otlp/**`) are not covered today. The OTLP SDKs already retry internally, so end-to-end retry safety on that path will land in a future release.

## Key format

| Constraint  | Value                                                                    |
| ----------- | ------------------------------------------------------------------------ |
| Length      | 1 to 255 characters                                                      |
| Charset     | Printable ASCII only (`!` through `~`, no spaces, no control characters) |
| Recommended | UUID v4 generated client-side, one per logical request                   |

Keys are scoped per account, so two accounts can use identical key strings without colliding.

## Behavior matrix

What the server returns depends on whether a record already exists for `(account, key)` and what the request body looks like.

| Scenario                                                                                                                                    | Result                                                                          |
| ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| New key                                                                                                                                     | Request runs normally, response is cached for 24 hours                          |
| Same key, same request                                                                                                                      | Cached response is replayed: original status code, body, and content type       |
| Same key, different body                                                                                                                    | `409 Conflict` with code `idempotency_key_mismatch`                             |
| Same key, concurrent retry while the first call is in flight                                                                                | `409 Conflict` with code `idempotency_key_in_progress`, header `Retry-After: 1` |
| Key fails format validation (empty value, longer than 255 characters, non-printable characters, or sent more than once in the same request) | `400 Bad Request` with code `invalid_idempotency_key`                           |

The fingerprint that defines "same request" is `(HTTP method, request path, request body)`. Request headers (including content type) and query string are not part of it. If you send the same body to the same endpoint with the same key, you will get the cached response back.

## Error envelope

All idempotency errors share the same JSON envelope.

```json
{
  "error": {
    "type": "idempotency_error",
    "code": "idempotency_key_mismatch",
    "message": "The same Idempotency-Key was used with a different request.",
    "doc_url": "https://docs.revenium.io/integrations/idempotency"
  }
}
```

| Field     | Description                                                                                 |
| --------- | ------------------------------------------------------------------------------------------- |
| `type`    | `idempotency_error` for `409` conflicts, `validation_error` for `400` bad key format        |
| `code`    | One of `idempotency_key_mismatch`, `idempotency_key_in_progress`, `invalid_idempotency_key` |
| `message` | Human-readable description of the specific case                                             |
| `doc_url` | Link back to this page                                                                      |

## Recommended client behavior

1. **Generate one UUID v4 per logical request.** Treat the key as part of that request, not a per-session token. The same logical retry must reuse the same key.
2. **Persist the key with your retry state.** If your client retries from another process or after a restart, it still needs the original key to benefit from replay.
3. **Send the same body on retry.** If your client mutates the payload between attempts (a fresh timestamp, a regenerated trace id), the second call returns `idempotency_key_mismatch`. Build the body once, then resend the same bytes.
4. **Handle `idempotency_key_in_progress` with a short wait.** Your previous call is still executing. Respect `Retry-After: 1` and try again.
5. **Treat the cache TTL as 24 hours.** A retry sent more than 24 hours after the original call will execute fresh, with no replay. By that point a real duplicate is extremely unlikely; if you need stricter guarantees, deduplicate client-side as well.

If you have a use case that needs broader idempotency coverage, [contact support](mailto:support@revenium.io).


# Webhook Signing

Outbound webhooks from Revenium can be cryptographically signed so receivers verify the payload originated from Revenium and was not tampered with in transit. Signing is opt-in per webhook: enable it from the dashboard, copy the secret once, verify every delivery against that secret.

## How it works

When a webhook has signing enabled, every dispatch carries two headers and a deterministic signature over the request body. The receiver recomputes the signature locally and compares against the one on the wire. If they match, the payload is authentic.

Webhooks without signing enabled keep being delivered unchanged. No headers are added, and the receiver does not need to do anything different.

## Headers

Two headers appear on every signed delivery.

| Header                         | Meaning                                                                                                                                                     |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-Revenium-Signature-256`     | `sha256=<hex>`. During a 24h rotation overlap, two signatures are present: `sha256=<hex_new>, sha256=<hex_previous>` (RFC 7230 multi-value, comma + space). |
| `X-Revenium-Webhook-Timestamp` | Unix epoch seconds at signing time. Used both as part of the signed payload and to reject replays.                                                          |

## Verification algorithm

```
signed_payload = <X-Revenium-Webhook-Timestamp> + "." + raw_request_body_bytes
expected       = HMAC-SHA256(secret, signed_payload)
header_value   = "sha256=" + lowercase_hex(expected)
```

Three rules a correct verifier must follow:

1. **Sign the raw wire bytes**, not a re-serialised copy. If your framework parses JSON then stringifies it back, whitespace and key order differ from what was signed. Read the body as bytes before JSON-decoding.
2. **Reject the request if the timestamp drifts more than 300 seconds** from your local clock. This is the replay defence.
3. **Use a constant-time comparison.** Python: `hmac.compare_digest`. Node: `crypto.timingSafeEqual`. Go: `hmac.Equal`. Direct `==` comparison leaks the signature through timing side-channels.

## Multi-signature during rotation

When a customer rotates the signing secret in the dashboard, the previous secret remains valid for **24 hours** so receivers can roll forward without downtime. During that window, every delivery is signed with **both** secrets, and the header carries both signatures comma-separated:

```
X-Revenium-Signature-256: sha256=8e7f3a..., sha256=2b4c91...
```

Receivers verify by trying their currently-deployed secret against every signature in the header. As long as one matches, the delivery is authentic. After the 24h window expires, the header returns to a single signature on the new secret.

An immediate rotation (used when a secret is known to be compromised) skips the overlap window: the previous secret stops verifying right away.

## Testing your receiver

The API exposes two endpoints that together let you produce a signed delivery on demand, useful during integration:

1. **Enable signing or rotate the secret.** `POST /profitstream/v2/api/export-configurations/{id}/rotate-signing-secret?teamId=...` returns `{ "signingSecret": "<value>" }`. The secret is shown exactly once. Body `{ "immediate": true }` skips the rotation overlap; `{}` (default) starts the 24h graceful window.
2. **Trigger a synthetic delivery.** `POST /profitstream/v2/api/export-configurations/{id}/send-test-event?teamId=...` dispatches a synthetic event through the same code path used in production. The receiver sees the same headers and signing behaviour as a real event.

Configure your receiver to log the headers and body, capture one synthetic delivery, run it through your verifier, and confirm the signature matches.

## Code examples

Reference implementations using language standard libraries.

### Python

```python
import hmac
import hashlib
import time

def verify_signature(payload: bytes, signature_header: str, timestamp_header: str, secrets: list[str], tolerance_seconds: int = 300) -> bool:
    if abs(time.time() - int(timestamp_header)) > tolerance_seconds:
        return False
    signed_payload = f"{timestamp_header}.".encode() + payload
    received = [s.strip().removeprefix("sha256=") for s in signature_header.split(",") if s.strip().startswith("sha256=")]
    for secret in secrets:
        expected = hmac.new(secret.encode(), signed_payload, hashlib.sha256).hexdigest()
        if any(hmac.compare_digest(expected, r) for r in received):
            return True
    return False
```

### Node

```javascript
const crypto = require('crypto');

function verifySignature({ payload, signatureHeader, timestampHeader, secrets, toleranceSeconds = 300 }) {
  if (Math.abs(Date.now() / 1000 - parseInt(timestampHeader, 10)) > toleranceSeconds) return false;
  const body = Buffer.isBuffer(payload) ? payload : Buffer.from(payload);
  const signedPayload = Buffer.concat([Buffer.from(`${timestampHeader}.`), body]);
  const received = signatureHeader.split(',').map(s => s.trim()).filter(s => s.startsWith('sha256=')).map(s => s.slice(7));
  for (const secret of secrets) {
    const expected = crypto.createHmac('sha256', secret).update(signedPayload).digest('hex');
    const expectedBuf = Buffer.from(expected, 'hex');
    if (received.some(r => {
      const rBuf = Buffer.from(r, 'hex');
      return rBuf.length === expectedBuf.length && crypto.timingSafeEqual(expectedBuf, rBuf);
    })) return true;
  }
  return false;
}
```

### Go

```go
package main

import (
    "crypto/hmac"
    "crypto/sha256"
    "encoding/hex"
    "fmt"
    "math"
    "strconv"
    "strings"
    "time"
)

func VerifySignature(payload []byte, signatureHeader, timestampHeader string, secrets []string, toleranceSeconds int) bool {
    if toleranceSeconds == 0 {
        toleranceSeconds = 300
    }
    ts, err := strconv.ParseInt(timestampHeader, 10, 64)
    if err != nil {
        return false
    }
    if math.Abs(float64(time.Now().Unix()-ts)) > float64(toleranceSeconds) {
        return false
    }
    signedPayload := append([]byte(fmt.Sprintf("%s.", timestampHeader)), payload...)
    var received []string
    for _, s := range strings.Split(signatureHeader, ",") {
        s = strings.TrimSpace(s)
        if strings.HasPrefix(s, "sha256=") {
            received = append(received, strings.TrimPrefix(s, "sha256="))
        }
    }
    for _, secret := range secrets {
        mac := hmac.New(sha256.New, []byte(secret))
        mac.Write(signedPayload)
        expected := hex.EncodeToString(mac.Sum(nil))
        for _, r := range received {
            if hmac.Equal([]byte(expected), []byte(r)) {
                return true
            }
        }
    }
    return false
}
```

## Recommended receiver behavior

1. **Read the body as bytes before parsing.** Frameworks that auto-decode JSON may discard the original byte stream. If you can only get the parsed object, you cannot verify.
2. **Verify before any side effect.** Reject unverified deliveries early; do not write to your database or trigger downstream calls until the signature checks out.
3. **Keep both secrets while you rotate.** During the 24h overlap, your receiver should hold the new secret and the previous one. Drop the previous secret only after the window closes.
4. **Persist a small dedup window.** Two retries can deliver the same event; the signature confirms authenticity but not uniqueness. Use the event identifier in the payload (or the timestamp + body hash) to deduplicate on your side.

If you have a use case that needs broader signing coverage or alternative algorithms, [contact support](mailto:support@revenium.io).


# Provider Integrations

While the Revenium SDK intercepts your live application traffic, connecting your underlying AI provider accounts (OpenAI, Anthropic, AWS Bedrock, Google Vertex AI, Azure, fal.ai, Runway, OpenRouter, LiteLLM, Cursor) unlocks the other half of the FinOps picture: provider-native cost data synced directly from each provider's billing system.

> <i class="fa-square-info">:square-info:</i> **Note on Provider Permissions:** Different AI platforms have different permission models. Always check the specific instructions on the **Link Provider** screen, and use the credential type called out below for each provider. The wrong key type will authenticate but return zero billing data.

When you add your provider API Keys, Revenium actively syncs with the provider to pull granular usage records and workspace data. This unlocks four primary dashboard views:

<table><thead><tr><th width="204.390625">Insight</th><th>What It Tells You</th></tr></thead><tbody><tr><td><strong>Workspaces</strong></td><td>Provider billing and Revenium-metered spend side by side, with a named coverage-health state that helps you identify under-metered activity.</td></tr><tr><td><strong>API Keys</strong></td><td>A breakdown of cost, usage, and tokens by individual API key to help you spot rogue or uninstrumented scripts.</td></tr><tr><td><strong>Models</strong></td><td>The true cost per 1M tokens (or provider-specific unit) across all your active AI models so you can compare performance vs. price.</td></tr><tr><td><strong>Management</strong></td><td>Workspace naming and organization controls that make provider-generated identifiers easier for teams to understand.</td></tr></tbody></table>

***

## Supported Providers

Each connected provider syncs cost, usage, and workspace data using its own native billing API.

* **OpenAI** – GPT, DALL-E, embeddings, and all OpenAI API services. Requires an **Organization Admin API key** — project-scoped keys cannot read billing or usage data.
* **Anthropic** – Claude models and all Anthropic API services. Requires an **admin key** (`sk-ant-admin...`) — workspace-scoped service keys and Enterprise Analytics API keys cannot read billing or usage data. Note: request counts may show as `N/A` because Anthropic's billing API does not expose them.
* **AWS Bedrock** – Synced via the AWS Cost Explorer API. Requires **IAM user credentials** (Access Key ID + Secret), not Bedrock API keys. Bedrock API keys (`ABSK...`) can invoke models but cannot read billing. **Provider credits applied** (AWS Activate, enterprise agreements) are captured per-day per-model and visible on the dashboard.
* **Google Vertex AI** – Synced via BigQuery Billing Export. Cost data has a 24–48 hour delay — this is BigQuery export latency, not a sync issue. **Provider credits applied** (GCP startup credits, enterprise agreements) are captured per-day per-model and visible on the dashboard.
* **fal.ai** – 600+ image, video, audio, and LLM endpoints. Requires an **ADMIN** API key — regular user keys cannot return cost or usage breakdowns.
* **Runway** – Video and image generation (Gen-4, Gen-4 Turbo). Credits are converted to dollars at 1 credit = $0.01.
* **OpenRouter** – Multi-provider gateway with 200+ models. Standard API key required; an optional Provisioning Key (Team/Enterprise plans) unlocks per-user and per-request usage breakdowns.
* **Azure** – Synced via the Azure Cost Management API using a Service Principal. Requires an **App Registration** with Client ID, Client Secret, Tenant ID, and Subscription ID. The Service Principal must have the **Cost Management Reader** role at subscription scope. Cost data is delayed 8–24 hours for EA/MCA agreements and up to 72 hours for Pay-As-You-Go subscriptions.
* **LiteLLM** – Self-hosted proxy with unified access to 100+ LLM providers. Revenium connects to your proxy's API; LiteLLM itself is not hosted by Revenium.
* **Cursor** – Coding-assistant usage synced automatically by Revenium, with no CLI to install. Requires a Cursor **team** API key — a personal user key will not work. Usage is synced every 5 minutes.

***

## Provider Credits (AWS Bedrock + Google Vertex AI)

Customers on AWS or GCP often receive provider credits — AWS Activate, GCP startup credits, enterprise agreements — that reduce their real AI spend. Revenium captures these credits and displays them alongside list-price costs so margin reporting reflects what you're actually paying, not just the sticker price.

### What's Captured

For both AWS Bedrock and Google Vertex AI, Revenium ingests applied credits from each provider's billing surface:

* **AWS Bedrock** – credits retrieved from AWS Cost Explorer alongside Bedrock billing cost data.
* **Google Vertex AI** – credits retrieved from the BigQuery billing export (sums GCP credit types — promotional, committed-usage discounts, and others).

Credits are stored at the same grain as cost: per organization, per workspace, per API key, per model, per day.

### Where To Find It

The provider cost dashboard exposes credits applied per provider so you can see the gap between list-price spend and real spend in one view. Net cost = total cost − credits applied.

{% hint style="info" %}
**Sign convention:** `creditsApplied` is stored as a positive number representing the credit amount. Net cost = `totalCost − creditsApplied`.
{% endhint %}

{% hint style="info" %}
**AWS service-level credits:** Some AWS credits arrive scoped to the Bedrock service rather than to a specific model. These are reported under the model bucket `bedrock-general` so you can still see the spend impact even when AWS does not attribute them to a particular foundation model.
{% endhint %}

### Why It Matters

* **Margin accuracy** — list-price reporting overstates real AI cost when credits are in play.
* **Budget planning** — knowing how much of current spend is offset by credits helps forecast when credits run out.
* **Customer reporting** — net cost is the number that flows to invoicing and chargebacks.

### Out Of Scope

* Azure (billing integration available, but credit capture is not yet supported).
* Other cloud providers (only AWS Bedrock and Google Vertex AI have credit capture in this release).

***

## How Provider Sync Works

1. **Connect provider accounts** from **Connections → Providers** using the **Link Provider** button.
2. **Automatic sync** pulls workspaces, API keys, and usage data from provider billing systems on a regular schedule.
3. **Manual refresh** is available from the Provider Dashboard via the **Refresh Data** button — useful right after adding new keys, or when troubleshooting discrepancies. A manual refresh may take 30–60 seconds.
4. **Historical tracking** compares the current period against the previous period to surface trends and outliers.

***

## How to Link a Provider

1. Head to [Connections → Providers](https://app.revenium.ai/connections/providers) in the left sidebar and click **Link Provider**.
2. Select your AI platform, drop in your credentials, and confirm.

Revenium authenticates the credential and starts syncing historical data immediately.

### Credential Quick Reference

<table><thead><tr><th>Provider</th><th width="172">Format</th><th>Key Pattern</th><th>Where to Get</th></tr></thead><tbody><tr><td>OpenAI</td><td>API Key (read only)</td><td><code>sk-admin...</code><br>(Note: must be an <strong>admin key</strong>.)</td><td>Organization Settings / Admin keys (<a href="https://platform.openai.com/settings/organization/admin-keys">link</a>)</td></tr><tr><td>Anthropic</td><td>API Key</td><td><code>sk-ant-admin...</code><br>(Note: must be an <strong>admin key</strong>.)<br>Enterprise Analytics API keys are not supported.</td><td>Claude Console / Organization Settings / Admin keys (<a href="https://platform.claude.com/settings/admin-keys">link</a>)</td></tr><tr><td>AWS Bedrock</td><td>IAM Credentials</td><td>Access Key ID (<code>AKIA...</code>) + Secret + Region (<code>us-east-1</code>)</td><td>AWS Console → IAM → Users</td></tr><tr><td>Google Vertex AI</td><td>Service Account JSON</td><td><code>{"type":"service_account",...}</code></td><td>GCP Console → IAM → Service Accounts</td></tr><tr><td>fal.ai</td><td>API Key (ADMIN)</td><td><code>{uuid}:{hex}</code></td><td>fal.ai team/admin key settings</td></tr><tr><td>Runway</td><td>API Key</td><td><code>key_...</code></td><td>Runway workspace API key settings</td></tr><tr><td>OpenRouter</td><td>JSON</td><td><code>{"apiKey":"sk-or-v1-...", "provisioningKey":"..."}</code></td><td>OpenRouter key settings</td></tr><tr><td>Azure</td><td>Service Principal</td><td>Tenant ID + Client ID + Client Secret + Subscription ID</td><td>Azure Portal → App registrations</td></tr><tr><td>LiteLLM</td><td>JSON</td><td><code>{"apiKey":"sk-...", "baseUrl":"https://..."}</code></td><td>Your LiteLLM proxy admin</td></tr><tr><td>Cursor</td><td>API Key (team)</td><td>Cursor team API key</td><td>Cursor team settings</td></tr></tbody></table>

***

## Provider-Specific Setup Notes

### OpenAI

Use an **Organization Admin API key**, not a project-scoped key. Once linked, Revenium syncs project/workspace, API key, usage, cost, model, token, and request data that the provider exposes.

### Anthropic

**Supported: Console admin key.** Create an **admin key** (`sk-ant-admin...`) from Claude Console → **Organization Settings** → **Admin keys**, then add it in Revenium. Plain service keys (`sk-ant-api...`) scoped to a single workspace cannot read organization usage and are rejected.

**Not yet supported: Enterprise Analytics API keys.** Some Enterprise organizations issue Analytics API keys (`sk-ant-api...`) carrying the `read:analytics` and `read:spend_limits` scopes. Revenium syncs Anthropic data through Anthropic's Admin API, which those scopes do not authorize, so Analytics keys cannot be connected today. If your organization cannot mint an admin key, contact Revenium support. For reference, the Analytics path also carries these constraints:

* Scopes cannot be changed after creation — adding one later requires a new key.
* Only the **parent organization primary owner** can create the key. Ordinary organization owners are limited to Compliance-scoped keys, which do not work against the Analytics API.
* **Public API access** and the **Analytics API** must both be enabled at the organization level beforehand. These are two independent gates, separate from key creation.

**Limitations:**

* Data starts at **2026-01-01**; earlier usage is not backfilled.
* Seat-based Enterprise plans expose usage credits only — not seat spend.
* **Claude Team** plans have no API and cannot be connected.
* Claude Code traffic routed through **Amazon Bedrock** is not returned here; connect the Bedrock provider to capture it.
* Request counts render as `N/A` because Anthropic does not expose the metric.

### AWS Bedrock

Bedrock requires IAM credentials with billing read access — not Bedrock model-invocation keys.

**First, enable AWS Cost Explorer.** Cost Explorer must be turned on once per AWS account, manually, in the console — there is no API for this: AWS Console → **Billing and Cost Management** → **Cost Explorer**; opening it for the first time enables it. Until it's enabled, the billing-read calls below fail even with correct credentials. After enabling, AWS takes up to \~24 hours to prepare the first data, so a newly connected Bedrock provider shows an empty dashboard until then — expected, not an error.

Then, in the AWS Console, create an IAM user with programmatic access (an access key), and attach the least-privilege policy below. It grants billing read only, with no model invocation:

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReveniumBillingRead",
      "Effect": "Allow",
      "Action": [
        "ce:GetCostAndUsage",
        "sts:GetCallerIdentity"
      ],
      "Resource": "*"
    }
  ]
}
```

`ce:GetCostAndUsage` reads Bedrock spend from Cost Explorer; `sts:GetCallerIdentity` reads the account ID that identifies the workspace. Neither action can invoke a model. (Cost Explorer and `GetCallerIdentity` do not support resource-level scoping, so `Resource` is `*`.)

Enter the Access Key ID, Secret Access Key, and the Cost Explorer region — use `us-east-1`, which is Cost Explorer's service endpoint regardless of where your Bedrock workloads run — in Revenium. Revenium checks the credential against Cost Explorer when you connect, so an invalid key — or a Bedrock model-invocation key (`ABSK...`) — is caught right away rather than failing silently later.

{% hint style="info" %}
**Billing delay:** AWS Cost Explorer refreshes cost data at least once every 24 hours and reflects usage only up to the previous day. After you connect, Bedrock billing data can take up to \~24 hours to appear — an empty dashboard right after connect is expected, not a failure. The connection is validated and saved immediately; the cost data follows on AWS's refresh cycle. This is an AWS Cost Explorer pipeline characteristic, not a sync issue.
{% endhint %}

{% hint style="info" %}
**Bedrock agent workloads:** Agent-driven spend — for example Amazon Bedrock AgentCore — arrives through the same billing sync as your other Bedrock service costs. Where AWS reports it scoped to the Bedrock service rather than to a specific foundation model, it appears under the `bedrock-general` model bucket, and it follows the same up-to-24-hour Cost Explorer refresh cycle.
{% endhint %}

### Google Vertex AI

Vertex requires BigQuery Billing Export and a service-account JSON key.

Enable BigQuery Billing Export, create a service account that can read the export dataset and run BigQuery jobs, then paste the service-account JSON into Revenium. Billing export data usually has a 24-48 hour delay.

### fal.ai

Use an **ADMIN** API key, not a regular user key. Once linked, Revenium syncs per-endpoint, per-day cost and usage across image, video, audio, and LLM endpoints where the provider exposes that data.

### Runway

Use a workspace API key. Cost is tracked per model, with provider credit usage converted to USD for reporting.

### OpenRouter

Two key types are supported:

* **API Key** (required) — standard usage data and model access.
* **Provisioning Key** (optional, Team/Enterprise only) — unlocks per-user and per-request usage breakdowns.

Paste credentials as a JSON object: `{"apiKey":"sk-or-v1-...", "provisioningKey":"sk-or-v1-..."}`. Omit `provisioningKey` if you don't have Team/Enterprise access.

### Azure Cost Management Setup

Azure Cost Management integration uses a Service Principal to pull subscription-level cost data. Follow these steps:

1. **Create an App Registration** — In Azure Portal, go to Microsoft Entra ID > App registrations > New registration. Name it (e.g. "Revenium Cost Manager") and accept default settings.
2. **Generate a Client Secret** — Open your app registration, go to Certificates & secrets > New client secret. Copy the **Value** field immediately — not the Secret ID. The Value is only shown once.
3. **Assign Cost Management Reader role** — Go to Subscriptions > your subscription > Access control (IAM) > Add role assignment. Select **Cost Management Reader** at subscription scope and assign it to the app registration.
4. **Enter credentials in Revenium** — From the app registration Overview page, copy the Directory (Tenant) ID and Application (Client) ID. Copy the Subscription ID from the Subscriptions page. Enter all four values in the Revenium provider form.

You can also paste all four fields as a JSON object using the "Paste JSON instead" option:

```json
{
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "clientSecret": "your-client-secret-value",
  "subscriptionId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```

{% hint style="info" %}
**Billing delay:** Azure cost data is delayed by 8–24 hours for EA/MCA agreements and up to 72 hours for Pay-As-You-Go (PAYG) subscriptions. This is an Azure billing pipeline limitation, not a sync issue.
{% endhint %}

{% hint style="warning" %}
**Sovereign clouds not supported:** Azure Government, Azure China, and Azure Germany are not supported. Use a commercial Azure subscription.
{% endhint %}

### LiteLLM

Revenium connects to your existing LiteLLM proxy — it does not host LiteLLM. Make sure your proxy has spend tracking and logging enabled, then provide the proxy's admin API key and base URL. Historical data depth depends on your proxy's retention.

This is a **scheduled sync**, not real-time: Revenium pulls spend and usage from the proxy's admin API on a recurring interval, so it informs reporting rather than live enforcement. What is captured follows what your LiteLLM version records — confirm coverage for the request formats you use with a test transaction after connecting.

For **real-time** metering of the same proxy, register the Revenium proxy callback instead — see [LiteLLM Proxy Setup](/integrations/litellm-proxy-setup). The provider integration reports what your provider **bills**; the callback and client telemetry report what Revenium **meters**. Billed and metered figures are held independently and shown side by side for reconciliation and coverage-health, so connecting the provider integration is always safe alongside real-time metering.

***

## Viewing Your Data

Once a key is authenticated, open the **Provider Dashboard**. Data populates across four primary views:

* **Workspaces** — provider billing and Revenium-metered spend for the selected period, with coverage-health guidance that helps you identify under-metered activity.
* **API Keys** — per-key cost, usage, tokens, and trend, with a key hint (e.g. `sk-ant-api03-Z4C...EQAA`) so you can spot uninstrumented or rogue scripts without exposing the key.
* **Models** — model efficiency: actual cost per 1M tokens (or per-credit, per-image equivalent) so you can compare model price-performance.
* **Management** — workspace naming and organization controls.

The **Management** view lets you rename provider workspaces. Provider-generated names like `proj_abc123xyz` are cryptic; renaming them to `Production API` or `Customer Support Bot` makes cost tracking intuitive across teams. Workspace history is retained — you can view name-change timestamps and revert to any previous name. You can also map workspaces from different providers to the same display name (e.g. an OpenAI project and an Anthropic workspace both renamed to `Customer Support`) to see combined costs in one row.

> **Note on Syncing:** If you have a large historical footprint, it may take a few moments for all data to appear. Click **View Sync Logs** on the Provider dashboard to verify that Revenium is actively processing your records.

***

## Reconcile Billed and Metered Spend

The **Workspaces** view compares two distinct totals:

* **Provider billing** — charges synchronized from connected provider accounts.
* **Revenium-metered spend** — usage observed by Revenium through instrumented traffic.

These totals answer different questions. Provider billing shows what the provider charged; metered spend shows how much of that activity Revenium can associate with instrumented usage. Do not add the totals together. Use them as reconciliation points for the same selected period.

### Read the Reconciliation Summary

The summary presents provider billing and Revenium-metered spend separately. It also highlights providers that are under-metered so you can identify where the metered view does not yet account for billed activity.

### Interpret Coverage Health

Coverage is shown as a named health state rather than an uncapped raw ratio. Read the state as the dashboard's assessment of the current billed-versus-metered relationship, then use the underlying totals to understand the size of the gap.

The health state avoids presenting an unstable raw ratio as precise coverage when the billed amount is very small.

### Resolve Empty and Partial-Data States

The Workspaces view distinguishes between several conditions instead of treating every empty result as the same problem:

* A required integration is missing.
* Data is temporarily unavailable.
* No spend exists for the selected view.
* No active provider rows are available.

Read the state shown before changing filters or connection settings so you respond to the condition the dashboard has identified.

***

## Getting Started

1. Open the **Provider Dashboard**.
2. Select **Workspaces**.
3. Set the provider and time range you want to review.
4. Compare provider billing with Revenium-metered spend in the summary.
5. Read the named coverage-health state.
6. Review any under-metered providers or empty-state guidance.
7. Move to **API Keys**, **Models**, or **Management** when you need a narrower view.

***

## Filtering, Trends & Exports

Each tab supports:

* **Provider filter** — view all providers combined, or drill into a single provider.
* **Usage-type filter** — narrow the dashboard to the type of activity you want to analyze where this filter is available.
* **Time period** — preset ranges or custom date pickers, with current-vs-previous-period trend indicators (↑ red for cost increases, ↓ green for cost decreases).
* **Cost-range filter** — narrow to a specific spend bracket.
* **Search** — by workspace, key hint, or model name.
* **CSV export** — exports respect current filters and sort order.

Keep the same period while comparing provider billing with Revenium-metered spend so both sides of the reconciliation refer to the same window.

The Models tab also surfaces a **Most Efficient Model** badge — the model with the lowest cost per 1M tokens (or per-unit equivalent for image/video/audio) — and an **Avg Tokens/Req** column for providers that report request counts.

***

## OpenAI Image Cost Tracking

For OpenAI, image generation (DALL-E) is tracked separately from text completions. Image costs appear in the Models tab (with per-image cost metrics by DALL-E version), in the Workspaces tab (rolled into workspace totals), and in API Key Analytics (so you can attribute image generation by key). Tracked metrics include cost per image, total image cost, image count, and resolution mix (standard vs HD).

***

## View Sync Logs

The Provider Dashboard's **View Sync Logs** button opens a per-provider sync history. Each entry shows:

* Sync timestamp.
* Provider success/failure status.
* Summary of workspaces, API keys, and usage data retrieved.
* Specific error messages on failed syncs.

### Common Sync Issues

| Issue                  | Likely Cause                                         | Resolution                                                                           |
| ---------------------- | ---------------------------------------------------- | ------------------------------------------------------------------------------------ |
| No data synced         | Wrong key type or invalid credentials                | Re-authenticate via Manage AI Accounts; confirm the key type matches the table above |
| Partial data           | Provider rate limiting                               | Wait and retry; if the issue persists, review the sync log details                   |
| Stale data             | Sync not running                                     | Click **Refresh Data** or check the account's connection state                       |
| Missing provider       | Not connected                                        | Add it via Manage AI Accounts                                                        |
| Delayed Vertex AI data | BigQuery export is batch-processed                   | Expected 24–48h delay; nothing to fix                                                |
| Delayed Azure data     | Azure billing pipeline latency                       | Expected 8–24h delay (EA/MCA) or up to 72h (PAYG); nothing to fix                    |
| Delayed Bedrock data   | Cost Explorer refreshes at least once every 24 hours | Expected up-to-24h delay, including right after connecting; nothing to fix           |

***

## Common Scenarios

**Identifying a cost spike.** Open Workspaces, set the period to "Last 30 days", and review **Current vs Previous Period**. Click the high-growth workspace, then switch to API Key Analytics filtered by that workspace to find the specific keys driving the increase. Switch to Models to see whether the model mix changed.

**Tracking team API key usage.** Use Workspace Management to rename workspaces by team or project, then open API Key Analytics and search by team name. Identify unused keys (0 requests) for rotation or deactivation, and export per-key data for cost allocation.

**Monthly cost reporting.** Set a custom date range to last month, export Workspaces and Models data to CSV, and combine with your budget/alert data for a complete cost picture.

***

## Best Practices

* **Start with the Workspaces view.** It's the fastest way to understand overall spending patterns and surface the high-cost workspaces worth investigating first.
* **Rename workspaces early.** Provider-generated names are cryptic; assign meaningful names as soon as new workspaces appear so the rest of your team has a usable cost view from day one.
* **Check Models weekly.** Model price-performance shifts; the Models view surfaces cheaper alternatives without sacrificing quality.
* **Audit API keys monthly.** Spot rogue keys, idle keys, and keys whose cost has drifted from intent.
* **Combine with alerts.** Use [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) to get notified when spending crosses a threshold so the dashboard isn't the only thing watching.

***

## Related Pages

* [SDK Setup](/integrations/sdk-setup) — connect Revenium-metered usage.
* [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) — receive notifications when spending crosses a threshold.

***

## Frequently Asked Questions

<details>

<summary>Why are provider billing and Revenium-metered spend different?</summary>

Provider billing is synchronized from connected provider accounts. Revenium-metered spend comes from instrumented traffic. A difference indicates that the billed and metered sources do not currently cover the same activity.

</details>

<details>

<summary>Why does the dashboard show a health state instead of a raw percentage?</summary>

Named states keep an unstable raw ratio from being presented as precise coverage. Use the state with the billed and metered totals to interpret the result.

</details>

<details>

<summary>What should I do when the Workspaces view is empty?</summary>

Read the empty-state message first. The view distinguishes a missing integration, temporarily unavailable data, no spend, and no active provider rows so you can respond to the actual condition.

</details>


# API Data Sources

Use this page to understand the data-source records Revenium creates for instrumented applications, provider accounts, and external API sources. For the first OTLP setup, start with [API Data Sources & OTLP](/get-started/quickstart/api-data-sources-and-otlp). For full endpoint details, use [OTLP Integration](/integrations/otlp-integration).

## What a Data Source Represents

A data source identifies where usage data enters Revenium. It can represent:

* An application or service emitting telemetry through an SDK or OTLP exporter.
* A provider account connected for billing and historical usage import.
* A direct API integration that sends metering payloads to Revenium.

The data source gives Revenium a stable place to attach environment, owner, version, and metering identifiers. Those identifiers are then used by logs, traces, charts, alerts, and cost attribution.

## Fields You Will Use

| Field       | Use it for                                                                      |
| ----------- | ------------------------------------------------------------------------------- |
| Source type | Distinguishes AI, provider, API, or other source categories.                    |
| Source name | Human-readable name shown in the product.                                       |
| Environment | Separates production, staging, development, and other contexts.                 |
| Metering ID | Identifier used when configuring SDKs, agents, middleware, or external sources. |
| Version     | Optional version marker for source-level tracking.                              |

## Where To Go Next

| Need                                       | Page                                                         |
| ------------------------------------------ | ------------------------------------------------------------ |
| Create or manage API keys                  | [API Key Permissions](/integrations/api-key-permissions)     |
| Add metering to app code                   | [SDK Setup](/integrations/sdk-setup)                         |
| Send OpenTelemetry spans, logs, or metrics | [OTLP Integration](/integrations/otlp-integration)           |
| Connect provider billing data              | [Provider Integrations](/integrations/provider-integrations) |
| Validate direct API payloads               | [API Reference](https://revenium.readme.io)                  |


# OTLP Integration

Revenium accepts OTLP (OpenTelemetry Protocol) data directly from your instrumented applications. If your app already emits telemetry via an OTLP exporter—using LangChain, the OpenAI Python SDK with OTel instrumentation, or your own custom spans—you can point it at Revenium with a few lines of configuration and start seeing AI usage data immediately.

This page covers Revenium-specific configuration. It assumes you already understand OTLP and have an exporter set up.

***

## Endpoints

Revenium accepts both OTLP/HTTP and OTLP/gRPC.

### OTLP/HTTP

| Path                                               | Accepts                                          |
| -------------------------------------------------- | ------------------------------------------------ |
| `https://api.revenium.ai/meter/v2/otlp/v1/traces`  | Traces (JSON or protobuf)                        |
| `https://api.revenium.ai/meter/v2/otlp/v1/logs`    | Logs (JSON or protobuf)                          |
| `https://api.revenium.ai/meter/v2/otlp/v1/metrics` | Metrics (JSON or protobuf)                       |
| `https://api.revenium.ai/meter/v2/otlp`            | Unified (traces + logs + metrics in one request) |

Both `application/json` and `application/x-protobuf` content types are accepted.

### OTLP/gRPC

| Host              | Port   | Service                                               |
| ----------------- | ------ | ----------------------------------------------------- |
| `api.revenium.ai` | `4317` | `opentelemetry.proto.collector.trace.v1.TraceService` |

The gRPC endpoint accepts traces only. For logs and metrics, use the HTTP endpoints.

{% hint style="warning" %}
**gRPC authentication note.** The gRPC path accepts the API key as either `x-api-key` or `Authorization: Bearer <key>` metadata. It cannot use `OTEL_RESOURCE_ATTRIBUTES=revenium.api_key=...` because authentication happens before the trace payload is deserialized.
{% endhint %}

### Direct Metering Endpoints

If you are not using OTLP, Revenium also accepts direct metering payloads:

| Endpoint                                                                      | Purpose                                 |
| ----------------------------------------------------------------------------- | --------------------------------------- |
| `https://api.revenium.ai/meter/v2/ai/completions`                             | LLM completions, tokens, and cost       |
| `https://api.revenium.ai/meter/v2/tool/events`                                | Agent tool executions                   |
| `https://api.revenium.ai/meter/v2/ai/images`                                  | Image generation usage                  |
| `https://api.revenium.ai/meter/v2/ai/audio`                                   | Audio generation or transcription usage |
| `https://api.revenium.ai/meter/v2/ai/video`                                   | Video generation usage                  |
| `https://api.revenium.ai/profitstream/v2/api/jobs/{jobId}/outcome?teamId=...` | Terminal job outcomes                   |

The `/meter/v2/...` endpoints are metering-ingest endpoints for usage events. The `/profitstream/v2/api/...` endpoint is the Jobs API used to close an already-metered job with its terminal business outcome. Use a metering key (`rev_mk_*`) for ingest-only calls and a write-scope key (`rev_sk_*`) when reporting outcomes or managing Jobs resources.

For choosing between SDKs, OTLP, and direct API calls, see [Integration Options](/integrations/integrations).

***

## Authentication

For both OTLP/HTTP and OTLP/gRPC, your Revenium API key can be sent as either `x-api-key` or `Authorization: Bearer`. OTLP ingest requires a metering key (`rev_mk_*`) — if your workflow also reports business outcomes or manages Revenium resources, use a write-scope key (`rev_sk_*`) for those calls; see [API Key Permissions](/integrations/api-key-permissions).

```
Authorization: Bearer rev_mk_your_tenant_yourkey
```

or

```
x-api-key: rev_mk_your_tenant_yourkey
```

For frameworks or SDKs that cannot set custom headers (e.g., some CLI tools), you can pass the API key as an OTLP resource attribute instead:

```bash
export OTEL_RESOURCE_ATTRIBUTES="revenium.api_key=rev_mk_your_tenant_yourkey"
```

This travels inside the encrypted OTLP payload body and is secure over TLS. Note: this fallback is **not** available for OTLP/gRPC (interceptors run before message deserialization on the gRPC path).

Authentication priority is:

1. `x-api-key: <key>` HTTP header
2. `Authorization: Bearer <key>` header
3. `OTEL_RESOURCE_ATTRIBUTES=revenium.api_key=<key>` for OTLP/HTTP only

Headers always win over the resource attribute. If no key is available in either place, the request is rejected before metering.

You can find your API key in the Revenium app under **Connections → SDK Setup**.

***

## Quick Start

### 1. Configure your OTLP exporter

Set the exporter endpoint and auth header. The exact env vars depend on your SDK, but the standard OpenTelemetry environment variables work with all OTel SDKs:

```bash
export OTEL_EXPORTER_OTLP_ENDPOINT=https://api.revenium.ai/meter/v2/otlp
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer rev_mk_your_tenant_yourkey"
```

If your framework uses separate endpoint vars for signals:

```bash
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://api.revenium.ai/meter/v2/otlp/v1/traces
export OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://api.revenium.ai/meter/v2/otlp/v1/logs
export OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://api.revenium.ai/meter/v2/otlp/v1/metrics
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer rev_mk_your_tenant_yourkey"
```

{% hint style="warning" %}
**Python SDK note:** The Python OpenTelemetry SDK requires header values in `OTEL_EXPORTER_OTLP_HEADERS` to be percent-encoded. Use `Bearer%20` instead of `Bearer` (with a space):

```bash
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20rev_mk_your_tenant_yourkey"
```

Other SDKs (Node.js, Go, Java) accept the unencoded space. If data is not arriving from a Python app, check for a "Header format invalid" error and switch to the percent-encoded form.
{% endhint %}

### 2. Send a trace

Run your application normally. The OTel instrumentation in your app creates spans when AI calls are made, and the exporter sends them to Revenium.

Minimal OTLP/JSON trace shape:

```json
{
  "resourceSpans": [{
    "resource": {
      "attributes": [
        {"key": "service.name", "value": {"stringValue": "support-bot"}},
        {"key": "revenium.product.name", "value": {"stringValue": "support-bot"}}
      ]
    },
    "scopeSpans": [{
      "scope": {"name": "opentelemetry.instrumentation.anthropic"},
      "spans": [{
        "traceId": "...",
        "spanId": "...",
        "name": "claude_client.messages.create",
        "attributes": [
          {"key": "gen_ai.provider.name", "value": {"stringValue": "anthropic"}},
          {"key": "gen_ai.request.model", "value": {"stringValue": "claude-sonnet-4-6"}},
          {"key": "gen_ai.usage.input_tokens", "value": {"intValue": 150}},
          {"key": "gen_ai.usage.output_tokens", "value": {"intValue": 75}},
          {"key": "revenium.subscriber.id", "value": {"stringValue": "user-12345"}}
        ]
      }]
    }]
  }]
}
```

### 3. See it in Revenium

Go to **System & Transaction Logs** or **Trace Analytics**. If the span contained recognized GenAI attributes (see below), you'll see token counts, model, provider, and cost data populated automatically.

***

## Supported Frameworks and SDKs

Revenium auto-detects the source based on resource attributes and instrumentation scope names. No special configuration in Revenium is required—just point your exporter at the endpoint.

### Python: opentelemetry-instrumentation-openai

```python
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

tracer_provider = TracerProvider()
exporter = OTLPSpanExporter(
    endpoint="https://api.revenium.ai/meter/v2/otlp/v1/traces",
    headers={"Authorization": "Bearer rev_mk_your_tenant_yourkey"},
)
tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
OpenAIInstrumentor().instrument(tracer_provider=tracer_provider)
```

### Python: opentelemetry-instrumentation-anthropic

```python
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter

tracer_provider = TracerProvider()
exporter = OTLPSpanExporter(
    endpoint="https://api.revenium.ai/meter/v2/otlp/v1/traces",
    headers={"Authorization": "Bearer rev_mk_your_tenant_yourkey"},
)
tracer_provider.add_span_processor(BatchSpanProcessor(exporter))
AnthropicInstrumentor().instrument(tracer_provider=tracer_provider)
```

### Python: LangChain via OpenInference or OpenLLMetry

Both [OpenInference](https://github.com/Arize-ai/openinference) and [OpenLLMetry](https://github.com/traceloop/openllmetry) emit GenAI semantic convention spans. Configure the OTLP exporter as shown above; Revenium picks them up automatically.

### Node.js: @opentelemetry/instrumentation-openai

```javascript
const { NodeSDK } = require('@opentelemetry/sdk-node');
const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-http');
const { OpenAIInstrumentation } = require('@opentelemetry/instrumentation-openai');

const sdk = new NodeSDK({
  traceExporter: new OTLPTraceExporter({
    url: 'https://api.revenium.ai/meter/v2/otlp/v1/traces',
    headers: { 'Authorization': 'Bearer rev_mk_your_tenant_yourkey' },
  }),
  instrumentations: [new OpenAIInstrumentation()],
});

sdk.start();
```

### Go SDK (gRPC)

```go
import (
    "context"
    "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    "google.golang.org/grpc/credentials"
)

ctx := context.Background()
exporter, _ := otlptracegrpc.New(ctx,
    otlptracegrpc.WithEndpoint("api.revenium.ai:4317"),
    otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")),
    otlptracegrpc.WithHeaders(map[string]string{
        "Authorization": "Bearer rev_mk_your_tenant_yourkey",
    }),
)
```

### OpenTelemetry Collector

If you're already running an OTel Collector, add Revenium as an exporter:

```yaml
exporters:
  otlphttp/revenium:
    endpoint: https://api.revenium.ai/meter/v2/otlp
    headers:
      Authorization: "Bearer rev_mk_your_tenant_yourkey"

service:
  pipelines:
    traces:
      exporters: [otlphttp/revenium]
    logs:
      exporters: [otlphttp/revenium]
```

***

## What Gets Captured Automatically

Revenium reads [OpenTelemetry GenAI semantic conventions](https://opentelemetry.io/docs/specs/semconv/gen-ai/) from your spans and log records. If your instrumentation library follows the spec, these fields populate automatically—no extra code required.

### Token Counts

| GenAI Attribute                            | Revenium Field        | Notes                                                    |
| ------------------------------------------ | --------------------- | -------------------------------------------------------- |
| `gen_ai.usage.input_tokens`                | Input tokens          | Also accepts deprecated `gen_ai.usage.prompt_tokens`     |
| `gen_ai.usage.output_tokens`               | Output tokens         | Also accepts deprecated `gen_ai.usage.completion_tokens` |
| `gen_ai.usage.cache_read_input_tokens`     | Cache read tokens     | Also accepts `gen_ai.usage.cache_read_tokens`            |
| `gen_ai.usage.cache_creation_input_tokens` | Cache creation tokens | Also accepts `gen_ai.usage.cache_creation_tokens`        |

### Model and Provider

| GenAI Attribute         | Revenium Field  | Notes                                           |
| ----------------------- | --------------- | ----------------------------------------------- |
| `gen_ai.response.model` | Model           | Preferred; falls back to `gen_ai.request.model` |
| `gen_ai.provider.name`  | Provider        | Also accepts deprecated `gen_ai.system`         |
| `gen_ai.request.model`  | Model (request) | Used when response model is absent              |

### Operation Type and Finish Reason

| GenAI Attribute                  | Revenium Field | Values                                                                                   |
| -------------------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `gen_ai.operation.name`          | Operation type | `chat` → Chat; `embeddings` → Embed; `text_completion` → Chat; `generate_content` → Chat |
| `gen_ai.response.finish_reasons` | Stop reason    | Array; Revenium uses the first element — see mapping table below                         |

**Finish reason mapping:**

| `gen_ai.response.finish_reasons` value | Revenium stop reason |
| -------------------------------------- | -------------------- |
| `stop`, `end_turn`                     | End                  |
| `max_tokens`, `length`                 | Token Limit          |
| `stop_sequence`                        | End Sequence         |
| `content_filter`                       | Error                |
| `tool_calls`, `function_call`          | End                  |
| *(any other value)*                    | End                  |

### Request Parameters

| GenAI Attribute              | Revenium Field     | Notes                                           |
| ---------------------------- | ------------------ | ----------------------------------------------- |
| `gen_ai.request.temperature` | Temperature        | Standard OTel attribute; captured automatically |
| `gen_ai.response.id`         | System fingerprint | Response identifier from the model provider     |

### Timing and Errors

Span start/end nanosecond timestamps (`startTimeUnixNano`, `endTimeUnixNano`) are used to populate request time, response time, and duration. Error details are read from `exception.message` (primary) and `error.type` (fallback). HTTP status codes are read from `http.response.status_code`.

### Infrastructure Context

| Standard OTel Attribute  | Revenium Field |
| ------------------------ | -------------- |
| `deployment.environment` | Environment    |
| `cloud.region`           | Region         |

### Span Hierarchy

`traceId`, `spanId`, and `parentSpanId` from spans are mapped to Revenium's trace, transaction, and parent transaction fields respectively. This powers the Trace Analytics dependency tree and waterfall visualizations.

{% hint style="info" %}
Revenium skips spans with `gen_ai.operation.name` of `execute_tool`, `invoke_agent`, or `create_agent` — these are orchestration spans, not LLM calls. Only spans that represent actual model invocations are metered.
{% endhint %}

***

## Attribute Precedence and Source Detection

Revenium resolves attribution values in this order:

```
span attribute > resource attribute > computed default
```

| Category               | Attributes                                                                                | Span override | Resource default |
| ---------------------- | ----------------------------------------------------------------------------------------- | ------------- | ---------------- |
| System fingerprint     | `revenium.system.fingerprint`                                                             | Yes           | Yes              |
| Organization / product | `revenium.organization.name`, `revenium.product.name`                                     | Yes           | Yes              |
| Subscriber             | `revenium.subscriber.id`, `revenium.subscriber.email`, `revenium.subscriber.credential.*` | Yes           | Yes              |
| Agent and job          | `revenium.agent.name`, `revenium.task.type`, `revenium.trace.type`, `revenium.job.id`     | Yes           | Yes              |
| Squad                  | `revenium.squad.id`, `revenium.squad.name`, `revenium.squad.role`                         | Yes           | Yes              |
| Operational            | `revenium.operation.subtype`, `revenium.retry.number`, `revenium.request.stream`          | Yes           | Yes              |

Revenium identifies GenAI spans using this detection chain:

1. Span attribute `gen_ai.provider.name`
2. Span attribute `gen_ai.system`
3. Instrumentation scope names such as `gen_ai.*`, `openai.*`, `anthropic.*`, or `opentelemetry.instrumentation.*`
4. Resource-level GenAI attributes
5. If none match, the span is logged but not metered

***

## Deep Attribution with `revenium.*` Attributes

Standard OTel tells you *what happened* — which model was called, how many tokens were used. `revenium.*` attributes tell Revenium *why it happened and who it happened for*. This is what enables per-customer, per-product, per-agent, and per-job cost attribution that goes beyond what the OTel spec captures.

Set these on spans or log records (record-level attributes take precedence over resource-level attributes, so you can set defaults at the resource level and override on individual spans).

### System Fingerprint

{% hint style="info" %}
`revenium.system.fingerprint` is one of Revenium's most powerful attribution tools. It lets you tag each AI call with an identifier that represents *what configuration produced it* — your system prompt version, your prompt template ID, your agent configuration hash, or any other identifier you use to distinguish one variant from another.

This is how you answer questions like: "Which version of my system prompt is more expensive?" or "Did my prompt optimization actually reduce costs?" Standard OTel has no equivalent.
{% endhint %}

| Attribute                     | Revenium Field     | Notes                                                                                       |
| ----------------------------- | ------------------ | ------------------------------------------------------------------------------------------- |
| `gen_ai.response.id`          | System fingerprint | Populated automatically if your provider returns a response ID                              |
| `revenium.system.fingerprint` | System fingerprint | Use this to set your own fingerprint — overrides `gen_ai.response.id` when both are present |

```python
span.set_attribute("revenium.system.fingerprint", "system-prompt-v3-2025-03-12")
```

Use any value that uniquely identifies the configuration: a version string, a git SHA, a prompt template ID, or a hash of your system prompt content.

### Organization and Product

| Attribute                    | Revenium Field | Example                 |
| ---------------------------- | -------------- | ----------------------- |
| `revenium.organization.name` | Organization   | `"acme-corp"`           |
| `revenium.product.name`      | Product        | `"document-summarizer"` |
| `revenium.subscription.id`   | Subscription   | `"enterprise-plan-q1"`  |

### Subscribers and Users

| Attribute                              | Revenium Field   | Example              |
| -------------------------------------- | ---------------- | -------------------- |
| `revenium.subscriber.id`               | Subscriber ID    | `"user-12345"`       |
| `revenium.subscriber.email`            | Subscriber email | `"user@example.com"` |
| `revenium.subscriber.credential.name`  | Credential name  | `"api-key-prod"`     |
| `revenium.subscriber.credential.value` | Credential value | `"pk-abc123"`        |

### Agents and Agentic Workflows

| Attribute                   | Revenium Field   | Example                       |
| --------------------------- | ---------------- | ----------------------------- |
| `revenium.agent.name`       | Agent            | `"support-agent-v2"`          |
| `revenium.task.type`        | Task type        | `"summarize"`                 |
| `revenium.trace.type`       | Trace type       | `"rag-pipeline"`              |
| `revenium.trace.name`       | Trace name       | `"support-ticket-resolution"` |
| `revenium.transaction.name` | Transaction name | `"retrieve-context"`          |

### Squads (Multi-Agent Teams)

| Attribute             | Revenium Field | Example                   |
| --------------------- | -------------- | ------------------------- |
| `revenium.squad.id`   | Squad ID       | `"squad-billing"`         |
| `revenium.squad.name` | Squad name     | `"Billing Support Squad"` |
| `revenium.squad.role` | Role in squad  | `"orchestrator"`          |

### Agentic Jobs

| Attribute              | Revenium Field | Example                |
| ---------------------- | -------------- | ---------------------- |
| `revenium.job.id`      | Job ID         | `"job-20250312-001"`   |
| `revenium.job.name`    | Job name       | `"nightly-report-gen"` |
| `revenium.job.type`    | Job type       | `"batch"`              |
| `revenium.job.version` | Job version    | `"2.1.0"`              |

### Other Fields

| Attribute                    | Revenium Field    | Notes                                   |
| ---------------------------- | ----------------- | --------------------------------------- |
| `revenium.operation.subtype` | Operation subtype | Free-form sub-classification            |
| `revenium.retry.number`      | Retry number      | Integer; useful for tracking retry cost |
| `revenium.request.stream`    | Is streamed       | Boolean                                 |
| `revenium.middleware.source` | Middleware source | Identifies the SDK or integration layer |

### Setting Attribution Attributes (Python Example)

```python
from opentelemetry import trace

tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("llm-call") as span:
    span.set_attribute("revenium.organization.name", "acme-corp")
    span.set_attribute("revenium.product.name", "support-bot")
    span.set_attribute("revenium.agent.name", "tier1-support-agent")
    span.set_attribute("revenium.task.type", "classify-ticket")
    span.set_attribute("revenium.subscriber.id", "user-98765")
    span.set_attribute("revenium.system.fingerprint", "system-prompt-v3")
    # ... make your LLM call
```

You can also set defaults at the resource level so they apply to all spans from your service, and override on individual spans where needed:

```python
from opentelemetry.sdk.resources import Resource

resource = Resource(attributes={
    "service.name": "support-bot",
    "revenium.organization.name": "acme-corp",
    "revenium.product.name": "support-bot",
})
```

Record-level (span) attributes always win over resource-level attributes when the same key is set at both levels.

***

## Troubleshooting

**Data not appearing in Revenium**

Check that:

1. Your API key starts with `rev_mk_` and is in the correct format (`rev_mk_<tenant>_<secret>`).
2. Your spans include at least one of the following so Revenium can route them to the correct mapper:
   * `gen_ai.provider.name` or `gen_ai.system` attribute (resource-level or span-level)
   * An instrumentation scope name starting with `gen_ai`, `openai`, `anthropic`, `opentelemetry.instrumentation.openai`, or `opentelemetry.instrumentation.anthropic`
3. The exporter endpoint URL is correct and includes the full path (`/v2/otlp/v1/traces`, not `/v2/otlp`), unless your SDK sends all signals to a single base URL—in that case, use `/v2/otlp`.

**Tokens showing as zero**

Verify your instrumentation library emits `gen_ai.usage.input_tokens` and `gen_ai.usage.output_tokens` (or their deprecated equivalents `gen_ai.usage.prompt_tokens` / `gen_ai.usage.completion_tokens`) as numeric attributes on the span.

**Tool call and agent orchestration spans are not appearing**

This is expected behavior. Revenium filters out `execute_tool`, `invoke_agent`, and `create_agent` spans because they are not LLM calls. Only spans that represent actual model invocations produce metering records.

***

## Related Documentation

* [Integration Options for AI Metering](/integrations/integrations) — SDK and direct API options
* [AI Coding Data Reference](/track-and-control-costs/analyze-ai-tooling-spend/ai-coding-data-reference) — Complete list of data points collected from AI coding assistants
* [Debug Logs & Traces](/optimize-performance/debug-logs-and-traces) — Visualizing trace hierarchies, transaction details, and costs
* [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) — Set thresholds on usage and cost


# Context7 and AI Docs Access

Access Revenium documentation from AI coding assistants via Context7 or llms.txt.

Use this page when you want an AI assistant or coding agent to retrieve Revenium documentation, schemas, and API guidance while it works. If you want an agent to query or operate Revenium itself, use [MCP Server](/integrations/mcp-server).

## Context7 (Recommended)

[Context7](https://context7.com) provides automatic documentation retrieval via MCP. Your AI agent pulls relevant Revenium docs on demand — works with any MCP-compatible tool (Claude Code, Cursor, Windsurf, Continue, Cline, GitHub Copilot).

Add the Context7 MCP server to your agent's configuration:

```json
{
  "mcpServers": {
    "context7": {
      "command": "npx",
      "args": ["-y", "@upstash/context7-mcp@latest"]
    }
  }
}
```

Refer to your tool's MCP documentation for the configuration file location.

### Revenium Libraries on Context7

**Documentation:**

| Library            | Content                                                   |
| ------------------ | --------------------------------------------------------- |
| **API Reference**  | Complete REST API reference with request/response schemas |
| **Knowledge Base** | Guides, quickstarts, and platform concepts                |

**SDKs and Tools:**

| Library             | Content                                                          |
| ------------------- | ---------------------------------------------------------------- |
| **Python SDK**      | Unified Python middleware for OpenAI, Anthropic, Google, LiteLLM |
| **Node Middleware** | Unified TypeScript middleware for all supported providers        |
| **MCP Server**      | Zero-code AI metering via Model Context Protocol                 |
| **Claude Code SDK** | Claude Code telemetry export and usage tracking                  |
| **CLI**             | Command-line interface for the Revenium platform                 |

When querying Context7, use `revenium` as the search term to find these libraries.

***

## llms.txt

For browser-based AI tools (ChatGPT, Claude.ai, Gemini) or when MCP is unavailable, paste this URL into your conversation:

[**https://revenium.readme.io/llms.txt**](https://revenium.readme.io/llms.txt)

***

## OpenAPI Specs

Full OpenAPI (OAS) documents are available for download at:

[**Revenium OpenAPI Spec Downloads**](https://revenium.readme.io/reference/llm-agent-friendly-api-specs-for-revenium)

{% hint style="warning" %}
These are large files intended for code generation tools and schema validation, not for pasting into AI chat. For AI agent access to Revenium APIs, use Context7 or llms.txt instead.
{% endhint %}

***

## Related

* [Integration Options](/integrations/integrations) — choose the right setup path
* [MCP Server](/integrations/mcp-server) — connect MCP-compatible agents to Revenium
* [OTLP Integration](/integrations/otlp-integration) — OTLP endpoints and GenAI attribute mapping

### Metering API Reference

| Modality    | API Reference                                                                   |
| ----------- | ------------------------------------------------------------------------------- |
| Completions | [Meter AI Completion](https://revenium.readme.io/reference/meter_ai_completion) |
| Images      | [Meter AI Images](https://revenium.readme.io/reference/meter_ai_images)         |
| Video       | [Meter AI Video](https://revenium.readme.io/reference/meter_ai_video)           |
| Audio       | [Meter AI Audio](https://revenium.readme.io/reference/meter_ai_audio)           |


# MCP Server

The Revenium MCP Server connects AI agents to your Revenium account for cost intelligence, entity management, metering, alert governance, and operational diagnostics — all through natural conversation

The Revenium MCP Server surfaces your entire Revenium account as native tools inside any MCP-compatible AI assistant. Cost analysis, anomaly detection, budget alerts, customer and product management, metering, ROI tracking, and system diagnostics are all available through plain-language requests — no dashboards, no manual queries, no context-switching.

This is MCP-first integration: every Revenium capability that an operator or developer needs is accessible from the assistant's context, so cost intelligence and governance become part of every conversation.

***

### <i class="fa-route">:route:</i> Connect Your MCP Server

Choose the connection path that fits your environment:

| Connection model               | Use this when                                                                                          | Start here                                                      |
| ------------------------------ | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| **Hosted OAuth (recommended)** | You want zero-install setup with per-user authentication and no shared API keys.                       | [Connect with OAuth](#connect-with-your-revenium-account-oauth) |
| **Local with API key**         | You need a local stdio server for CI, service accounts, or IDE setups that only support local servers. | [Run locally](#run-it-locally-with-an-api-key)                  |

#### Connect with Your Revenium Account (OAuth)

The fastest way to get started is the hosted MCP server. There is nothing to install and no API key to manage — you sign in with your Revenium account and the connection is ready:

```
https://mcp.revenium.ai/mcp
```

**Claude (web and desktop):** open **Settings > Connectors > Add custom connector**, paste the URL above, and complete the sign-in when your browser opens. Your assistant now has the full Revenium toolset.

**Claude Code:**

```bash
claude mcp add --transport http revenium https://mcp.revenium.ai/mcp
```

Then run `/mcp`, select **revenium**, and choose **Authenticate** — your browser opens to complete the sign-in.

Any MCP client that supports remote servers with OAuth authorization can connect the same way — see the [compatibility table](#supported-mcp-clients) below for tested clients.

The hosted connector serves the production environment. To point the MCP server at any other environment, use the local install below with that environment's API key and base URL.

{% hint style="info" %}
The hosted server authenticates every request with a short-lived OAuth token tied to your sign-in — no long-lived API key is created, stored, or shared.
{% endhint %}

#### Run It Locally with an API Key

You can also run the MCP server yourself and authenticate with an API key instead of OAuth — useful for CI environments, service accounts, and IDE setups that only support local stdio servers. Install `uv` (`pip install uv`) and add this to your MCP client config:

```json
{
  "mcpServers": {
    "revenium": {
      "command": "uvx",
      "args": ["revenium-mcp"],
      "env": {
        "REVENIUM_API_KEY": "rev_sk_your_api_key_here"
      }
    }
  }
}
```

The MCP server needs a write-scope key (`rev_sk_*`) because it both reads Revenium data and can create alerts and modify resources — a metering-only key (`rev_mk_*`) will be rejected. See [API Key Permissions](/integrations/api-key-permissions) for the full key tier reference.

The MCP server is open source. The `uvx` install above runs it locally per developer, or your team can deploy a shared instance using the Dockerfile and docker-compose templates in the [Revenium MCP server repository](https://github.com/revenium/revenium-mcp). For Kubernetes deployments, see [Rancher Prime Integration](/integrations/mcp-server/rancher-prime). The repository also covers Claude Code shortcuts, IDE-specific install variants, troubleshooting, and the full configuration reference.

{% hint style="info" %}
This locally-run, open-source server is a separate thing from the hosted connector at `https://mcp.revenium.ai/mcp` described above — same underlying capabilities, but you install and manage this one yourself, authenticated with your own API key rather than OAuth sign-in.
{% endhint %}

***

### <i class="fa-desktop">:desktop:</i> Supported MCP Clients

| Client                | Transport | Connection method                                                                                                                | Status     |
| --------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| **Claude Web**        | HTTP      | Settings > Connectors > Add custom connector                                                                                     | Verified   |
| **Claude Desktop**    | HTTP      | Settings > Connectors > Add custom connector                                                                                     | Verified   |
| **Claude Code (CLI)** | HTTP      | `claude mcp add --transport http revenium https://mcp.revenium.ai/mcp`                                                           | Verified   |
| **Cursor**            | HTTP      | Settings > MCP > Add server (paste the hosted URL)                                                                               | Verified   |
| **Windsurf**          | stdio     | Local install via `uvx` in MCP client config                                                                                     | Verified   |
| **VS Code (Copilot)** | stdio     | Local install via `uvx` in MCP client config                                                                                     | Verified   |
| **Any MCP client**    | HTTP      | Point at `https://mcp.revenium.ai/mcp` with OAuth; or use the local stdio install for clients that do not support remote servers | Compatible |

{% hint style="info" %}
The [Revenium MCP server repository](https://github.com/revenium/revenium-mcp) maintains IDE-specific installation instructions and troubleshooting guides for each client.
{% endhint %}

***

### <i class="fa-buildings">:buildings:</i> Multi-Tenant by Design

The hosted MCP server is fully multi-tenant. Your Revenium team and tenant are resolved from your sign-in — not from server configuration — so:

* **Each person connects as themselves.** Teammates add the same connector URL and sign in with their own Revenium credentials; there are no shared secrets to distribute or rotate.
* **Data access is scoped to your team.** Every tool call runs in the context of the team associated with your account, and you only see that team's costs, products, subscriptions, customers, and alerts.
* **Access follows your account.** Deactivating a user in Revenium ends their MCP access with it — nothing else to clean up.

***

### <i class="fa-chart-mixed">:chart-mixed:</i> What You Can Do

Once connected, the MCP server exposes a set of tools organized around five operational areas. You interact with them through natural language — the assistant picks the right tool and action for each request.

#### Cost Intelligence and Analytics

The MCP server gives your assistant full access to Revenium's cost analytics engine. Ask for spend breakdowns by any dimension — provider, model, customer, agent, API key, or tool — over any time window from the last hour to the last 30 days.

* "Why did my costs spike yesterday?"
* "Show me a cost breakdown by model for the last 7 days"
* "Which customers are driving the most spend this month?"
* "What's my agent-level cost breakdown for the past 24 hours?"

**Anomaly detection** surfaces abnormal spend patterns across all dimensions, with configurable sensitivity and dollar-impact thresholds. **Budget alerts** cover three trigger types — spike detection for real-time monitoring, cumulative usage for period-based budgets, and relative change for week-over-week or month-over-month trend shifts — with delivery to Slack or email.

* "Find cost anomalies in the last 7 days with at least $50 impact"
* "Set a daily budget alert at $500 that notifies Slack"
* "Create a relative-change alert that fires when weekly spend increases by 20%"
* "Disable all alerts temporarily"

**AI Insights** triggers Revenium's recommendation engine, which analyzes your usage and returns findings across waste, provider concentration risk, reliability issues, and efficiency opportunities.

* "Run an AI insights analysis and show me the findings"
* "List my previous insight runs"

**Cost Controls** let your assistant create and manage the enforcement side of Guardrails — rules that block a request at the call site rather than just notifying after the fact.

* "Create a cost control that blocks any single request over $10"
* "Show me my active cost control rules"

#### Entity Management

The MCP server is not read-only — it is a full management layer for Revenium entities. Your assistant can create, read, update, and delete customers, products, subscriptions, data sources, metering elements, and tools, all through conversation.

**Customers** are the organizations, subscribers, users, and teams that consume your AI-powered services. Manage their full lifecycle and analyze their relationships.

* "List all my customers"
* "Create a customer called Acme Corp"
* "Show me the relationships for customer X"

**Products** represent the APIs, services, or AI capabilities you are billing for. Create them from structured data, natural language, or templates with pricing models attached.

* "Create a product called Summarizer API at $0.01 per request"
* "Show me available product templates"
* "What pricing models are supported?"

**Subscriptions** connect customers to products. Create, search, cancel, and manage credentials for each subscription.

* "Subscribe Acme Corp to the Summarizer API"
* "List all active subscriptions"
* "Cancel subscription X"

**Data sources** represent the API keys and ingestion endpoints that route metering events to the right product.

* "Create a new data source for the Summarizer API"
* "Validate my data source configuration"

**Metering elements** define the meters — the specific dimensions and units — that metering events record against. Create them from templates and assign them to data sources.

* "List available metering element templates"
* "Create a token-count meter and assign it to source X"

**Tool Registry** manages the tools your AI agents use, with pricing models, cost tracking by agent and provider, success rates, and latency metrics.

* "Register a new tool called Document Parser at $0.005 per call"
* "Show me cost breakdown by agent for my tools"
* "What's the success rate for tool X?"

**Agents and squads** cover the agents registered to your account and how they're grouped into squads, so you can manage them and review squad-level activity through conversation.

* "List my registered agents"
* "Show me activity for the support squad"

#### Metering and Transactions

Submit AI transaction events directly through the assistant — individually or in batch. The metering tools handle field validation, cost estimation, model lookup, and provider verification before submission.

* "Submit a metering event for an OpenAI GPT-4o call with 1500 input tokens and 500 output tokens"
* "Estimate the cost of a Claude Sonnet call with 10K input tokens"
* "Look up supported AI models"

For integration testing, the metering field validation tool generates test data, runs validation suites, and analyzes field mapping to verify that your metering pipeline is correctly configured before going to production.

* "Generate test metering data for my setup"
* "Run a validation suite against my field mapping"

#### Jobs and ROI

Track the performance and return on investment of individual AI agent jobs. Measure conversion funnels, calculate ROI across job types, and report business outcomes back to Revenium so cost data connects to the value it produced.

* "Show me ROI for my agent jobs this month"
* "What's my conversion funnel for job type X?"
* "Report a successful outcome for job Y with $500 revenue"

#### Workflows

For complex operations that span multiple tools, the workflow engine coordinates multi-step processes through guided templates. Instead of issuing five separate commands, describe what you need and the assistant walks through each step.

* "Onboard a new customer with a product, subscription, and budget alert"
* "Show me available workflow templates"

#### System and Diagnostics

The diagnostic tools validate your environment configuration, run health checks, analyze operation logs, and debug auto-discovery issues. Use them during initial setup or when troubleshooting connectivity.

* "Run a system health check"
* "Show me my environment variables and their status"
* "Search logs for errors in the last hour"
* "What's my onboarding status?"

The tool introspection system lets the assistant describe its own capabilities — list every available tool, inspect individual tool metadata, and discover supported actions and parameters.

* "List all available Revenium tools"
* "What actions does manage\_alerts support?"

#### Setup Assistants

Guided setup flows for email verification and Slack integration walk through configuration step by step, checking prerequisites and validating connectivity at each stage.

* "Help me set up my email for alert notifications"
* "Guide me through Slack integration setup"

***

### <i class="fa-clipboard">:clipboard:</i> Available Tools

| Tool                               | Category          | What it does                                                                               |
| ---------------------------------- | ----------------- | ------------------------------------------------------------------------------------------ |
| `business_analytics_management`    | Cost Intelligence | Spend breakdowns by provider, model, customer, agent, API key, and tool; anomaly detection |
| `manage_alerts`                    | Cost Intelligence | Budget alerts (spike, cumulative, relative-change) with Slack and email delivery           |
| `manage_ai_insights`               | Cost Intelligence | AI recommendation engine — trigger runs, review findings, submit feedback                  |
| `manage_cost_controls`             | Cost Intelligence | Create and manage Cost Control (enforcement) Guardrail rules                               |
| `manage_customers`                 | Entity Management | Customer lifecycle — organizations, subscribers, users, teams                              |
| `manage_products`                  | Entity Management | Product creation with pricing models, templates, and natural language support              |
| `manage_subscriptions`             | Entity Management | Connect customers to products; credential management                                       |
| `manage_sources`                   | Entity Management | Data source and API key configuration                                                      |
| `manage_metering_elements`         | Entity Management | Meter definitions — templates, assignment to data sources                                  |
| `manage_tools`                     | Entity Management | Tool Registry — pricing, cost tracking, success rates, latency                             |
| `manage_agents`                    | Entity Management | Registered agents and squad-level activity                                                 |
| `manage_metering`                  | Metering          | AI transaction submission (single and batch), cost estimation, model lookup                |
| `manage_metering_field_validation` | Metering          | Test data generation, validation suites, field mapping analysis                            |
| `manage_jobs`                      | Jobs and ROI      | Job performance, ROI calculation, conversion funnels, outcome reporting                    |
| `manage_workflows`                 | Workflows         | Multi-step cross-tool operations via guided templates                                      |
| `system_diagnostics`               | System            | Environment validation, health checks, log analysis, operation debugging                   |
| `configuration_status`             | System            | Onboarding status, auto-discovery, system health                                           |
| `tool_introspection`               | System            | Self-describing tool metadata and capability discovery                                     |
| `verify_email_setup`               | Setup             | Email configuration verification and guided setup                                          |
| `slack_setup_assistant`            | Setup             | Guided Slack integration configuration                                                     |

{% hint style="success" %}
All tools are available immediately after connecting — no additional configuration required.
{% endhint %}

***

### <i class="fa-forward">:forward:</i> What to Do Next

1. **Connect** using the [OAuth setup](#connect-with-your-revenium-account-oauth) above, then ask your assistant "Run a system health check" to verify the connection.
2. **Explore your spend** — try "Show me a cost summary for the last 7 days" to see what your analytics surface looks like through conversation.
3. **Set your first alert** — ask "Create a daily budget alert at $500 with Slack notifications" to put a guardrail in place.

For programmatic metering from application code, see [SDK Setup](/integrations/sdk-setup). For one-command codebase instrumentation, see [Revvy CLI](/integrations/revvy-cli).

## Related

* [Rancher Prime Integration](/integrations/mcp-server/rancher-prime) — Kubernetes in-cluster deployment
* [Context7 and AI Docs Access](/integrations/context7) — AI-readable docs access without running an MCP server
* [AI Assistants](/track-and-control-costs/analyze-ai-tooling-spend) — Dashboard-level visibility into coding assistant adoption and spend
* [SDK Setup](/integrations/sdk-setup) — Instrument application code with Revenium SDKs and middleware
* [Slack](/integrations/slack) — Route alerts and reports to Slack channels
* [Revvy CLI](/integrations/revvy-cli) — Guided codebase instrumentation from the command line


# MCP Server for Rancher Prime

The Revenium MCP Server for Rancher is in private beta -- contact sales\@revenium.io if you'd like early access.

The Revenium MCP Server for Rancher gives Liz — SUSE Rancher Prime's AI assistant — direct access to your Revenium account. Once connected, Liz can answer AI cost questions, set spend alerts, and investigate anomalies as a native member of her agent crew, alongside your Kubernetes and infrastructure tooling.

This repo wraps the standard Revenium MCP server with an HTTP transport so it can run inside a Rancher-managed cluster and be consumed by the Rancher AI Agent — which expects an HTTP endpoint, not the stdio interface used by local clients like Claude Code.

### What Liz Can Do With the Revenium MCP Server

Once connected, Liz can:

* Investigate cost spikes — ask "Why did my AI costs spike yesterday?" and get a breakdown by provider, model, customer, agent, or API key
* Detect anomalies — find abnormal spend patterns across all dimensions, with configurable sensitivity and dollar thresholds
* Set budget alerts — configure Slack or email notifications when monthly, daily, or per-transaction spend exceeds a threshold
* Monitor trends — get cost summaries for any time window (last hour, day, week, or month) broken down any way you need
* Catch cost increases early — set relative-change alerts that fire when spend rises or falls by a percentage week-over-week or month-over-month
* Meter its own usage — track Liz's own API calls back to your Revenium account for full operational transparency

### Requirements

* A Kubernetes cluster managed by Rancher (tested with Rancher 2.13.4)
* Rancher with the AI Assistant feature enabled
* kubectl configured against that cluster

A Revenium API key — get one at [app.revenium.ai](https://app.revenium.ai).

### Getting Started

#### Step 1: Create the API Key Secret

Do this once, outside the YAML, so your key is never committed to version control:

```zsh
kubectl -n cattle-ai-agent-system create secret generic revenium-mcp-credentials \
  --from-literal=REVENIUM_API_KEY=rev_sk_your_api_key_here
```

The MCP server requires a write-scope key (`rev_sk_*`) — it reads account data and can create alerts and modify resources, so a metering-only key (`rev_mk_*`) will be rejected. See [API Key Permissions](/integrations/api-key-permissions).

#### Step 2: Deploy the MCP Server

Apply the Rancher deployment manifest from the maintained Revenium MCP Rancher package:

```zsh
kubectl apply -f revenium-mcp-k8s.yaml
```

This deploys the MCP server as a Kubernetes Deployment + Service inside cattle-ai-agent-system. No custom image or registry is required — the container pulls the published `revenium-mcp` package at start.

#### Step 3: Verify the Server is Up

```
kubectl -n cattle-ai-agent-system rollout status deploy/revenium-mcp-server
kubectl -n cattle-ai-agent-system get svc revenium-mcp-server
```

The in-cluster endpoint is:

```
http://revenium-mcp-server.cattle-ai-agent-system.svc
```

{% hint style="info" %}
**Regulated environments.** The default manifest exposes the endpoint as HTTP because in-cluster traffic is typically isolated by the cluster network policy. If your environment requires encryption-in-transit for in-cluster traffic, route the service through your cluster's existing service mesh or ingress TLS termination.
{% endhint %}

#### Step 4: Register the Agent

Apply the AIAgentConfig CR to register the MCP endpoint with the Rancher AI Assistant:

```zsh
kubectl apply -f revenium-agent.yaml
```

This uses the same API the Rancher AI Assistant uses internally to seed its built-in Rancher, Fleet, and Cluster Provisioning agents.

#### Step 5: Confirm Liz Can See It

```
kubectl get aiagentconfigs -n cattle-ai-agent-system -w
```

Once the revenium entry appears, refresh the Rancher AI Assistant. The Revenium agent will show up in the agent picker alongside the built-in agents.\ <br>

<br>


# Revvy CLI

An AI-powered CLI assistant that connects your billing providers, scans your codebase for AI calls, generates Revenium metering configuration, and wires up CI checks — all in one guided flow.

Revvy is a one-command wizard that turns a blank codebase — or an existing one — into a fully-instrumented Revenium integration. Instead of stepping through provider connections, SDK installs, config files, and CI wiring separately, Revvy does all of it in an interactive flow and leaves a working setup behind.

* **Package:** [`@revenium/revvy`](https://www.npmjs.com/package/@revenium/revvy) on npm
* **Source:** [github.com/revenium/revenium-revvy-cli](https://github.com/revenium/revenium-revvy-cli)

## What Revvy Does

In one interactive run, Revvy:

* **Connects your AI provider billing accounts and scans your codebase** — guided setup for OpenAI, Anthropic, AWS Bedrock, Google Vertex AI, and others so Revenium can consolidate spend, plus AST-level detection of every AI SDK call site so you know exactly what's about to be instrumented.
* **Generates a metering model and instruments your code** — a short Q\&A captures how you want usage attributed (organizations, products, agents, subscribers), then Revvy writes a config helper tailored to your app and wraps every AI call with the Revenium middleware. Python and Node.js today, with OpenAI, Anthropic, Google GenAI, Vertex AI, and Perplexity.
* **Wires up CI guardrails** — GitHub Action, editor rules for AI coding tools, and a `revvy check` command so metering coverage stays healthy as the code evolves.

## Why Use Revvy

* **Zero context-switching.** No separate docs tabs for each provider, no hand-copying API keys between files, no piecing together middleware patterns. Revvy asks what you need and does it.
* **Correct by construction.** The configuration and code transforms Revvy generates reflect Revenium's latest best practices.
* **Safe to preview.** Dry-run mode shows you exactly what Revvy would change without touching your files.
* **CI-aware from day one.** Revvy installs a GitHub Action that runs on every PR to catch missing metering, invalid config, and stale middleware versions before they ship.

## Quick Start

Get a Revenium metering API key at [app.revenium.ai/connections/sdk-setup](https://app.revenium.ai/connections/sdk-setup), then from the root of the project you want to instrument:

```bash
export REVENIUM_METERING_API_KEY="your-key"
npx @revenium/revvy
```

That's it. Revvy detects your language, scans for AI SDK usage, asks a few questions about how you want usage attributed, instruments every AI call site, and prints a summary of what changed.

Want to preview the changes before they happen? Add `--dry-run`. Want to run it from CI or have an AI coding assistant run it for you? Add `--non-interactive`. Full flag reference lives on the [package README](https://github.com/revenium/revenium-revvy-cli#readme) and `npx @revenium/revvy --help`.

## For AI Coding Agents

Revvy is designed to be driven by AI coding assistants (Claude Code, Cursor, Copilot, Gemini, Codex). On the first run Revvy installs an agent prompt at `.claude/revvy-agent.md`, `.cursor/revvy-agent.md`, etc. — your assistant reads it and finishes the instrumentation autonomously, including the AI-Outcomes design conversation that turns basic per-customer cost tracking into per-workflow and per-outcome ROI.

The agent prompt is also published with the package — see [`docs/agent-guide.md`](https://github.com/revenium/revenium-revvy-cli/blob/main/docs/agent-guide.md). If you're an AI coding agent and the user asked you to instrument their codebase, **read the agent guide before invoking the CLI**.

## Related

* **Outcomes Tracking:** see [ROI and Unit Economics](/track-and-control-costs/analyze-roi-and-unit-economics) for the API Revvy wires up via `agenticJobId`.


# Slack

The Slack integration makes Slack a delivery destination for the alerts and reports that Revenium already generates. Once connected, alerts configured under [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) can be routed to Slack channels rather than (or alongside) email and webhooks.

Slack is managed under **Connections → Integrations** in the product, alongside the GitHub and GitLab integrations. Each integration shows its connection status, credentials, and configuration on the same screen, and either can be connected, reconfigured, or disconnected without affecting the other.

{% hint style="info" %}
For GitHub Copilot and AI coding assistant cost tracking, see [GitHub Integration](/track-and-control-costs/analyze-ai-tooling-spend/github-integration).
{% endhint %}

### <i class="fa-slack">:slack:</i> Routing Alerts and Reports

#### What's Configurable

The integration page shows the number of Slack channels currently configured. The **Manage** button opens the channel configuration, where channels are mapped to alerts and reports.

For most teams, the right pattern is one channel per concern: a `#ai-cost-alerts` channel for spend guardrails, a `#ai-incidents` channel for failure-rate or anomaly alerts, and possibly a `#ai-reports` channel for weekly or monthly summaries. Channel-per-concern keeps notifications scoped to people who actually need to see them rather than dumping everything into one general channel where it gets ignored.

#### Why Slack Specifically

Slack is the channel most teams already live in for operational decisions. An AI cost spike that hits the right Slack channel five minutes after it happens lands in front of an engineer who can investigate; the same spike sitting in an inbox might not get noticed for a day. The integration exists to close that latency gap.

Webhooks (covered on the Set Budgets & Alerts page) cover everything Slack doesn't — incident management tools, custom routing logic, automated circuit-breaking. Email is always available without configuration. Slack sits between them: more immediate than email, less custom than a webhook, and tuned to the conversation patterns most teams already have.

### <i class="fa-plug">:plug:</i> Connecting and Managing the Integration

The Slack integration follows a standard lifecycle on the Integrations tab:

* **Connect** the integration with a Slack workspace authorisation
* **Validate** the connection — the integration shows its last successful validation timestamp on the configuration screen, and re-validates on each sync
* **Sync** — Slack channel updates happen as you change them in Slack
* **Reconfigure or disconnect** at any time from the same screen

Disconnecting Slack doesn't affect the GitHub integration on the same tab, and reconnecting after a disconnect resumes data flow without requiring any backfill on your part.


# FAQ

Common questions organized by what you're trying to do — not internal feature categories.

This FAQ is organized around what you're trying to do — not internal feature categories. Pick the scenario closest to yours: you're trying to get your AI agent reporting into Revenium, you want to see the full AI spend picture from your providers, you want guardrails before the invoice arrives, or you're troubleshooting why the numbers don't match what you expected. Each section answers the questions that come up in that context. For reference docs on specific features, follow the links.

***

### <i class="fa-rocket-launch">:rocket-launch:</i> Where do I start?

#### **I'm trying to instrument an AI agent versus using AI to interact with the platform — which path is this?**

Two distinct paths:

**Path A — Instrumenting your agent (most common):** You're sending data *to* Revenium. Your agent calls the Revenium SDK, OTLP endpoint, or direct API, and that data flows into your dashboards, cost controls, and AI Outcomes tracking. Most setup work lives here.

**Path B — Using Revenium's AI features:** You're using AI-powered features *within* Revenium — the MCP Server, AI Insights recommendations, or natural-language alert configuration. These features read your existing data and surface intelligence on top of it.

If you're just getting started, you're on Path A. See [Connect Your Coding Assistant & Code Repository](/get-started/quickstart/5-minute-quickstart).

***

#### **What's the minimum I need to do to get any data into Revenium?**

Start with instrumentation — that's the per-call layer that unlocks the rest. Use the SDK or OTLP to send data for every AI call: which agent, which workflow, which subscriber. That's also what powers cost guardrails, per-customer attribution, and the AI Outcomes layer. See [API Key Permissions](/integrations/api-key-permissions) for key setup.

Provider integrations complement instrumentation — connect your AI providers in [Provider Integrations](/integrations/provider-integrations) to pull total spend per provider as a baseline. On their own, admin-key syncs are read-only and after-the-fact, so they're useful for visibility but not for control.

If you use AI coding tools — Claude Code, Cursor, Gemini CLI, GitHub Copilot, or Codex — you can bring that spend in too. See [Analyze AI Tooling Spend](/track-and-control-costs/analyze-ai-tooling-spend).

Not sure where to begin? Try one of the [runnable examples](/get-started/quickstart/examples) — each one is self-contained and produces real data in your dashboard you can explore straight away.

The goal in all cases is [360 visibility](/track-and-control-costs/analyze-ai-tooling-spend): every AI dollar from every source, in one place.

***

#### **Which languages and frameworks are supported?**

See [Integration Options](/integrations/integrations) for the current list — that page is the single maintained reference for supported languages, frameworks, and connection paths.

***

### <i class="fa-360-degrees">:360-degrees:</i> Getting 360 visibility

#### **I want 360 visibility into my AI spend — what do I actually have to do?**

Two things, both required for the full picture:

1. **Connect your AI provider admin keys** in **Connections → Providers** — this pulls your provider billing data directly and shows you the total spend from each provider.
2. **Instrument your agents** with the SDK or OTLP — this gives you per-call attribution, subscriber-level breakdown, workflow-level ROI, and the control surface for guardrails.

Provider admin keys alone show you the total bill. Instrumentation shows you *why* — which agent, which workflow, which subscriber. Both together give you 360 visibility. The more data you send through instrumentation, the sharper the attribution picture gets.

***

#### **Do I need to send data, or will Revenium just see it through my provider admin keys?**

**Yes — you need to send data via the SDK or API.** Provider admin keys only cover one aspect of the picture: total billing data from each provider, read-only, after the spend has occurred. For cost controls to work, per-subscriber attribution, guardrails, and the AI Outcomes layer to function, your agents must send instrumented data into Revenium.

The control surface sits with your application — pre-call guardrails fire from the SDK before a request reaches the provider, which is only possible when your code is instrumented. Admin keys are a complementary baseline, not a substitute. Use the SDK for the easiest path to full coverage.

***

#### **I've connected my OpenAI / Anthropic admin key. Why aren't my cost controls firing?**

Provider admin key connections are billing-data syncs — they're read-only and happen after the fact. Cost controls require SDK instrumentation. When a guardrail rule is active, the SDK checks the rule *before* sending the call to the AI provider. If you're only using provider admin keys, Revenium sees the spend after it's already been incurred and can alert you, but cannot block the call.

See [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts) for how to enable runtime enforcement.

***

#### **What attribution fields should I pass with each call?**

The more attribution you send, the richer the views available in Revenium — by customer, product, agent, task, workflow, and more. Every additional field unlocks a new slice in the dashboards and makes cost controls more precise. On top of per-call attribution sits the outcomes layer — see [AI Outcomes](/instrument-your-agents/agent-outcomes) — where each job closes with a business result (CONVERTED, DEFLECTED, ESCALATED, UNSUCCESSFUL, CUSTOM) so the ROI loop completes.

At minimum, pass these fields so events map cleanly to your configured resources:

* `organizationName` — top-level customer account (used when a single customer has multiple users or API keys). The backend now requires `organizationName`; the legacy `organizationId` alias is silently dropped.
* `subscriber` — sub-object `{ id, email, credential: { name, value } }` identifying the end customer and their API key.
* `productName` — commercial tier or SKU. The backend now requires `productName`; the legacy `productId` alias is silently dropped.
* `agent` — the agent making the call. Populates per-agent cost attribution and the Tool Registry.
* `taskType` — categorizes what the agent was doing (qualification, support, code review, etc.); shows up in per-task analytics.
* `traceId` — links sequential AI calls into a single execution path for Trace Analytics.

For the full field list including `subscriptionId` (the Revenium subscription this call rates against — distinct from the end-customer `subscriber.id`) and `responseQualityScore`, see [SDK Setup → Usage Metadata](/integrations/sdk-setup#usage-metadata). If you're emitting OpenTelemetry instead of using the SDK, see [OTLP Integration](/integrations/otlp-integration) for the `revenium.*` attribute equivalents.

***

#### **Will adding the Revenium SDK slow down my application?**

For normal telemetry, no. SDK metering calls run on a background thread after the model call returns — fire-and-forget. They do not block your application and add no measurable latency to your AI calls.

The one exception is when a cost guardrail rule is active. In that case, the SDK performs a synchronous check *before* sending the call to the AI provider. That check is what makes pre-execution budget enforcement possible — it has to happen before the call, so it runs in-line. If no guardrail rules are configured, every SDK call is fully asynchronous.

***

### <i class="fa-box-dollar">:box-dollar:</i> Cost control

#### **How do I set hard spending limits on AI usage?**

Budget rules in Revenium can operate in two modes: **NOTIFY** (alert when a threshold is crossed) and **ENFORCE** (block calls once the ceiling is reached). Both are configured in **Guardrails**, under **Spend Management**.

For enforcement to work — meaning the SDK blocks the call before any spend is incurred — you need two things:

* **SDK instrumentation** on the agent making the calls. The SDK runs a synchronous pre-call check against the active rules. Without the SDK, Revenium can alert you after spend occurs but cannot block it.
* **Runtime enforcement enabled** on the rule. A rule set to NOTIFY only alerts — it does not stop execution. Switch it to ENFORCE to make it a hard gate.

If your stack emits OpenTelemetry instead, see [OTLP Integration](/integrations/otlp-integration) — you can implement your own pre-call check using the enforcement API, but the SDK handles this automatically.

The SDK's enforcement check happens at the call site, before the model sees the request. When a rule is breached, the call is blocked and `ReveniumCostLimitExceeded` is raised — no spend is incurred. See [Set Budgets & Alerts](/track-and-control-costs/set-budgets-and-alerts).

***

### <i class="fa-calculator-simple">:calculator-simple:</i> How does Revenium calculate my AI spend?

#### **How does Revenium calculate AI spend per request?**

When you use the SDK, Revenium automatically extracts model name, vendor, and token counts from the API response, then applies the current published pricing for that model. You don't calculate cost — Revenium does. Provider admin key data and SDK-metered data are reconciled together so the full spend picture reflects both sources.

If you're on a custom or negotiated pricing arrangement, set custom rates in **Settings → AI Models** — that takes precedence over published pricing.

***

#### **Can I override the cost Revenium calculates?**

Yes, two paths depending on your setup:

* **Settings → AI Models** (preferred for negotiated rates): set custom pricing for any model. This works whether you're using the SDK or the direct API and overrides published pricing for every cost calculation going forward.
* **Inline `totalCost` field** (direct API only): pass `totalCost` directly in your metering payload and Revenium will use your value instead of calculating it.

If your provider has given you negotiated pricing that differs from published rates, the Settings path is the right choice — it ensures all historical and future calculations use your rates. See [SDK Setup](/integrations/sdk-setup) and [OTLP Integration](/integrations/otlp-integration) for the relevant field references.

***

### <i class="fa-brain-arrow-curved-right">:brain-arrow-curved-right:</i> Understanding what Revenium finds

#### **How does AI Insights find waste and optimization opportunities in my usage?**

AI Insights runs Revenium's Recommendations Engine across your full transaction history — AI spend, errors, agent behavior, and model usage patterns — and produces a prioritized list of findings. Each finding is grounded in your actual data, tagged with severity and estimated monthly impact, and linked to the specific transactions that triggered it. Common findings include wasted spend on failed calls, over-sized models for simple tasks, and agents looping unexpectedly. The more instrumented data you send, the more precise the recommendations get. See [AI Insights](/optimize-performance/ai-insights) for the full reference.

***

#### **What happens when an agent fails its business outcome?**

Revenium's AI Outcomes layer classifies every agent execution as CONVERTED, ESCALATED, DEFLECTED, UNSUCCESSFUL, or CUSTOM — linking the technical result to a business result. When an agent fails to achieve its intended outcome, that execution is recorded against its outcome type so you can track failure rates, AI spend per outcome, and ROI at the workflow level. This separates technical success (did the call complete?) from business success (did it achieve what it was supposed to?). See [Agent Outcomes](/instrument-your-agents/agent-outcomes) for setup and the full taxonomy.

***

### <i class="fa-user-lock">:user-lock:</i> Privacy and data

#### **Does Revenium have access to prompt or response content?**

{% hint style="success" %}
**By default, no.** Revenium does not access, store, or analyze the raw input (prompts) or output (responses) of your AI calls unless you explicitly opt in.
{% endhint %}

Our SDK and APIs are designed to capture **usage metadata only** by default, such as:

* Token counts (input and output)
* Model type and latency
* Subscriber, organization, product, and agent attribution fields
* Optional quality or classification metrics

This enables precise AI spend tracking, performance alerts, and usage-based billing — **without exposing any user-generated content**.

Prompt capture is opt-in and controlled at multiple levels. A team admin must first enable it per team. Once enabled at the team level, individual users must be granted view access before they can see prompt content. Admins can restrict prompt viewing per user, or restrict it to a dedicated data context that only specific users can access. The default at every level is off — prompt data only flows when each layer has been explicitly configured.

#### **Where is data stored and processed?**

Data is processed and stored in US-based cloud infrastructure by default. EU region is available on Enterprise plans.

***

### <i class="fa-toolbox">:toolbox:</i> Troubleshooting

#### **Why does my first test event show missing or zero cost?**

This usually means Revenium accepted the event but did not receive enough cost-relevant metadata to price it.

**Common causes:**

* Using `imageCount` instead of `actualImageCount`
* Using `audioLength` instead of `audioDurationSeconds`
* Using `stop_reason` instead of `stopReason`
* Omitting the required `stopReason` field entirely

**How to fix:**

1. Review the API documentation to verify exact field names
2. Check the AI Analytics dashboard to confirm costs are being calculated
3. Use one of our [SDKs](/integrations/sdk-setup) to avoid field-name issues entirely — SDKs handle correct field mapping automatically

***

#### **How can I test whether usage is being tracked?**

Go to the AI Transactions log page in the Revenium UI to see usage, tokens, latency, and AI spend per call. You can also verify metadata like organizations, products, subscribers, and agents there. See [Debug Logs & Traces](/optimize-performance/debug-logs-and-traces) for guidance.

***

#### **What happens if I send metadata Revenium doesn't recognize?**

Because the SDK's metering call is async and non-blocking, your call to the AI provider continues unaffected — only the usage tracking to Revenium is skipped. Most SDKs log a warning via standard logging so you can identify and fix the issue. The AI provider call itself is never blocked by a metadata problem.

***

Still have questions? Visit [app.revenium.ai](https://app.revenium.ai) and use the in-app chat to reach the team.


# Manage Users & Teams

Behind every productive use of Revenium is a clean map of who's allowed to see what. Users are the individuals in your organization who log in and use the product - engineers instrumenting agents, finance teams auditing spend, product leaders tracking ROI. Teams are the internal structure those users belong to - business units, departments, product groups - that let you separate analytics and usage by group rather than flattening everything into one undifferentiated tenant view.

This is where you manage both. Access this area from the user avatar in the bottom-left corner of Revenium, then choose **Users & Teams** from the menu. Two tabs: **User** for individual accounts, **Teams** for the organizational structure they live within.

Worth a quick distinction before getting into detail: Teams here are your *internal* business units. They're different from Organizations, which represent your *customers* and live under [Manage Customers & Credentials](/monetize-your-ai/manage-customers-and-credentials). A Team is for your own team at Revenium; an Organization is for the company that pays you.

### <i class="fa-user">:user:</i> Users

The Users tab lists every person with access to your Revenium account. Each user has:

* **Email Address** - the login and unique identifier
* **First Name** and **Last Name** - for display in dashboards and audit trails
* **Teams** - one or more teams the user belongs to, displayed as badges. Users can belong to multiple teams, which is how you handle people who work across business units
* **Assigned Roles** - the permission scopes that govern what the user can do (see below)
* **Actions** - edit user details or delete the user

Adding a new user uses the **Add User** dialog. First Name, Last Name, Email, Teams, and Roles are all required. Once saved, the user receives a magic link invitation at the email address provided - no password is set on creation; the user claims their account by following the link.

#### Roles

Revenium uses a small set of named roles to control what users can do. These include **Tenant Administrator**, **Team Administrator**, and **Read Only**. A single user can hold more than one role; the Assigned Roles column in the Users list shows each applicable role, and role badges also appear against members in the Teams view.

The specific permission boundaries of each role are documented in Revenium's role reference. As a rough conceptual guide, tenant-scoped roles tend to grant cross-team access to settings and data, while team-scoped roles tend to be bounded to the team or teams the user belongs to. When configuring roles for a new user, choose the least privilege that covers their job.

**Understand workspace roles**

A user is treated as read-only only when the **Read Only** role is present without a write-capable role. If the same user also holds a write-capable role, that role supplies their write access.

**Read-only access**

The **Read Only** role grants view-only access: a user with this role can see the data and settings their scope allows but cannot create, modify, or delete resources. It is the right fit for stakeholders who need visibility—such as auditors, finance reviewers, or leadership tracking spend—without write capability.

For a user identified as read-only, write actions — create, edit, delete — appear disabled, with a note explaining the account is read-only.

In Guardrails, for example, a read-only user can view every rule and its history but can't create, toggle, or delete one.

Other product areas may expose different read and write actions. Use the disabled-action guidance shown in the product rather than assuming that the Guardrails boundary defines every page. User roles and API key permissions are separate access controls; see [API Key Permissions](/integrations/api-key-permissions) for the API key access model.

**Assign or change a role**

Choose **Read Only** when a user needs visibility without write access. Choose a write-capable administrator role when the user must manage resources within its scope. If you assign Read Only together with a write-capable role, the user is not treated as read-only.

#### The Can View Prompt Data Permission

One permission sits separately from the standard role model: **Can View Prompt Data**. This toggle, configurable per user, controls whether the user can see captured AI prompts, messages, and responses in the transaction log and trace views.

This is deliberately a standalone permission because prompt data is sensitive in a way that other AI cost data isn't. A user who can legitimately see cost and usage totals for a customer may not have any business seeing the actual text content of that customer's prompts. The default is off; Tenant Administrators have implicit access regardless of the setting, and only Tenant Administrators can modify it for other users.

Worth configuring thoughtfully from the start. Teams with compliance requirements around PII, confidential business data, or regulated industries generally want prompt access limited to a small set of named reviewers rather than everyone with a Revenium login.

### <i class="fa-users">:users:</i> Teams

The Teams tab lists your internal organizational structure. Each team has:

* **Name** - the display label
* **Parent** - optional, for building a hierarchy. Teams can be nested, so a parent team contains sub-teams. The Teams list renders the hierarchy as an expandable tree - click the chevron to expand a parent and see its children.

Teams are lightweight to create but carry a lot of optional configuration. Teams can be created without a tier upgrade or plan prerequisite, so you can structure your teams as soon as you need them. The **Add Team** dialog's header calls them "Team, Organization, or Business Unit" - reflecting that a Team can represent anything from a small engineering group to an entire business division.

#### Configuring a Team

The required fields are minimal - just **Name**. Everything else is optional and grouped into expandable sections:

* **Currency** - the default currency for this team's billing and analytics. USD is the default; pick a different currency if the team operates in a non-dollar market.
* **Advanced Settings** - team-level behaviors including auto-discovery settings for data sources and metering elements (Revenium recommends leaving these on in most cases).
* **Billing Address** - postal address and contact details used on invoices issued to or from this team, along with remittance instructions.
* **Metadata** - arbitrary key-value pairs for your own tagging or integration needs.
* **AI Settings** - team-level AI behaviors including whether prompt capture is enabled. Prompt capture is the feature that makes the Can View Prompt Data permission meaningful - without it on at the team level, there's no captured prompt data for users to see or not see.

You can also upload a team logo that appears in the Revenium interface when that team is active.

#### Why Teams Matter

Teams aren't just an org-chart convenience - they're the scope boundary for a lot of Revenium's behavior. API keys are scoped to a team. Analytics can be filtered and rolled up by team. Invoices and billing settings apply at the team level. When you pick a team from the selector in the top-left of the product, you're choosing which team's data you're currently looking at.

For most organizations, the right pattern is one top-level team representing the company, with sub-teams for departments or business units that need their own cost attribution. Users who work across sub-teams can belong to multiple teams simultaneously.

### Tenants

Tenants are the top-level object that contains your teams. The hierarchy is Tenants -> Teams -> Users.

### <i class="fa-code">:code:</i> Via API

The [Users endpoints](https://revenium.readme.io/reference/get_user) and [Teams endpoints](https://revenium.readme.io/reference/get_team) both have full CRUD - creating and listing users, updating their roles and team memberships, creating and configuring teams, nesting them into hierarchies via `parentId`. Useful when provisioning users programmatically (from an identity provider, for instance) or when setting up a multi-team structure as part of a deployment script rather than clicking through the UI. The [Tenants endpoint](https://revenium.readme.io/reference/get_tenant) returns information about your tenant.


# What Generates Charges

Understand which metered activities create Revenium transactions, so you can anticipate platform charges and explain billing volume.

Revenium platform charges are based on the volume of metered transactions your application generates. This is different from AI provider spend, which is the cost you pay OpenAI, Anthropic, AWS, Google, or another provider. This page explains what creates a Revenium transaction so finance and product teams can predict billing volume and explain charges.

There are three categories of billable activity: **AI completions**, **tool registry events**, and **metered product usage for monetization**.

{% hint style="success" %}
**Quick answer:** A Revenium transaction is recorded each time your application sends a metered event to Revenium: an AI call, a Tool Registry event, or a subscriber's use of a metered product configured for monetization. Viewing data in the Revenium dashboard, configuring alerts, or managing subscribers does **not** generate transactions.
{% endhint %}

***

## AI Completions

Each AI call routed through Revenium's metering creates one transaction. This is the primary source of Revenium billing volume for most customers.

The captured data is used for cost attribution and analytics within each transaction — showing you what your AI usage costs across providers, models, agents, and customers — but the transaction itself is the billing unit.

{% hint style="info" %}
**You only pay for what you send.** Revenium meters events you explicitly route through its SDK or metering API. AI calls that bypass Revenium — for example, direct calls to a provider made without the SDK — are not metered and not charged.
{% endhint %}

### What counts as one completion event?

Each request-response pair with a model is one transaction. If your application makes a single `chat.completions.create` call, that is one metered event. Streaming responses count as one event once the full response is received. Retries count as separate transactions if each retry reaches the model.

***

## Tool Registry Events

[Monitor Agent Tool Usage](/instrument-your-agents/monitor-agent-tool-usage) is Revenium's feature for tracking costs that go beyond AI model calls — things like external API calls, third-party data services, MCP servers, or human review steps that your agents invoke. You define each cost source in Revenium, assign it a price, and then your application sends an event each time that tool is used. This is separate from the tool-calling capability built into LLMs; it's a way to capture the full economic footprint of your AI workflows, not just token costs.

Each event sent for a registered tool that has pricing configured creates one transaction.

**A tool registry event creates a transaction only when both conditions are true:**

1. The tool has a pricing element configured (flat rate or tiered).
2. Your application sends an event to the metering API for that tool.

Tools with no pricing configured are tracked for observability but do not generate a transaction. Tools that are disabled are not metered.

***

## Metered Product Usage for Monetization

If you are using Revenium's [monetization features](/monetize-your-ai/create-pricing-models-and-products) to bill your own customers, product usage transactions are generated by your subscribers' activity against their subscriptions.

What creates a product usage transaction depends on how your product is priced:

| Pricing model                  | What triggers a transaction          |
| ------------------------------ | ------------------------------------ |
| **Flat subscription**          | Subscription activation / renewal    |
| **Per-call / per-transaction** | Each metered request by a subscriber |

Transactions are only generated for active subscriptions. Subscribers who have not activated a subscription, or whose subscription has expired, do not generate product usage transactions.

***

## What Does Not Generate a Charge

| Activity                                                                  | Charged? |
| ------------------------------------------------------------------------- | -------- |
| Viewing dashboards, analytics, or logs                                    | No       |
| Configuring alerts, budgets, or cost controls                             | No       |
| Creating or managing subscribers, credentials, or products                | No       |
| AI calls blocked before reaching the model (e.g., by a Cost Control rule) | No       |
| Tool Registry events for tools with no pricing configured                 | No       |
| Tool Registry events for disabled tools                                   | No       |
| Revenium's SDK evaluating a cost control rule                             | No       |

***

## FAQ

<details>

<summary>Is there a charge if my AI call fails?</summary>

It depends on where the failure occurs. If a Cost Control rule blocks the request before it reaches the model, no transaction is recorded and no charge is incurred. If the request reached the model and received a response — even an error response — the event was metered and a transaction is recorded.

</details>

<details>

<summary>I've connected an AI coding assistant like Claude Code or Gemini — what transactions will it generate?</summary>

AI coding assistants that send telemetry to Revenium follow the same model as any other AI completion: each AI call the assistant makes generates one metered transaction. In practice, a single session where a developer asks several questions and runs several tasks will produce multiple transactions — one per model request.

The exact transaction count for a given session depends on how the tool vendor's harness batches and reports events, which is outside Revenium's control. What you can observe is straightforward: each transaction that appears in your [AI Transactions log](/optimize-performance/debug-logs-and-traces) represents one AI call that was metered. There are no hidden multipliers or background charges.

For details on connecting specific tools and understanding what data each one reports, see the [AI Assistants Dashboard](/track-and-control-costs/analyze-ai-tooling-spend).

</details>

<details>

<summary>If I use multiple providers (OpenAI, Anthropic, etc.), does that affect my transaction count?</summary>

Each AI call generates one transaction regardless of which provider handled it. Using multiple providers does not change the transaction count — it affects the cost attribution data captured within each transaction, which you can view broken down by provider in your analytics.

</details>

<details>

<summary>How do I see a breakdown of what I've been charged?</summary>

For a transaction-level breakdown, use the [AI Transactions log](/optimize-performance/debug-logs-and-traces), which includes both AI transaction details and product transaction entries.

</details>


