# AI Anomalies Source: https://help.nops.io/ai/anomalies AWS Cost Anomaly Detection results filtered to AI services, with severity, impact, and root causes. **Anomalies** shows AWS-detected cost anomalies narrowed to AI services (Bedrock, SageMaker, and related services) so an unexpected spike in model spend does not have to be found by scrolling through every anomaly in the account. > [!NOTE] > > The AWS section appears only when you have an active AWS integration. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Anomalies**. 3. Sort out what matters using the summary cards, then work the table. The sidebar entry carries a badge with the number of open anomalies. ## Key features ### Summary cards | Card | What it counts | | - | - | | **AI anomalies** | AWS-detected AI service anomalies in the window. | | **Total impact** | Aggregate anomaly impact. | | **High severity** | Critical or high severity anomalies. | All three describe active anomalies inside your selected date window (not an account-wide total) so the numbers always match the table below. ### AWS Detected Anomalies | Column | What it shows | | - | - | | **Source** | Where the anomaly was detected. | | **Severity** | Severity level. | | **Start** / **End** / **Duration** | When it ran. | | **Cost impact** | Dollar impact. | | **Impact %** | Impact as a percentage. | | **Trend** | A sparkline of the spend shape. | | **Service** | The AWS service involved. | | **Root causes** | What AWS attributed it to. | Filter the window with **Last 7 days**, **Last 30 days**, **Last 90 days** (the default), or **All time**. ### Active and Ignored Toggle between **Active** and **Ignored**. The **Ignored** tab carries a count of how many anomalies in the current window you have set aside. Select rows with the checkboxes to ignore them in bulk, or ignore everything currently in view in one action. Anything ignored can be brought back from the **Ignored** tab. This is how you retire a known, explained spike so it stops competing for attention with new ones. ## FAQs > **Why is the AWS section missing?** > > It renders only when an AWS integration is connected and active. > **Which services count as AI here?** > > Anomalies from AWS Cost Anomaly Detection filtered to AI services, including Bedrock and SageMaker. > **Does ignoring an anomaly delete it?** > > No. It moves to the **Ignored** tab and stops counting toward the summary cards. You can unignore it at any time. > **Why doesn't the ignored count match what I expect?** > > The count reflects only ignored anomalies inside the selected date window, so widening the range can reveal more. ## Related * [AI Recommendations](/ai/recommendations) * [Tracking](/ai/tracking) * [Insights](/inform/insights) # Automated Rebalance Source: https://help.nops.io/ai/automated-rebalance How nOps moves unused seat limit to the seats about to hit their cap — the workflow modes, the trust scorecard it has to pass before it can write, and the safeguards that hold it back. **Automated Rebalance** watches pooled seat spend and moves unused limit to the seats about to hit their cap, so nobody gets blocked mid-period. Because it writes to your provider, the default posture is that it *cannot*. It has to earn write access against a published scorecard you can watch in the product, and it loses that access the moment a write cannot be verified. This page documents exactly how that works, so you can decide whether to trust it before turning it on. > [!NOTE] > > Automated Rebalance is an admin-only tab inside seat tracking, not a sidebar entry. It unlocks once your budget is ready. Unattended limit changes are supported for **Claude Enterprise**, and for **Cursor Enterprise** teams you connected with limit management enabled. Cursor **Teams**-plan seats and ChatGPT / Codex seat limits are read-only in nOps, so they are reported on but never changed. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. Open your seat tracking project and go to the **Automated Rebalance** tab. 3. Open the **Automation** card and read the **Trust scorecard** before changing anything. 4. Leave the workflow on **Observe** until the scorecard says **Eligible**. If you have no provider that supports limit writes, the tab tells you so: *Enable an AI seat tracking provider with limit writes to configure automation.* Seat recommendations still show; nothing can be applied. ## Key features ### The Automation card A collapsible card with two tabs, **Settings** and **Activity**, plus two controls in its header: * **Enable** turns detection on and off. * **Run now** triggers a check immediately instead of waiting for the schedule. The card's status reads **Detection off**, **Observing pool**, **Approve before apply**, or **Auto-rebalancing**, depending on how it is configured. ### Workflow modes Under **Settings**, three tiles decide what a run is allowed to do. Checks happen about hourly; if raise or lower recommendations exist, the run honors whichever mode you picked. | Mode | What a run does | | - | - | | **Observe** | Detect only, never write to the provider. | | **Approve** | Propose changes for a human to confirm. | | **Auto** | Apply limit changes immediately. | Click **Save settings** to apply. Email and chat notifications for rebalance runs are configured in project settings. > [!WARNING] > > The workflow mode is a preference, not a permission. A policy still cannot write unattended until it has passed the trust scorecard, regardless of which tile is selected. ### Triggers By default every check runs on the schedule. Turn on **Only run when pool is tight** to skip the hourly check unless something actually warrants it: | Setting | What it does | | - | - | | **Run when remaining pool hits** | Fire when the remaining pool falls to a dollar figure. | | **Run when pool spend reaches** | The same trigger expressed as a percentage of the pool. | | **Min spend before checks** | A floor, so early-period noise does not trigger runs. | | **Forecast breach** and **Days ahead** | Fire when the forecast says you will breach within N days. | Under **Advanced**: * **Custom pool cap** overrides the pool size. Leave it blank to use the budget target. * **Open requests before graduation** lets runs open seat requests and wait for a human while the trust score is still building. Automation still never writes on its own — someone has to approve the run. This is unavailable in Observe, which never opens requests. ### The trust scorecard The **Trust scorecard** card shows the evidence required to graduate out of the current autonomy state, with a pill reading **Eligible** or **Building trust**. Every criterion must pass. | Criterion | Requirement | Why it exists | | - | - | - | | **Observation window** | 7 days by default | Enough calendar time to cover a full weekly spend cycle. | | **Qualifying hours observed** | 50 distinct hours by default | Confirms the controller has seen this budget repeatedly over real elapsed time. | | **Settled forecast samples** | At least 1 | Graduation cannot rest on forecasts that were never checked against reality. | | **Forecast error** | Mean absolute percentage error at or below 25% | The controller must be able to predict this budget before acting on it. | | **Simulated budget violations** | Exactly 0 | If any recommendation *would have* pushed allocations past the pool, that disqualifies it. | | **Recommendation samples** | At least 5 recommendation transitions | Churn cannot be judged from an empty sample. | | **Recommendation churn** | Below 10% | A controller that keeps reversing itself is unstable, whatever its average accuracy. | The card shows your live figures next to these: elapsed versus required days, qualifying hours, forecast error with its settled sample count, churn with its reversal count, and **Budget adherence**, which reads **No violations** when clean. #### What counts as evidence Only outcomes that reflect an actual decision count toward graduation. Runs that errored out, found nothing worth deciding on (no pool to work with, no managed seats, or a conflicting policy already holds write access), or were held back before they got that far (rate-limit backoff, another run still in progress) don't count. A policy cannot graduate because its runs kept failing or getting skipped. A run that looked at a healthy pool and correctly did nothing *does* count. Evidence accrues by the distinct UTC hour, not by the number of runs — several runs inside the same hour count once, and you can bank at most 24 hours of credit per day. The floor always implies real elapsed time. ### Rebalance History The **Activity** tab and the **Rebalance History** panel record every run. | Run status | Meaning | | - | - | | **Proposed** | A recommendation was recorded; nothing was written. | | **Awaiting approval** | The run is parked waiting for a human. | | **Applied** | Limit changes were written and verified. | | **Failed** | The run errored. | | **Skipped** | The run was suppressed before deciding. | Each run also records what triggered it: **Manual**, **Threshold**, **Forecast**, or **Scheduled**. A run **Awaiting approval** offers **Approve** and **Undo**. A **Proposed** run offers **Undo**. Pending runs also point out that you can review each seat change individually as an open request on the [Requests](/ai/requests) tab, if you would rather decide seat by seat than approve the whole run. ## How often it runs Every tracked budget is checked on a fixed hourly schedule. There is no faster path, and there is no way for a check to decide it should run more often. That is a deliberate constraint rather than a limitation. A check that can decide to run itself more often can drift into checking far more frequently than anyone intended, with no setting you could point to that explains why. Keeping the schedule as the only trigger means the frequency you see in **Settings** is the frequency you get — it can't quietly speed up on its own. Raising a seat's limit sooner is still possible: open a seat request and approve it, or use **Run now**. ## Safeguards **Every write is verified.** After changing a seat limit, nOps re-reads that user's effective limit from the provider and confirms it matches the intended value. A write that cannot be verified — wrong value, unreadable, or the provider identity no longer matches — is recorded as a failure, not a success. **Failed verification revokes autonomy.** A policy that fails reconciliation is demoted back to Observe. It stops writing immediately and has to earn write access back through the scorecard. **One unattended writer per provider.** Only one policy per organization may hold write autonomy for a given provider. If a second policy would otherwise graduate, graduation is refused and the conflict is logged. Claude Enterprise spend limits are organization-wide, so two controllers writing to the same roster would fight each other with no audit trail explaining the result. **Rate limits are respected.** Provider calls back off and retry rather than hammering your provider organization's shared request budget. ## What it will never do * Write to your provider while in Observe. * Graduate itself without every scorecard criterion passing. * Raise a seat's allocation past the budget pool. * Change a read-only seat's limit — a ChatGPT / Codex seat, a Cursor Teams-plan seat, or a Cursor seat that appears in more than one connected team. * Keep writing after a write failed to verify. ## FAQs > **Can I skip the observation period?** > > No. There is no setting that grants write access immediately. The scorecard is the only path. > **Why isn't my policy graduating even though it has run hundreds of times?** > > Check which criterion is unmet on the scorecard. The two most common causes are **Qualifying hours observed** — runs that were skipped, backed off, or failed do not count, and multiple runs in the same hour count once — and **Recommendation samples**, because a policy that has never changed its recommendation has no churn sample to judge. > **How do I revoke autonomy manually?** > > Set the workflow back to **Observe**, or turn off **Enable**. It stops writing on the next run. > **Can I let automation open requests before it has graduated?** > > Yes. Turn on **Open requests before graduation** under **Advanced**. Runs will open seat requests and wait for a human. Automation still never writes on its own. > **Why is the tab missing for me?** > > It is admin-only, it lives inside seat tracking rather than the sidebar, and it unlocks only once the project's budget is ready. ## Related * [Requests](/ai/requests) * [Budgets](/ai/budgets) * [Wallets](/ai/wallets) * [Claude Enterprise integration](/integrations/claude-enterprise) # Budgets Source: https://help.nops.io/ai/budgets Set AI spend targets per group or per seat, compare them against seat limits, and forecast where the period is heading. **Budgets** turns your [Wallets](/ai/wallets) allocation into numbers you can hold people to. The **Planning** view is where you set targets and see them next to the seat limits you have actually issued. **Budgets vs. Actual** is where you watch the period play out with a rolling forecast. > [!NOTE] > > Budgets requires seat tracking admin rights and unlocks once your allocation has at least one group. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Budgets**. 3. Review the targets setup generated from your recent spend, and adjust them. 4. Switch to **Budgets vs. Actual** to see how the current period is tracking. The budget behind this page is an ordinary nOps budget backed by an Explorer report, so everything in [Budgets (Operate)](/operate/budgets) (alerts, CSV round-trips, period schedules) applies to it too. ## Planning ### Summary cards | Card | What it tells you | | - | - | | **Sum of individual limits** | Every seat limit you have issued, added up. | | **Limits vs target** | Whether those limits fit inside the target, or exceed it. | The second card is the one to watch. Handing out more limit than you budgeted is not an error, but it is a decision, and this is where you find out you made it. ### The group grid | Column | Meaning | | - | - | | **Group** | The allocation group (or user, in user mode). | | **Previous** | The previous period's spend. | | **Avg lookback** | The average over the lookback window. | | **Period columns** | One column per budget period, holding the target. | | **Seat spend** | Provider period-to-date spend, live from the Cursor or Claude Enterprise APIs for the current billing period. | | **Limit** | The sum of seat limits in that group. | | **Remaining** | Limit still available. | | **Seats** | How many seats are in the group. | A **Targets** row totals the grid. On a bottom-up budget you edit each group's periods and the total rolls up; on a top-down budget you edit the **Targets** row total and the group rows move proportionally. Search with **Search groups…** when the list gets long. > [!NOTE] > > The two halves of this grid come from different places. Period targets and actuals come from the linked Explorer report. **Seat spend**, **Limit**, and **Remaining** come from live provider APIs. They can legitimately disagree for the current period. ### Roll up by group or vendor The **Roll up by** toggle changes the lens: * **Group:** roll spend up by allocation group, with editable targets. This is the working view. * **Vendor:** roll the same seats up by AI vendor (Claude, Cursor, and so on). Vendor is a read-only lens, reachable directly with `?budgetBy=vendor`. Its period columns cover the current period and earlier, drawn from the monthly spend rollup; future periods hold targets, which stay on the Group view. Vendor mode is not available when your allocation is organized by user. ### Context banners The grid tells you when something upstream is incomplete rather than quietly showing zeroes: * **Enable AI providers to sync seat usage:** no provider is syncing seats yet. * **Your allocation rules are per user:** you are in user mode and the group lens does not apply. * **Waiting for seat usage:** providers are connected but no usage has landed. * **Group membership is still loading:** figures will settle in a moment. You will also see a warning when your targets have gone stale relative to the allocation behind them, which usually means you changed groups in Wallets and should regenerate. ## Budgets vs. Actual Reachable from the second tab, or directly with `?view=actual`. The header reads **Track & Forecast**: AI seat spend with a rolling daily forecast. ### Period summary | Card | What it shows | | - | - | | **Budget planned** | The target for the current period. | | **Budget actuals** | Actual spend, with what percent of planned that is. | | **Variance** | How far over or under you are, in dollars. | ### Controls * **Forecast horizon:** 14 days, 30 days, 2 months, or 3 months. It defaults to 3 months. Training history scales with the horizon, so a longer projection is fit on more history rather than extrapolated from a couple of weeks. * **Group filter:** narrow the forecast to one allocation group, or leave it on **All groups**. * **Scope:** **All Project Usage**, **My Department**, or **My Usage**. You only see the scopes you have access to; a seat holder with no admin role sees their own usage. If you have an open limit request, your own view surfaces it here with the requested and current limits, so you are not left wondering whether anyone saw it. ## FAQs > **Where did my initial targets come from?** > > Setup generates them as a monthly, bottom-up budget over 12 periods, starting from the average of your recent monthly spend with no growth applied. If your AI spend history is shorter than the lookback window, the average uses whatever months exist. > **Why don't Seat spend and the period actual match?** > > They are different sources on purpose. Actuals come from the Explorer report behind the budget; **Seat spend** is live period-to-date spend straight from the provider API. Within a period, the live figure moves first. > **Can I edit targets on the Vendor view?** > > No. Vendor is a read-only roll-up. Targets are edited on the Group view. > **Can I set alerts on this budget?** > > Yes. It is a normal nOps budget. Configure threshold alerts from the budget itself. See [Budgets](/operate/budgets). > **My targets say they're stale.** > > That happens after the underlying allocation changes. Regenerate targets so they match your current groups. ## Related * [Wallets](/ai/wallets) * [Automated Rebalance](/ai/automated-rebalance) * [Budgets (Operate)](/operate/budgets) * [Set up AI seat tracking](/ai/setup) # Introduction Source: https://help.nops.io/ai/introduction Track AI model and seat spend, allocate it to teams, budget it, and keep individual seats from getting blocked. # nOps AI **AI** is where nOps brings your AI spend together: model and token usage across providers, per-seat spend and limits, the requests people file when they hit a cap, and the budgets and wallets that decide who gets what. It sits on the same Explorer and Budgets machinery as the rest of nOps, so AI spend is allocated and budgeted the same way your cloud spend is. > [!NOTE] > > AI requires the **Inform** plan. Some areas need additional permissions; see [Who sees what](#who-sees-what) below. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. Connect at least one AI provider integration (Claude Enterprise, Cursor, or ChatGPT / Codex) in **Settings → Integrations**. 3. In the sidebar, open **AI → Tracking** to see model and token usage right away, at [clara.nops.io/ai-optimization/tracking](https://clara.nops.io/ai-optimization/tracking). 4. To manage seats, limits, and budgets, create a seat tracking project. See [Set up AI seat tracking](/ai/setup). ## What's in the AI area > **[Tracking](/ai/tracking)** > > Model Overview and AI Explorer: which models and platforms your spend and tokens go to. > **[Requests](/ai/requests)** > > The queue where people ask for a higher spend limit and reviewers approve, reject, or ask for more. > **[Wallets](/ai/wallets)** > > Split AI spend into groups, assign seats to them, and pick who approves each group's requests. > **[Budgets](/ai/budgets)** > > Per-group and per-seat targets, plus a Budgets vs. Actual forecast view. > **[Recommendations](/ai/recommendations)** > > Measured model, seat, and cap findings across Bedrock, Cursor, and Claude Enterprise. > **[Anomalies](/ai/anomalies)** > > AWS-detected anomalies filtered to AI services, plus Clara's analysis. One more surface sits alongside these: * [**Automated Rebalance**](/ai/automated-rebalance): an admin-only tab inside seat tracking that moves unused limit to the seats about to hit their cap. ## Key concepts ### Seat tracking projects Most of the AI area is organized around a **seat tracking project**. A project ties together three things that already exist elsewhere in nOps: an AI-scoped Cost Allocation showback (your wallets), a budget with an Explorer report behind it, and the live seat rosters your provider integrations sync. Creating the project provisions those links for you. Tracking works without a project. Wallets, Budgets, Automated Rebalance, and most of the Requests workflow do not. ### Providers nOps tracks three AI providers today, and they do not all do the same things: | Provider | Per-seat spend | Limit writes | Group sync | | - | - | - | - | | **Claude Enterprise** | Yes | Yes | Yes | | **Cursor** | Yes | Enterprise teams only | No | | **ChatGPT / Codex** | Yes | Read-only | No | Claude Enterprise limits can be read and written on any connection. Cursor depends on the plan of the team you connect: a Cursor **Teams** plan exposes no per-user spend limits at all, while a Cursor **Enterprise** team can have its limits read and written if you connect it with an Admin-scoped key and turn on limit management. ChatGPT / Codex is read-only. Read-only spend is still tracked, allocated, budgeted, and forecast. nOps simply cannot change the cap for you. > [!NOTE] > > nOps takes one connection per Cursor team, so an organization with several teams connects each one. A person who appears in two connected teams has their spend summed for reporting, but their limit cannot be changed from nOps, because no single team owns it. Model and token usage on **Tracking** covers a wider set of platforms than the seat providers, including Amazon Bedrock spend that arrives through your cloud integration. ### Who sees what The AI group in the sidebar adapts to your permissions: * **Everyone with AI access** sees Tracking, Requests, Recommendations, and Anomalies. * **Seat tracking admins** additionally see Wallets and Budgets, and get the admin-only Automated Rebalance tab inside seat tracking. * A restricted **request-viewer** role sees only Requests, and only their own. > [!NOTE] > > Model Overview and AI Explorer are each gated independently for your organization. If only one is enabled, the Tracking page shows it directly with no sub-tabs. ## FAQs > **Do I need a seat tracking project to see AI spend?** > > No. **AI → Tracking** works as soon as an AI provider or cloud integration is sending spend. A project is what unlocks wallets, budgets, seat limits, and requests. > **Why can't I see Wallets or Budgets?** > > Those two sidebar entries require seat tracking admin rights. Without them you still see Tracking, Requests, Recommendations, and Anomalies. > **Can nOps change someone's spend limit automatically?** > > For Claude Enterprise, and for Cursor **Enterprise** teams connected with limit management enabled. Either way it happens only when an admin has switched the workflow off **Observe**, and only within the rules described in [Automated Rebalance](/ai/automated-rebalance). Cursor Teams-plan seats and ChatGPT / Codex limits are read-only in nOps. > **How does AI spend relate to the rest of nOps?** > > A seat tracking project creates a Cost Allocation showback and an Explorer report behind the scenes, and its budget is an ordinary nOps budget. You can open any of them from their own pages and they behave exactly as documented there. ## Related * [Set up AI seat tracking](/ai/setup) * [Explorer](/inform/explorer) * [Budgets](/operate/budgets) * [Claude Enterprise integration](/integrations/claude-enterprise) * [Cursor Admin API integration](/integrations/cursor-admin-api) * [OpenAI Enterprise integration](/integrations/openai-enterprise) # AI Recommendations Source: https://help.nops.io/ai/recommendations Measured model, seat, and cap findings across Bedrock, Cursor, and Claude Enterprise. **Recommendations** is the AI slice of nOps recommendations: concrete, measured findings about model choice, unused seats, and oversized spend caps, grouped by the rule that produced them. > [!NOTE] > > Recommendations is available to anyone with AI access. No seat tracking project is needed. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Recommendations**. 3. Start with the largest group, expand it, and work down. ## Key features ### Summary cards | Card | What it counts | | - | - | | **AI recommendations** | Open findings on your AI spend. | | **Estimated monthly savings** | Cash off the invoice. Excludes cap headroom. | | **Cap headroom** | Unused spend-limit exposure, not cash. | The split between the last two cards matters. Lowering an unused spend cap reduces risk but changes nothing on the bill (the provider charges actual usage), so headroom is reported separately rather than inflating a savings number you will never see materialize. ### AI Optimization Recommendations The main list groups findings by rule, with a count and a total per group. Expand a group to see individual rows. Each row shows the recommended action, the owner, the owner type, the tool it applies to, and either an estimated monthly saving or a **headroom** figure, plus an effort badge. Filter by tool with the selector in the section header: **All tools**, **Bedrock**, **Cursor**, or **Claude Enterprise**. Each option carries its own count, so you can see where the findings are before switching. ## FAQs > **Why does a finding show 'headroom' instead of a dollar saving?** > > Because it is a spend cap, not usage. The cap is a guardrail; lowering an unused one removes exposure without reducing the invoice. Those figures are deliberately excluded from the savings total. > **How do these differ from the main Recommendations page?** > > They are the same data. This page pre-filters to AI findings and adds the AI-specific summary cards and tool filter, so you do not have to dig them out of a list dominated by storage and compute. > **Nothing shows for a tool I use.** > > A tool only produces findings once nOps has enough measured usage for it. Check that the integration is connected and syncing. ## Related * [AI Anomalies](/ai/anomalies) * [Tracking](/ai/tracking) * [Insights](/inform/insights) * [Amazon Bedrock integration](/integrations/amazon-bedrock) # Requests Source: https://help.nops.io/ai/requests The queue where people ask for a higher AI spend limit and reviewers approve, reject, or ask for more detail. **Requests** is the workflow between "I hit my AI spend cap" and "someone changed it". Seat holders file a limit request with a justification, reviewers see that person's actual usage next to the ask, and approving one writes the new limit at the provider. > [!NOTE] > > Requests needs a seat tracking project with a budget. See [Set up AI seat tracking](/ai/setup). ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Requests**. 3. If you are a reviewer, work the **Open** list. If you need more headroom yourself, switch to **My requests** and click **Request an increase**. The sidebar entry carries a badge with the number of open requests, so you do not have to go looking. ## Key features ### The status rail The left rail is how you slice the queue. | Group | Options | | - | - | | **Show** | **Team requests** or **My requests**. | | **Blocked now** | Seats that are out of headroom right now, with a live count. | | **Status** | **Open**, **Needs info**, **Approved**, **Rejected**, each with a count. | | **Rebalancing** | **Increase** and **Decrease** counts that jump you to [Automated Rebalance](/ai/automated-rebalance). | Everything except **Status** is reviewer-only. If you can only see your own requests, the rail shows just the four status filters. ### Filing a request Switch to **My requests** and click **Request an increase** to open the **Request a limit increase** composer: * **Limit request** shows your current limit for context. * **Desired new limit** is the cap you are asking for. It has to be higher than your current one. nOps suggests a figure that covers your projected spend for the period; click **Use suggested** to take it. * **Why do you need this?** is the justification your reviewer reads: expected traffic, timeline, or launch context. Click **Submit request**. Requests filed this way ask for an ongoing baseline, not a temporary bump; the reviewer decides whether to make it temporary at approval time. If your project has a **Request Prefix**, your request gets a readable ID like `ENG-1001` that you can paste into a ticket or chat. ### Blocked now **Blocked now** lists seats that have run out of limit, whether or not anyone has filed anything. Each entry shows the seat, how much of the limit is used, the current limit next to a proposed one, and a generated **Why this change** summary. Open a request straight from here. It is marked as automatically triggered so it is obvious it did not come from the seat holder. This is the fastest path when someone pings you saying they are stuck. ### Reviewing a request Selecting a request opens a detail pane with the ask, the requester, the current and requested limits, the justification, and that seat's real usage (including model usage) so you can judge the request against behavior rather than a number in isolation. Under **Finish your review**: | Control | What it does | | - | - | | **Applied limit on approval** | The limit actually written if you approve. You can approve a different number than was asked for. | | **Duration after approval** | **Permanent** keeps it as the new lasting cap. **Temporary** is a time-boxed bump for a launch or incident. | | **Approve request** | Applies the limit at the provider. | | **Request more info** | Moves the request to **Needs info** and puts it back to the requester. | | **Reject** | Declines the request. | | **Close** | Closes it without a decision. | A temporary approval defaults its review-again date to the end of the current month, so a launch bump does not silently become permanent. ### Comments and activity Every request has a discussion thread with **Comments** and **Activity** tabs. Type `@` to mention someone. Activity is the audit trail of what happened to the request and when. If your project has issue tracking connected, requests can carry a link to the corresponding ticket. > [!WARNING] > > Approving a request writes the new limit at the provider. Claude Enterprise and Cursor **Enterprise** teams support limit writes. Cursor **Teams**-plan seats and ChatGPT / Codex spend are tracked read-only, so their requests record the decision without changing anything at the provider. ## FAQs > **Who can approve a request?** > > Seat tracking admins. You can also set per-group approvers in [Wallets](/ai/wallets) so requests route to the person who owns that group's spend. > **Why can I only see my own requests?** > > The restricted request-viewer role is scoped to your own requests by design. Reviewers get the **Show** switcher and the team queue. > **Can I approve a different amount than was requested?** > > Yes. Edit **Applied limit on approval** before approving; that is the number that gets written. > **What happens to a temporary approval when it expires?** > > It comes back for review on the date you set, which defaults to the end of the current month. > **Where do requests opened by automation come from?** > > A rebalance run can open one request per affected seat instead of writing limits directly. Those show up in this same queue. See [Automated Rebalance](/ai/automated-rebalance). ## Related * [Automated Rebalance](/ai/automated-rebalance) * [Wallets](/ai/wallets) * [Budgets](/ai/budgets) * [Set up AI seat tracking](/ai/setup) # Set up AI seat tracking Source: https://help.nops.io/ai/setup Create a seat tracking project, connect providers, and let guided setup build your wallets, budget, and first read-only automation check. A **seat tracking project** is what turns raw AI spend into something you can manage: wallets you allocate to, a budget with targets, per-seat limits, and a request queue. Creating one provisions the underlying Cost Allocation showback, Explorer report, and budget for you, then runs a guided setup that fills them in from your recent spend. > [!NOTE] > > Creating and managing a project requires seat tracking admin rights and the **Inform** plan. Anyone with AI access can use [Tracking](/ai/tracking) without a project. ## Before you start Connect at least one AI provider in **Settings → Integrations**: * [Claude Enterprise](/integrations/claude-enterprise): per-seat spend and limits, readable and writable. * [Cursor Admin API](/integrations/cursor-admin-api): per-seat spend for each Cursor team you connect. Limits are readable and writable on Cursor **Enterprise** teams; a Cursor **Teams** plan is read-only. * [OpenAI Enterprise](/integrations/openai-enterprise): tracked as **ChatGPT / Codex**, read-only. Amazon Bedrock and other model spend flows in through your cloud provider integration and shows up on Tracking without a seat provider. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI**, then go to [clara.nops.io/ai-optimization/seat-tracking/new](https://clara.nops.io/ai-optimization/seat-tracking/new). 3. Give the project a **Project name.** For example, `Engineering AI seats`. 4. Optionally set a **Request Prefix**: a short acronym used for limit request IDs, so a request reads as `ENG-1001` instead of a raw identifier. 5. Choose a notification posture, then click **Create project**. ## Key features ### Notification presets Notifications are on by default and start from one of three presets. You can change any of it later in project settings. | Preset | What it sends | | - | - | | **Recommended** | Approvals, alerts, and activity. A good default for most teams. | | **Essential only** | Approval outcomes and critical alerts only. | | **Silent** | Nothing, until you turn specific types back on. | ### Guided setup After the project is created, nOps runs setup for you and shows its progress step by step: 1. Setting up cost allocation 2. Grouping your seats 3. Saving your allocation 4. Setting up your monthly budget 5. Building targets from your recent spend 6. Turning on Observe for your providers 7. Running a first read-only check 8. Syncing groups from Claude 9. Making sure everything looks good Setup is resumable and skips work that is already done, so you can re-run it safely. Steps that can never apply to your account are marked unavailable rather than failed. For example, if a provider exposes no per-seat limit at all, the Observe steps are skipped and the run still finishes. ### What setup configures The budget it creates starts from a fixed, conservative baseline: | Setting | Value | | - | - | | Period | Monthly | | Number of periods | 12 | | Budget type | Bottom Up | | Starting value | Average Monthly Lookback | | Lookback periods | 3 | | Growth rate | 0% | Automation is enabled in **Observe** mode: nOps watches the pool and records what it *would* have done, but never writes a limit back to the provider. Nothing is applied until an admin deliberately changes that on the [Automated Rebalance](/ai/automated-rebalance) tab. > [!NOTE] > > Targets are averaged over whatever spend history actually landed. If your AI spend attribution is younger than the lookback window, the average uses fewer months. Setup tells you which. ### If setup can't finish Two outcomes are common on a brand new account: * **AI spend data is still being prepared.** AI spend attribution typically completes within 24–48 hours of connecting your cloud integration. Your project, wallets, and budget are created; come back and re-run setup to generate targets. * **Per-seat limits are not available.** Either the provider has no such feature, or Anthropic declined the seat-limit scope on your Claude Enterprise key. In the second case, add the scope in Anthropic's console and re-validate the integration. Cost allocation, budgets, and forecasting are unaffected either way. They read warehouse spend, not the limit API. ### Project settings Open project settings from the seat tracking header to adjust what setup created: | Section | What you change | | - | - | | **Project & budget** | Name, request ID prefix, budget schedule, and how the Budgets tab is organized. | | **Provider sync** | Which AI providers sync seat usage and limits into this project. | | **Notifications** | Routing, issue-tracker integration, and per-type preferences. Group-level recipients live in [Wallets](/ai/wallets). | | **Notification activity** | An audit log of notifications sent, failed, and suppressed. | ### Finish the setup path Setup gets you a working project, but a few things are worth doing by hand: * Review the groups in [Wallets](/ai/wallets) and assign any unassigned seats. Wallets stays incomplete until at least one group exists, and Budgets is locked until it does. * Check the generated targets in [Budgets](/ai/budgets) and adjust them before the period gets away from you. * Set an approver per group so [Requests](/ai/requests) route to the right person. ## FAQs > **Can I have more than one project?** > > Yes. Projects are independent. Each has its own wallets, budget, seats, and requests. Switch between them from the project picker in the seat tracking header. > **Is the Request Prefix required?** > > No. It is optional and purely cosmetic: it makes limit request IDs readable, so a request appears as `ENG-1001`. It must be a few letters or digits. > **Will setup change limits at my provider?** > > No. Setup enables automation in **Observe** mode only, which records proposed changes without writing anything back. > **I re-ran setup. Will it overwrite my targets?** > > No. Setup recomputes what is still missing from persisted state. Allocation, generated targets, and existing automation policies are never redone. > **Why is the Budgets tab locked?** > > Budgets unlocks once cost allocation has at least one group. Automated Rebalance unlocks once the budget is ready. ## Related * [AI overview](/ai/introduction) * [Wallets](/ai/wallets) * [Budgets](/ai/budgets) * [Automated Rebalance](/ai/automated-rebalance) * [Budgets (Operate)](/operate/budgets) # Tracking Source: https://help.nops.io/ai/tracking See daily AI spend and token volume by model and platform, then dig into any model or slice it in AI Explorer. **Tracking** is the read-only view of what your AI actually costs: daily spend and token volume, broken down by model and by platform, with a per-model detail pane and a full Explorer scoped to AI spend. > [!NOTE] > > Tracking needs no seat tracking project. It works as soon as an AI provider or cloud integration is sending spend. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Tracking**, or go to [clara.nops.io/ai-optimization/tracking](https://clara.nops.io/ai-optimization/tracking). 3. Pick a date range in the top right. The choice flows through every card, chart, and table on the page. The page has up to two views, **Model Overview** and **AI Explorer**, shown as tabs. Each is enabled separately for your organization, so if only one is available you land on it directly with no tabs. ## Model Overview ### Model usage summary Four cards summarize the selected period: | Card | What it shows | | - | - | | **Total spend** | Spend across all tracked models for the period. | | **Total tokens** | Token volume in the period. | | **Models tracked** | How many models had usage, with a **Top** badge naming the leader by tokens. | | **Platforms** | How many platforms contributed, with their logos. | If a platform is missing because you have not connected it yet, the **Platforms** card offers to connect it inline. ### Spend & budget by client Model usage spend sits next to seat budget targets for the period. Expand a client row to see its projects and per-integration actuals. This is most useful if you manage several organizations. ### Charts * **Daily model usage:** spend and token volume day by day across the period. * **Platform token mix:** each provider's share of the period's token volume. ### Spend and tokens by model The main table ranks models for the period: | Column | Meaning | | - | - | | **Model** | The model name. | | **Spend** | Spend attributed to that model. | | **% of spend** | Its share of the period's total. | | **Tokens** | Token volume. | | **\$ / 1M tokens** | Effective blended rate: the fastest way to spot an expensive model. | Sort by **Spend** or **Tokens**, search by model or platform name, filter to a single platform with the tabs above the table, and use **Export CSV** to pull the filtered list out. ### Model details Click any model to open a detail pane beside the table. It has five sections: | Section | What's in it | | - | - | | **Overview** | A daily spend chart and a **By platform** breakdown. | | **Top users** | Who drove the spend. | | **Variants** | Spend split across the model's variants. | | **Token split** | Input, output, and cache read token mix. | | **Reasoning** | Reasoning token usage. | Drag the pane's left edge to widen it. ### Viewing several organizations If you administer more than one organization, a **View usage for** selector appears next to the date filter. Choose **All portfolios** for a combined roll-up or pick a single organization. Organizations you do not administer are named in a notice below the header and excluded from the roll-up. This is part of **Portfolio Portal**. See [Portfolio Portal](/portfolio/introduction) for the full picture, including how portfolios are set up and which pages currently support it. ## AI Explorer **AI Explorer** (`?view=explorer`) is the full nOps [Explorer](/inform/explorer) pre-scoped to AI spend. Everything Explorer can do (grouping, filtering, charting, saving a report) works here, without you having to build the AI filter each time. Use Model Overview to answer "where is the money going", and AI Explorer when you need a slice Model Overview does not offer. ## FAQs > **Which platforms show up here?** > > Any AI platform nOps has spend for, including your connected seat providers and model spend arriving through a cloud integration such as Amazon Bedrock. > **Why do I only see one tab?** > > Model Overview and AI Explorer are enabled independently. When only one is on, the tab strip is hidden and that view fills the page. > **How far back can I look?** > > Choose from the presets or set a custom range. Custom ranges are capped at roughly a year, so **Last 12 months** and **Year to date** both fit. > **Does the date range persist if I share the URL?** > > Yes. The range is written to the URL, so a link reproduces exactly what you were looking at. ## Related * [AI overview](/ai/introduction) * [Explorer](/inform/explorer) * [Budgets](/ai/budgets) * [Recommendations](/ai/recommendations) # Wallets Source: https://help.nops.io/ai/wallets Split AI spend into groups, assign seats to them, set allocation percentages, and choose who approves each group's limit requests. **Wallets** is where you decide how AI spend is divided. You define value groups, assign seats to them, give each group a share of the pool, and name the people who approve that group's limit requests. Everything downstream (budget targets, forecasts, request routing, rebalancing) reads from what you set here. > [!NOTE] > > Wallets requires seat tracking admin rights. It is the first thing to finish after creating a project: [Budgets](/ai/budgets) stays locked until at least one group exists. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **AI → Wallets**. 3. Create groups that match how you actually think about AI spend: teams, products, cost centers. 4. Assign seats from **Unassigned seats** into those groups. 5. Click **Save**. Under the hood this is an AI-category Cost Allocation showback plus a scoped Explorer report, both provisioned for you. You can open the showback directly at any time. ## Key features ### Groups or users An allocation can be organized two ways, and the choice changes the vocabulary throughout: * **Groups:** the usual case. You create named groups such as `Engineering` and assign seats to them. * **Users:** each seat is its own line. There is no **Add group** button, because the users come from your seat roster. Switch modes in project settings under **Project & budget**. Group mode is what unlocks the vendor roll-up and per-group targets in [Budgets](/ai/budgets). ### The allocation table | Column | What it holds | | - | - | | **Group** (or **User**) | The value the spend is allocated to. | | **Allocation %** | That group's share of the pool. | | **Members** | How many seats are assigned. | | **Approvers** | Who reviews this group's limit requests. Appears once a budget is linked. | | **Spend** | Actual spend for the group. | Above the table, a coverage line tells you exactly where you stand: what percent is allocated to groups and what percent is still unassigned. Use the search box to find a group, and **Add group** to create one. Creating a group does not assign anyone to it; you do that from **Unassigned seats** below. Expand any group row to see the AI seats inside it. ### The FinOps row The first row of the table is **FinOps**: not a spending group, but the people who should hear about everything. Its **Allocation %** cell reads **Notified only**. Expand it to pick who gets FinOps-level notifications and how often. ### Unassigned seats Below the table, **Unassigned seats** lists every seat nOps has discovered that does not belong to a group yet. Search it, then assign seats into groups. **Add by email** opens **Watch a seat by email**, which creates a pending seat for someone who has not shown up in provider spend yet. Assign it to a group and any spend matching that email will follow it automatically. This is how you get ahead of a new hire instead of waiting for their first invoice line. ### Scope, dates, and saving The toolbar above the table controls what the allocation covers: * **Scope chips** name the providers included, or read **All sources**. Edit them to narrow the allocation to specific providers. * A **date range** selector sets the window the spend figures cover. * **CSV** actions let you take the allocation out and bring bulk edits back. * The **More options** menu has **Open in Cost Allocation** to work on the underlying showback directly, and **Link existing…** to point the project at a showback you already built. > [!WARNING] > > Scope changes are not live. Click **Save** to apply them and update the linked Explorer report. Saving also regenerates your budget's planning targets from the new allocation. ### Approvers and notifications The **Approvers** column routes [Requests](/ai/requests) to the person who actually owns that group's spend, rather than sending everything to one admin. Group-level recipients are configured here; project-wide notification routing lives in project settings under **Notifications**. If your provider supports it, you can also sync group membership from the provider rather than maintaining it by hand. Claude Enterprise supports group sync today. ## FAQs > **What happens to spend that isn't allocated to a group?** > > It stays unallocated and shows in the coverage line as unassigned. It still counts toward total AI spend; it just is not attributed to anyone, so it cannot be budgeted or forecast per group. > **Do I have to allocate 100%?** > > No, but the coverage line will keep telling you what is missing, and unassigned spend will not appear in per-group targets. > **Can I use a Cost Allocation showback I already built?** > > Yes. Use **Link existing…** in the **More options** menu instead of letting the project provision a new one. > **Why did my budget targets change after I saved?** > > Saving the allocation regenerates the budget's planning targets so they match the new group structure. Review them in [Budgets](/ai/budgets) after a significant reorganization. > **Someone new joined and isn't listed.** > > Seats appear once the provider reports spend for them. To get ahead of that, use **Add by email** to create a pending seat and assign it now. ## Related * [Budgets](/ai/budgets) * [Requests](/ai/requests) * [Set up AI seat tracking](/ai/setup) * [Explorer](/inform/explorer) # Get AI Optimization default dashboard Source: https://help.nops.io/api-reference/ai-optimization/get-ai-optimization-default-dashboard /openapi.json get /v1/ai-optimization/default-dashboard # List AI-detected anomalies Source: https://help.nops.io/api-reference/ai-optimization/list-ai-detected-anomalies /openapi.json get /v1/ai-optimization/anomalies Returns AI spend anomalies, one entry per headline anomaly. Each entry nests a `breakdown` of the sources, models, and people that drove it, with their unusual hourly windows, plus an `hourly_confirmation` verdict and `hourly_summary` from the hourly re-check. # Set organization AI Optimization default dashboard Source: https://help.nops.io/api-reference/ai-optimization/set-organization-ai-optimization-default-dashboard /openapi.json patch /v1/ai-optimization/default-dashboard Requires an admin-equivalent API key service user. # List anomalies Source: https://help.nops.io/api-reference/anomalies/list-anomalies /openapi.json get /v1/anomalies Returns cost anomalies detected for your organization, one entry per headline anomaly. Each nOps anomaly nests a `breakdown` of the sources, models, and people that drove it, with their unusual hourly windows, plus an `hourly_confirmation` verdict and `hourly_summary` from the hourly re-check. # Budget lookback preview Source: https://help.nops.io/api-reference/budgets/budget-lookback-preview /openapi.json get /v1/budgets/lookback Preview historical spend for budget planning. # Budget lookback query Source: https://help.nops.io/api-reference/budgets/budget-lookback-query /openapi.json post /v1/budgets/lookback Query historical spend for budget planning with filters. # Clear budget planning grid Source: https://help.nops.io/api-reference/budgets/clear-budget-planning-grid /openapi.json delete /v1/budgets/{id}/planning # Create budget Source: https://help.nops.io/api-reference/budgets/create-budget /openapi.json post /v1/budgets # Create budget alert Source: https://help.nops.io/api-reference/budgets/create-budget-alert /openapi.json post /v1/budgets/{id}/alerts # Delete budget Source: https://help.nops.io/api-reference/budgets/delete-budget /openapi.json delete /v1/budgets/{id} # Delete budget alert Source: https://help.nops.io/api-reference/budgets/delete-budget-alert /openapi.json delete /v1/budgets/{id}/alerts/{alertId} # Export budget CSV Source: https://help.nops.io/api-reference/budgets/export-budget-csv /openapi.json get /v1/budgets/{id}/csv # Generate budget planning grid Source: https://help.nops.io/api-reference/budgets/generate-budget-planning-grid /openapi.json post /v1/budgets/{id}/planning/generate # Get budget Source: https://help.nops.io/api-reference/budgets/get-budget /openapi.json get /v1/budgets/{id} # Get budget actuals Source: https://help.nops.io/api-reference/budgets/get-budget-actuals /openapi.json get /v1/budgets/{id}/actuals # Get budget AI seat tracking Source: https://help.nops.io/api-reference/budgets/get-budget-ai-seat-tracking /openapi.json get /v1/budgets/{id}/ai-seat-tracking Deprecated: prefer `GET /v1/seat-tracking/projects/{projectId}`. Per-user AI seat spend and limits for providers enabled on this budget (Claude Enterprise, Cursor). # Get budget alert Source: https://help.nops.io/api-reference/budgets/get-budget-alert /openapi.json get /v1/budgets/{id}/alerts/{alertId} # Get budget planning grid Source: https://help.nops.io/api-reference/budgets/get-budget-planning-grid /openapi.json get /v1/budgets/{id}/planning # Import budget CSV Source: https://help.nops.io/api-reference/budgets/import-budget-csv /openapi.json post /v1/budgets/{id}/csv # List budget alerts Source: https://help.nops.io/api-reference/budgets/list-budget-alerts /openapi.json get /v1/budgets/{id}/alerts # List budgets Source: https://help.nops.io/api-reference/budgets/list-budgets /openapi.json get /v1/budgets # Patch budget planning grid Source: https://help.nops.io/api-reference/budgets/patch-budget-planning-grid /openapi.json patch /v1/budgets/{id}/planning # Save budget planning grid Source: https://help.nops.io/api-reference/budgets/save-budget-planning-grid /openapi.json post /v1/budgets/{id}/planning # Send budget report Source: https://help.nops.io/api-reference/budgets/send-budget-report /openapi.json post /v1/budgets/{id}/send # Update budget Source: https://help.nops.io/api-reference/budgets/update-budget /openapi.json patch /v1/budgets/{id} # Update budget AI seat spend limit Source: https://help.nops.io/api-reference/budgets/update-budget-ai-seat-spend-limit /openapi.json patch /v1/budgets/{id}/ai-seat-tracking/limits Deprecated: prefer `PATCH /v1/seat-tracking/projects/{projectId}/seats/limits`. Set or clear a per-user spend limit override for a Claude Enterprise seat, or a Cursor seat on an Enterprise team with limit management enabled. Other Cursor seats are read-only. # Update budget AI seat tracking providers Source: https://help.nops.io/api-reference/budgets/update-budget-ai-seat-tracking-providers /openapi.json put /v1/budgets/{id}/ai-seat-tracking Deprecated: prefer `PUT /v1/seat-tracking/projects/{projectId}/providers`. Enable or disable AI seat tracking providers on a budget. # Update budget alert Source: https://help.nops.io/api-reference/budgets/update-budget-alert /openapi.json patch /v1/budgets/{id}/alerts/{alertId} # Create business unit Source: https://help.nops.io/api-reference/business-unit-economics/create-business-unit /openapi.json post /v1/business-unit-economics/units # Create business unit economics model Source: https://help.nops.io/api-reference/business-unit-economics/create-business-unit-economics-model /openapi.json post /v1/business-unit-economics # Delete business unit Source: https://help.nops.io/api-reference/business-unit-economics/delete-business-unit /openapi.json delete /v1/business-unit-economics/units/{id} # Delete business unit economics model Source: https://help.nops.io/api-reference/business-unit-economics/delete-business-unit-economics-model /openapi.json delete /v1/business-unit-economics/{id} # Get business unit economics model Source: https://help.nops.io/api-reference/business-unit-economics/get-business-unit-economics-model /openapi.json get /v1/business-unit-economics/{id} # List business unit economics items Source: https://help.nops.io/api-reference/business-unit-economics/list-business-unit-economics-items /openapi.json get /v1/business-unit-economics/{id}/items # List business unit economics models Source: https://help.nops.io/api-reference/business-unit-economics/list-business-unit-economics-models /openapi.json get /v1/business-unit-economics # List business units Source: https://help.nops.io/api-reference/business-unit-economics/list-business-units /openapi.json get /v1/business-unit-economics/units # Portfolio summaries for business unit economics Source: https://help.nops.io/api-reference/business-unit-economics/portfolio-summaries-for-business-unit-economics /openapi.json get /v1/business-unit-economics/summaries # Preview business unit economics spend Source: https://help.nops.io/api-reference/business-unit-economics/preview-business-unit-economics-spend /openapi.json get /v1/business-unit-economics/spend-preview Query params: explorerReportId (required), startDate, endDate (YYYY-MM-DD). # Send business unit economics report Source: https://help.nops.io/api-reference/business-unit-economics/send-business-unit-economics-report /openapi.json post /v1/business-unit-economics/{id}/send # Update business unit Source: https://help.nops.io/api-reference/business-unit-economics/update-business-unit /openapi.json patch /v1/business-unit-economics/units/{id} # Update business unit economics model Source: https://help.nops.io/api-reference/business-unit-economics/update-business-unit-economics-model /openapi.json patch /v1/business-unit-economics/{id} # Upsert business unit economics items Source: https://help.nops.io/api-reference/business-unit-economics/upsert-business-unit-economics-items /openapi.json post /v1/business-unit-economics/{id}/items # List commitments Source: https://help.nops.io/api-reference/commitments/list-commitments /openapi.json get /v1/commitments Reserved commitments API surface. Returns 501 until commitment endpoints are generally available. # Create contract Source: https://help.nops.io/api-reference/contract-tracker/create-contract /openapi.json post /v1/contract-tracker # Delete contract Source: https://help.nops.io/api-reference/contract-tracker/delete-contract /openapi.json delete /v1/contract-tracker/{id} # Get contract Source: https://help.nops.io/api-reference/contract-tracker/get-contract /openapi.json get /v1/contract-tracker/{id} # Get contract burndown Source: https://help.nops.io/api-reference/contract-tracker/get-contract-burndown /openapi.json get /v1/contract-tracker/{id}/burndown # List contracts Source: https://help.nops.io/api-reference/contract-tracker/list-contracts /openapi.json get /v1/contract-tracker # Update contract Source: https://help.nops.io/api-reference/contract-tracker/update-contract /openapi.json patch /v1/contract-tracker/{id} # Allocation history time series Source: https://help.nops.io/api-reference/cost-allocation/allocation-history-time-series /openapi.json post /v1/cost-allocation/{id}/allocation-history # Create allocation rule Source: https://help.nops.io/api-reference/cost-allocation/create-allocation-rule /openapi.json post /v1/cost-allocation/{id}/rules # Create report from showback Source: https://help.nops.io/api-reference/cost-allocation/create-report-from-showback /openapi.json post /v1/cost-allocation/{id}/reports Creates a saved Explorer report pre-scoped to this showback (groupBy and the showback overlay are derived automatically). Optional `config` overrides costType, granularity, date range, and filters. Defaults to the last 30 days when no date is given. # Create showback Source: https://help.nops.io/api-reference/cost-allocation/create-showback /openapi.json post /v1/cost-allocation # Create value combination Source: https://help.nops.io/api-reference/cost-allocation/create-value-combination /openapi.json post /v1/cost-allocation/{id}/value-combinations # Delete allocation rule Source: https://help.nops.io/api-reference/cost-allocation/delete-allocation-rule /openapi.json delete /v1/cost-allocation/{id}/rules/{ruleId} # Delete showback Source: https://help.nops.io/api-reference/cost-allocation/delete-showback /openapi.json delete /v1/cost-allocation/{id} # Delete value combination Source: https://help.nops.io/api-reference/cost-allocation/delete-value-combination /openapi.json delete /v1/cost-allocation/{id}/value-combinations/{combinationId} # Discover dimension values Source: https://help.nops.io/api-reference/cost-allocation/discover-dimension-values /openapi.json post /v1/cost-allocation/{id}/dimension-values # Drill into one allocation value Source: https://help.nops.io/api-reference/cost-allocation/drill-into-one-allocation-value /openapi.json post /v1/cost-allocation/{id}/value-breakdown # Duplicate showback Source: https://help.nops.io/api-reference/cost-allocation/duplicate-showback /openapi.json post /v1/cost-allocation/{id}/duplicate # Get showback Source: https://help.nops.io/api-reference/cost-allocation/get-showback /openapi.json get /v1/cost-allocation/{id} # List allocation rules Source: https://help.nops.io/api-reference/cost-allocation/list-allocation-rules /openapi.json get /v1/cost-allocation/{id}/rules # List showback MV build runs Source: https://help.nops.io/api-reference/cost-allocation/list-showback-mv-build-runs /openapi.json get /v1/cost-allocation/{id}/mv-builds Read materialization ledger rows from Postgres. Optional `requestId` filter. # List showbacks Source: https://help.nops.io/api-reference/cost-allocation/list-showbacks /openapi.json get /v1/cost-allocation # List value combinations Source: https://help.nops.io/api-reference/cost-allocation/list-value-combinations /openapi.json get /v1/cost-allocation/{id}/value-combinations # Percent distribution preview Source: https://help.nops.io/api-reference/cost-allocation/percent-distribution-preview /openapi.json post /v1/cost-allocation/{id}/rules/dimension-preview # Portfolio showback summaries Source: https://help.nops.io/api-reference/cost-allocation/portfolio-showback-summaries /openapi.json get /v1/cost-allocation/summaries # Preview a proposed (unsaved) rule set Source: https://help.nops.io/api-reference/cost-allocation/preview-a-proposed-unsaved-rule-set /openapi.json post /v1/cost-allocation/draft/preview # Reorder allocation rule Source: https://help.nops.io/api-reference/cost-allocation/reorder-allocation-rule /openapi.json post /v1/cost-allocation/{id}/rules/{ruleId}/move # Showback spend preview Source: https://help.nops.io/api-reference/cost-allocation/showback-spend-preview /openapi.json get /v1/cost-allocation/{id}/preview Preview allocated spend for a showback. Optional query params: startDate, endDate (YYYY-MM-DD), and dataSource (`live` default, or `processed` for materialized showback views). # Sync dimension-discovered rules Source: https://help.nops.io/api-reference/cost-allocation/sync-dimension-discovered-rules /openapi.json post /v1/cost-allocation/{id}/rules/sync # Trigger showback MV backfill Source: https://help.nops.io/api-reference/cost-allocation/trigger-showback-mv-backfill /openapi.json post /v1/cost-allocation/{id}/mv-builds Fan out Databricks MV backfill jobs for each month in the inclusive range (max 24 months). Returns a requestId grouping the materialization ledger rows. # Update allocation rule Source: https://help.nops.io/api-reference/cost-allocation/update-allocation-rule /openapi.json patch /v1/cost-allocation/{id}/rules/{ruleId} # Update showback Source: https://help.nops.io/api-reference/cost-allocation/update-showback /openapi.json patch /v1/cost-allocation/{id} # Update value combination Source: https://help.nops.io/api-reference/cost-allocation/update-value-combination /openapi.json patch /v1/cost-allocation/{id}/value-combinations/{combinationId} # Clone Explorer dashboard Source: https://help.nops.io/api-reference/explorer-dashboards/clone-explorer-dashboard /openapi.json post /v1/explorer/dashboards/{id}/clone # Create Explorer dashboard Source: https://help.nops.io/api-reference/explorer-dashboards/create-explorer-dashboard /openapi.json post /v1/explorer/dashboards # Delete Explorer dashboard Source: https://help.nops.io/api-reference/explorer-dashboards/delete-explorer-dashboard /openapi.json delete /v1/explorer/dashboards/{id} # Get Explorer dashboard Source: https://help.nops.io/api-reference/explorer-dashboards/get-explorer-dashboard /openapi.json get /v1/explorer/dashboards/{id} # List Explorer dashboards Source: https://help.nops.io/api-reference/explorer-dashboards/list-explorer-dashboards /openapi.json get /v1/explorer/dashboards # Update Explorer dashboard Source: https://help.nops.io/api-reference/explorer-dashboards/update-explorer-dashboard /openapi.json patch /v1/explorer/dashboards/{id} # Explorer cost heatmap Source: https://help.nops.io/api-reference/explorer/explorer-cost-heatmap /openapi.json post /v1/explorer/heatmap Heatmap-style cost breakdown across dimensions. # Explorer cost history Source: https://help.nops.io/api-reference/explorer/explorer-cost-history /openapi.json post /v1/explorer/history Time-series cost history for the selected filters. # Explorer previous period comparison Source: https://help.nops.io/api-reference/explorer/explorer-previous-period-comparison /openapi.json post /v1/explorer/previous-period Compare current period spend against the previous period. # Explorer summary totals Source: https://help.nops.io/api-reference/explorer/explorer-summary-totals /openapi.json post /v1/explorer/summary Aggregate cost totals for the selected filters and date range. # List dimension values Source: https://help.nops.io/api-reference/explorer/list-dimension-values /openapi.json get /v1/explorer/dimensions/{key}/values List available values for an Explorer dimension key. # Get feed run Source: https://help.nops.io/api-reference/feed/get-feed-run /openapi.json get /v1/feed/{runId} # List feed runs Source: https://help.nops.io/api-reference/feed/list-feed-runs /openapi.json get /v1/feed List Clara Feed runs and schedules. # Create MAP project Source: https://help.nops.io/api-reference/map-manager/create-map-project /openapi.json post /v1/map-manager # Delete MAP project Source: https://help.nops.io/api-reference/map-manager/delete-map-project /openapi.json delete /v1/map-manager/{id} # Get MAP project detail Source: https://help.nops.io/api-reference/map-manager/get-map-project-detail /openapi.json get /v1/map-manager/{id} # List AWS accounts for MAP Manager Source: https://help.nops.io/api-reference/map-manager/list-aws-accounts-for-map-manager /openapi.json get /v1/map-manager/accounts # List MAP project resources Source: https://help.nops.io/api-reference/map-manager/list-map-project-resources /openapi.json get /v1/map-manager/{id}/resources # List MAP projects Source: https://help.nops.io/api-reference/map-manager/list-map-projects /openapi.json get /v1/map-manager # Update MAP project Source: https://help.nops.io/api-reference/map-manager/update-map-project /openapi.json patch /v1/map-manager/{id} # Delete scheduled notification Source: https://help.nops.io/api-reference/notifications/delete-scheduled-notification /openapi.json delete /v1/notifications/scheduled/{id} # Get scheduled notification Source: https://help.nops.io/api-reference/notifications/get-scheduled-notification /openapi.json get /v1/notifications/scheduled/{id} # List scheduled notifications Source: https://help.nops.io/api-reference/notifications/list-scheduled-notifications /openapi.json get /v1/notifications/scheduled # Schedule notification Source: https://help.nops.io/api-reference/notifications/schedule-notification /openapi.json post /v1/notifications/schedule # Update scheduled notification Source: https://help.nops.io/api-reference/notifications/update-scheduled-notification /openapi.json patch /v1/notifications/scheduled/{id} # List recommendations Source: https://help.nops.io/api-reference/recommendations/list-recommendations /openapi.json get /v1/recommendations Returns cost optimization recommendations for your organization. # Create report Source: https://help.nops.io/api-reference/reports/create-report /openapi.json post /v1/reports # Delete report Source: https://help.nops.io/api-reference/reports/delete-report /openapi.json delete /v1/reports/{id} # Get report Source: https://help.nops.io/api-reference/reports/get-report /openapi.json get /v1/reports/{id} # List reports Source: https://help.nops.io/api-reference/reports/list-reports /openapi.json get /v1/reports # Render report Source: https://help.nops.io/api-reference/reports/render-report /openapi.json post /v1/reports/{id}/render # Send report Source: https://help.nops.io/api-reference/reports/send-report /openapi.json post /v1/reports/{id}/send # Update report Source: https://help.nops.io/api-reference/reports/update-report /openapi.json patch /v1/reports/{id} # Create scheduled prompt Source: https://help.nops.io/api-reference/scheduled-prompts/create-scheduled-prompt /openapi.json post /v1/scheduled-prompts # Delete scheduled prompt Source: https://help.nops.io/api-reference/scheduled-prompts/delete-scheduled-prompt /openapi.json delete /v1/scheduled-prompts/{id} # Enable scheduled prompt Source: https://help.nops.io/api-reference/scheduled-prompts/enable-scheduled-prompt /openapi.json post /v1/scheduled-prompts/{id}/enable # Get scheduled prompt Source: https://help.nops.io/api-reference/scheduled-prompts/get-scheduled-prompt /openapi.json get /v1/scheduled-prompts/{id} # List scheduled prompts Source: https://help.nops.io/api-reference/scheduled-prompts/list-scheduled-prompts /openapi.json get /v1/scheduled-prompts # Run scheduled prompt now Source: https://help.nops.io/api-reference/scheduled-prompts/run-scheduled-prompt-now /openapi.json post /v1/scheduled-prompts/{id}/run # Update scheduled prompt Source: https://help.nops.io/api-reference/scheduled-prompts/update-scheduled-prompt /openapi.json patch /v1/scheduled-prompts/{id} # Approve seat tracking automation run Source: https://help.nops.io/api-reference/seat-tracking/approve-seat-tracking-automation-run /openapi.json post /v1/seat-tracking/projects/{projectId}/automation/runs/{runId}/approve Approve and apply a pending rebalance run. Not reachable via MCP. # Bulk update seat tracking spend limits Source: https://help.nops.io/api-reference/seat-tracking/bulk-update-seat-tracking-spend-limits /openapi.json patch /v1/seat-tracking/projects/{projectId}/seats/limits/bulk Update Claude Enterprise spend limits for up to 50 users in one call. Not reachable via MCP. # Create seat tracking limit request Source: https://help.nops.io/api-reference/seat-tracking/create-seat-tracking-limit-request /openapi.json post /v1/seat-tracking/projects/{projectId}/requests Create a new seat limit request. # Create seat tracking limit request comment Source: https://help.nops.io/api-reference/seat-tracking/create-seat-tracking-limit-request-comment /openapi.json post /v1/seat-tracking/projects/{projectId}/requests/{requestId}/comments Add a comment to a limit request. Any user with access to the request can comment. # Create seat tracking project Source: https://help.nops.io/api-reference/seat-tracking/create-seat-tracking-project /openapi.json post /v1/seat-tracking/projects Create a new AI seat tracking project. # Decide seat tracking limit request Source: https://help.nops.io/api-reference/seat-tracking/decide-seat-tracking-limit-request /openapi.json post /v1/seat-tracking/projects/{projectId}/requests/{requestId}/decision Approve, request changes, close, or reject a limit request. # Delete seat tracking limit request comment Source: https://help.nops.io/api-reference/seat-tracking/delete-seat-tracking-limit-request-comment /openapi.json delete /v1/seat-tracking/projects/{projectId}/requests/{requestId}/comments/{commentId} Delete an existing comment on a limit request. # Delete seat tracking project Source: https://help.nops.io/api-reference/seat-tracking/delete-seat-tracking-project /openapi.json delete /v1/seat-tracking/projects/{projectId} Delete a seat tracking project. Optionally delete the linked budget and reports. # Get provider groups Source: https://help.nops.io/api-reference/seat-tracking/get-provider-groups /openapi.json get /v1/seat-tracking/projects/{projectId}/provider-groups List groups exposed by a provider (Claude Enterprise, Cursor). # Get seat tracking automation policy Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-automation-policy /openapi.json get /v1/seat-tracking/projects/{projectId}/automation Read the automation policy for a provider in a project. # Get seat tracking automation scorecard Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-automation-scorecard /openapi.json get /v1/seat-tracking/projects/{projectId}/automation/scorecard Get the autonomy scorecard for a provider in a project. # Get seat tracking grid Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-grid /openapi.json get /v1/seat-tracking/projects/{projectId}/seats Per-user AI seat spend, limits, and provider state for the project (Claude Enterprise, Cursor). # Get seat tracking groups Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-groups /openapi.json get /v1/seat-tracking/projects/{projectId}/groups Read the group config and allocation layout for a seat tracking project. # Get seat tracking limit request Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-limit-request /openapi.json get /v1/seat-tracking/projects/{projectId}/requests/{requestId} Get a single limit request with comments and history. # Get seat tracking notify routes Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-notify-routes /openapi.json get /v1/seat-tracking/projects/{projectId}/notify-routes Read notification routes for limit requests in a project. # Get seat tracking project Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-project /openapi.json get /v1/seat-tracking/projects/{projectId} Get summary and metadata for a seat tracking project. # Get seat tracking projections Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-projections /openapi.json get /v1/seat-tracking/projects/{projectId}/projections Projected per-user spend and at-risk seats for a project. # Get seat tracking providers Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-providers /openapi.json get /v1/seat-tracking/projects/{projectId}/providers List providers enabled for this seat tracking project. # Get seat tracking reviewer assignments Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-reviewer-assignments /openapi.json get /v1/seat-tracking/projects/{projectId}/reviewer-assignments List reviewer assignments for limit requests in a project. # Get seat tracking spend history Source: https://help.nops.io/api-reference/seat-tracking/get-seat-tracking-spend-history /openapi.json get /v1/seat-tracking/projects/{projectId}/spend-history Historical per-user and per-provider spend snapshots for a project. # Get seat user context Source: https://help.nops.io/api-reference/seat-tracking/get-seat-user-context /openapi.json get /v1/seat-tracking/projects/{projectId}/seats/{userId}/context Retrieve a manager or individual usage context payload for a seat user. # Get seat user model usage Source: https://help.nops.io/api-reference/seat-tracking/get-seat-user-model-usage /openapi.json get /v1/seat-tracking/projects/{projectId}/seats/{userId}/model-usage Retrieve model-mix usage details for a seat user. # Get seat user usage Source: https://help.nops.io/api-reference/seat-tracking/get-seat-user-usage /openapi.json get /v1/seat-tracking/projects/{projectId}/seats/{userId}/usage Public API equivalent of the internal `my-usage` route, with an explicit `{userId}` path parameter because API-key callers are service users. # Get seat user usage history Source: https://help.nops.io/api-reference/seat-tracking/get-seat-user-usage-history /openapi.json get /v1/seat-tracking/projects/{projectId}/seats/{userId}/usage-history Public API equivalent of the internal `my-usage-history` route, with an explicit `{userId}` path parameter. # List seat tracking automation evaluations Source: https://help.nops.io/api-reference/seat-tracking/list-seat-tracking-automation-evaluations /openapi.json get /v1/seat-tracking/projects/{projectId}/automation/evaluations List automation evaluations for a provider in a project. # List seat tracking automation runs Source: https://help.nops.io/api-reference/seat-tracking/list-seat-tracking-automation-runs /openapi.json get /v1/seat-tracking/projects/{projectId}/automation/runs List rebalance runs for a seat tracking project. # List seat tracking limit requests Source: https://help.nops.io/api-reference/seat-tracking/list-seat-tracking-limit-requests /openapi.json get /v1/seat-tracking/projects/{projectId}/requests List limit requests for a seat tracking project. # List seat tracking projects Source: https://help.nops.io/api-reference/seat-tracking/list-seat-tracking-projects /openapi.json get /v1/seat-tracking/projects List AI seat tracking projects for your organization. # Provision seat tracking cost allocation Source: https://help.nops.io/api-reference/seat-tracking/provision-seat-tracking-cost-allocation /openapi.json post /v1/seat-tracking/projects/{projectId}/cost-allocation Create or reuse a Cost Allocation showback for this seat tracking project. # Run seat tracking automation Source: https://help.nops.io/api-reference/seat-tracking/run-seat-tracking-automation /openapi.json post /v1/seat-tracking/projects/{projectId}/automation/run Trigger a manual automation run for a provider. Subject to a daily quota. Not reachable via MCP. # Undo seat tracking automation run Source: https://help.nops.io/api-reference/seat-tracking/undo-seat-tracking-automation-run /openapi.json post /v1/seat-tracking/projects/{projectId}/automation/runs/{runId}/undo Undo a previously applied rebalance run. Not reachable via MCP. # Update seat tracking automation policy Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-automation-policy /openapi.json put /v1/seat-tracking/projects/{projectId}/automation Configure detection thresholds, approval mode, and pool settings. # Update seat tracking group allocation layout Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-group-allocation-layout /openapi.json patch /v1/seat-tracking/projects/{projectId}/groups Change how group allocations are laid out. # Update seat tracking group targets Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-group-targets /openapi.json put /v1/seat-tracking/projects/{projectId}/groups/targets Set or override group-level spend targets for a seat tracking project. # Update seat tracking groups Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-groups /openapi.json put /v1/seat-tracking/projects/{projectId}/groups Enable or disable groups and link a cost-allocation showback. # Update seat tracking limit request Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-limit-request /openapi.json patch /v1/seat-tracking/projects/{projectId}/requests/{requestId} Edit the proposed limit, justification, or duration intent of a request. # Update seat tracking limit request comment Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-limit-request-comment /openapi.json patch /v1/seat-tracking/projects/{projectId}/requests/{requestId}/comments/{commentId} Edit an existing comment on a limit request. # Update seat tracking notify routes Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-notify-routes /openapi.json put /v1/seat-tracking/projects/{projectId}/notify-routes Configure who receives limit request notifications. # Update seat tracking project Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-project /openapi.json patch /v1/seat-tracking/projects/{projectId} Update a seat tracking project name, request key prefix, or issue tracker. # Update seat tracking providers Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-providers /openapi.json put /v1/seat-tracking/projects/{projectId}/providers Enable or disable AI seat tracking providers for a project. # Update seat tracking reviewer assignments Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-reviewer-assignments /openapi.json put /v1/seat-tracking/projects/{projectId}/reviewer-assignments Assign reviewers for limit requests by user or group. # Update seat tracking spend limit Source: https://help.nops.io/api-reference/seat-tracking/update-seat-tracking-spend-limit /openapi.json patch /v1/seat-tracking/projects/{projectId}/seats/limits Set or clear a per-user spend limit override for a Claude Enterprise seat, or a Cursor seat on an Enterprise team with limit management enabled. Other Cursor seats are read-only. Not reachable via MCP. # Amazon Web Services - Commitment Management Setup Source: https://help.nops.io/aws/commitment-management-setup Enable AWS Commitment Management in nOps using CloudFormation. Deploy three IAM roles for cross-account access, commitment purchasing, and inventory reads. ## FAQs > **Is this the same as the initial AWS integration setup?** > > No. The initial [AWS integration setup](/aws/integration-setup) connects **billing and cost visibility** (CUR + integration IAM role). Commitment Management uses **separate IAM roles** deployed via CloudFormation for purchasing and managing Reserved Instances and Savings Plans. > **Does the central role have to be in the payer account?** > > No. Deploy `NopsCMCrossAccountAssume` in **any account in your AWS Organization**. Many teams use the management (payer) account for convenience, but a dedicated member account works the same way. What **does** require payer access: launching **StackSets** for the child read role and deploying the **payer read role** directly in the management account (StackSets skip that account by default). > **Where is the ShareSave role deployed?** > > The **ShareSave** role is deployed in a **dedicated child account** within your AWS Organization. Commitments purchased from any account in an organization automatically apply across all accounts via RI/SP sharing. Using a dedicated account isolates purchase permissions from your payer account, a security best practice. > **What permissions does nOps get?** > > Three roles with scoped permissions: a **central role** (can only assume child read roles), a **child read role** (read-only EC2, RDS, ElastiCache, Savings Plans, and Organizations metadata), and a **ShareSave role** (commitment purchasing, Cost Explorer, and Organizations read). See the full breakdown in each step below or the [Permissions & Resources](/aws/permissions-and-resources) reference. > **Can I review the exact IAM policies before deploying?** > > Yes. Every permission is documented in this guide and in the [Permissions & Resources](/aws/permissions-and-resources) reference page. The CloudFormation templates are also available for review before you deploy them. > **Do I need Inform to view Commitment Inventory?** > > No. [Commitment Inventory](/optimize/commitment-inventory) is included on every nOps plan for members, admins, and owners when your AWS integration is **active**. Inform is only required to **email** or **schedule** inventory reports. This CM setup is for purchasing and for the full cross-account inventory read path, not for opening the Inventory page itself. *** ## Overview **You're enabling Commitment Management for AWS**, giving nOps the ability to view, quote, and purchase Reserved Instances and Savings Plans on your behalf across your AWS Organization. Open your active AWS integration card in [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings) and choose **Enable CM**. You'll complete **four steps**: 1. **Central Role:** Deploy the central role in any org account; deploy child read roles via StackSets from the management account; capture ARNs 2. **ShareSave Role:** Dedicated child account: deploy ShareSave role for commitment purchasing 3. **Confirm Details:** Save role ARNs and external IDs to nOps 4. **Verify Access:** Platform checks assume-role chains and API access **Prerequisite:** Complete [AWS integration setup](/aws/integration-setup) first (Legacy CUR + integration IAM role). > [!NOTE] > > **Who can do this:** Only **Admin** users in your nOps organization can enable or manage Commitment Management. See [Users and roles](/platform/users). *** ## Prerequisites Before you start, make sure you can: * Access the **payer (management) account** for **IAM**, **CloudFormation**, and **AWS Organizations** * Run **CloudFormation StackSets** from the payer account (or a delegated administrator) with trusted access enabled * Have the **Savings Analysis** integration already active on the same payer account *** ## CloudFormation templates nOps uses three CloudFormation templates. Each creates a single IAM role with scoped permissions. | Template | Role created | Deploy in | Purpose | | - | - | - | - | | `nops-cm-central-role.yaml` | `NopsCMCrossAccountAssume` | Any org account (not required to be payer) | Assume child read roles across member accounts | | `nops-cm-child-role.yaml` | `NopsCMReadEC2Instances` | Each member account (via StackSets) | Read-only EC2, RDS, ElastiCache, Savings Plans, and Organizations metadata | | `nops-cm-sharesave-role.yaml` | `nops-sharesave-mgt` | Dedicated child account | Commitment purchasing, Cost Explorer, Organizations read | *** ## Step 1: Central Role The central role can be deployed in **any account in your AWS Organization**. It does not have to be the payer (management) account. Many teams use the management account for convenience, but a dedicated member account works the same way. > [!NOTE] > > You still need access to the **payer (management) account** (or a delegated StackSets administrator) for **Step 2** (child read role StackSets) and **Step 3** (payer read role). **1. Open Enable CM in nOps** In [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings), open your AWS integration and choose **Enable CM**. **2. Enter management (payer) account ID** Enter your **AWS Organization management (payer) account ID** (12 digits). nOps uses this to identify your organization and to pre-fill StackSet defaults. It is not required to be the account where you deploy the central role. **3. Copy External ID (Central)** Copy the **External ID (Central)** from nOps. It is passed automatically when you open the central stack. Keep it for **Confirm Details** later. **4. Deploy central role (single stack)** Sign into the AWS account where you want the central role, then click **Deploy Central Role (CloudFormation)**. This opens the AWS CloudFormation console with the template pre-loaded. Review the stack parameters: * **NopsCMAssumerRoleArn:** pre-filled with the nOps bridge role ARN (no changes needed) * **ExternalId:** pre-filled with the External ID from nOps Acknowledge the IAM resource creation checkbox and click **Create stack**. Wait for **CREATE\_COMPLETE**. > [!NOTE] > > The central role `NopsCMCrossAccountAssume` has a single permission: `sts:AssumeRole` scoped to `arn:aws:iam::*:role/NopsCMReadEC2Instances`. It cannot access any other resources. > **Central role: trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam::861341088565:role/NopsCMCentralClientAccountAssume" > }, > "Action": "sts:AssumeRole", > "Condition": { > "StringEquals": { > "sts:ExternalId": "" > } > } > } > ] > } > ``` > **Central role: permissions policy (NopsCMAssumeChildRoles)** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": "sts:AssumeRole", > "Resource": "arn:aws:iam::*:role/NopsCMReadEC2Instances" > } > ] > } > ``` **5. Deploy child read role (StackSets)** Click **Deploy Child Role (CloudFormation StackSets)** to open the StackSets console. nOps copies the child role template URL to your clipboard. Paste it into **Amazon S3 URL** in the StackSets wizard. Deploy to all member accounts in your organization (or specific OUs). The child read role is **read-only**. It can only describe existing instances and commitments. > **Child read role: trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam:::role/NopsCMCrossAccountAssume" > }, > "Action": "sts:AssumeRole" > } > ] > } > ``` > **Child read role: permissions policy (NopsCMReadEC2Policy)** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "ec2:DescribeInstances", > "ec2:DescribeReservedInstances", > "savingsplans:DescribeSavingsPlans", > "rds:DescribeDBInstances", > "rds:DescribeReservedDBInstances", > "elasticache:DescribeReservedCacheNodes", > "organizations:ListAccounts" > ], > "Resource": "*" > } > ] > } > ``` **6. Deploy payer read role (single stack)** StackSets do **not** deploy to the payer (management) account by default. Click **Deploy Payer Read Role (CloudFormation)** to deploy the same `NopsCMReadEC2Instances` role directly in the payer account. This ensures nOps can also read commitment data from the management account itself, not just member accounts. **7. Paste Central and Read role ARNs** After all stacks complete: * **Central Role ARN:** e.g. `arn:aws:iam:::role/NopsCMCrossAccountAssume` (from the account where you deployed Step 1) * **Read Role ARN:** e.g. `arn:aws:iam:::role/NopsCMReadEC2Instances` (from any StackSet instance) **8. Continue** Click **Next** to move to **ShareSave Role**. *** ## Step 2: ShareSave Role This step deploys the **ShareSave** purchasing role in a **dedicated child account** within your AWS Organization. This role grants nOps the permissions to purchase and manage commitments on your behalf. > [!NOTE] > > Using a dedicated child account isolates purchase permissions from your payer account. Commitments purchased from any account in your organization automatically apply across all accounts via RI/SP sharing. **1. Create or identify the dedicated account** Create a new child account in your AWS Organization (recommended name: **nops-cm-sharesave**) or use an existing dedicated account. Enter its **12-digit account ID** in the nOps wizard. **2. Deploy ShareSave role in the dedicated account** Sign into the **dedicated child account**, then click **Deploy ShareSave Role (CloudFormation)**. Review the stack parameters: * **NopsCrossAccountRoleArn:** pre-filled with the nOps bridge role ARN (no changes needed) * **ExternalId:** pre-filled with the ShareSave External ID from nOps Acknowledge the IAM resource creation checkbox and click **Create stack**. Wait for **CREATE\_COMPLETE**. > **ShareSave role: trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam::861341088565:role/CrossAccountSharesaveMgt" > }, > "Action": "sts:AssumeRole", > "Condition": { > "StringEquals": { > "sts:ExternalId": "" > } > } > } > ] > } > ``` > **ShareSave role: AWS managed policies** > > The ShareSave role attaches five AWS managed policies: > > | Managed Policy | Purpose | > | - | - | > | `AWSSavingsPlansFullAccess` | Create, describe, and manage Savings Plans | > | `AWSOrganizationsReadOnlyAccess` | List and describe organization accounts | > | `AWSCloudTrail_ReadOnlyAccess` | Read CloudTrail event history for audit | > | `AWSSupportAccess` | Create and view support cases | > | `ServiceQuotasFullAccess` | View and request service quota increases | > **ShareSave role: inline policy (NopsSharesaveMgtPolicy)** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "ec2:CreateTags", > "ec2:DescribeReservedInstances", > "ec2:DescribeReservedInstancesListings", > "ec2:DescribeReservedInstancesModifications", > "ec2:DescribeReservedInstancesOfferings", > "ec2:ModifyReservedInstances", > "ec2:PurchaseReservedInstancesOffering", > "ec2:CreateReservedInstancesListing", > "ec2:CancelReservedInstancesListing", > "ec2:DeleteQueuedReservedInstances", > "ec2:GetReservedInstancesExchangeQuote", > "ec2:AcceptReservedInstancesExchangeQuote", > "rds:DescribeReservedDBInstances", > "rds:DescribeReservedDBInstancesOfferings", > "rds:PurchaseReservedDBInstancesOffering", > "elasticache:DescribeReservedCacheNodes", > "elasticache:DescribeReservedCacheNodesOfferings", > "elasticache:PurchaseReservedCacheNodesOffering", > "savingsplans:ReturnSavingsPlan", > "savingsplans:TagResource", > "ce:*" > ], > "Resource": "*" > } > ] > } > ``` **3. Paste ShareSave Role ARN and external ID** After the stack completes, paste **ShareSave Role ARN** (expected form: `arn:aws:iam:::role/nops-sharesave-mgt`) and confirm **External ID (Sharesave)** matches what nOps shows. **4. Continue** Click **Next** for **Confirm Details**. *** ## Step 3: Confirm Details Review and edit fields so they match what you deployed: * **Central Role ARN:** `NopsCMCrossAccountAssume` in the account where you deployed the central role (any org account) * **Read Role ARN:** `NopsCMReadEC2Instances` in a member account reached by your StackSet * **ShareSave Role ARN:** `nops-sharesave-mgt` in the dedicated child account * **Child Role Name** (optional): defaults to **`NopsCMReadEC2Instances`** if unchanged * **External ID (Central)** and **External ID (Sharesave):** must both be set and **must not** be identical Click **Save & Continue** to persist configuration before verification. *** ## Step 4: Verify Access Click **Run Verification** (or advance with **Next** from the prior step, which triggers the same check). nOps performs server-side checks that validate both role assumption chains and API-level permissions: | Check | What it verifies | | - | - | | Assume ShareSave role | Bridge → `nops-sharesave-mgt` (with ShareSave external ID) | | EC2 reserved instances read | `ec2:DescribeReservedInstances` via ShareSave role | | Savings Plans read | `savingsplans:DescribeSavingsPlans` via ShareSave role | | RDS reserved DB instances read | `rds:DescribeReservedDBInstances` via ShareSave role | | Organizations read *(optional)* | `organizations:ListAccounts` via ShareSave role (informational only; not required when the ShareSave role is in a dedicated child account) | | Assume central/child read role | Bridge → `NopsCMCrossAccountAssume` → `NopsCMReadEC2Instances` (3-hop chain) | | Child account EC2 RI read | `ec2:DescribeReservedInstances` via child read role | If any check fails, verify: * **Trust policies:** correct nOps bridge role ARN in the `Principal` * **External IDs:** match what nOps shows (central and ShareSave must differ) * **StackSet deployment scope:** ensure all target accounts/OUs are included * **Managed policies:** all five AWS managed policies attached to the ShareSave role When all checks pass, Commitment Management is marked **enabled** for that integration. *** ## Troubleshooting > **Check fails: Assume ShareSave role** > > * Verify you deployed `nops-cm-sharesave-role.yaml` in the **dedicated child account** > * Confirm the `NopsCrossAccountRoleArn` parameter was left at the default value > * Check that the `ExternalId` parameter matches the **ShareSave External ID** shown in nOps > * Ensure the CloudFormation stack reached **CREATE\_COMPLETE** (not ROLLBACK) > **Check fails: Assume central/child read role** > > * Verify `nops-cm-central-role.yaml` was deployed and note which account hosts `NopsCMCrossAccountAssume` (it does not have to be the payer account) > * Confirm the **Central Role ARN** in nOps matches that account > * Confirm the `ExternalId` parameter matches the **Central External ID** shown in nOps > * Ensure the StackSet for `nops-cm-child-role.yaml` deployed successfully to the target member accounts > * If testing with the payer account itself, ensure you also deployed the child read role directly in the payer account (StackSets skip the management account by default) > **Verification passes but operations fail later** > > * Verification checks **read** permissions. If a purchase operation fails with `UnauthorizedOperation`, check that all five AWS managed policies are attached to the ShareSave role (especially `AWSSavingsPlansFullAccess`) > * If you see `AccessDenied` on a specific service (e.g., RDS), confirm the inline policy `NopsSharesaveMgtPolicy` is present on the role *** ## Related guides > **[AWS integration setup](/aws/integration-setup)** > > Legacy CUR in S3 and the integration cross-account role for cost visibility. > **[Permissions & Resources](/aws/permissions-and-resources)** > > Complete reference of all IAM roles, policies, and trust relationships for both Savings Analysis and Commitment Management. > **[Platform integrations](/platform/integrations)** > > All cloud integrations and setup entry points. # Amazon Web Services - Integration Setup Source: https://help.nops.io/aws/integration-setup Onboard your AWS payer account for a savings analysis. A step-by-step walkthrough to connect your payer account so nOps can analyze your spend and surface optimization insights. ## FAQs > **Who can connect or manage an AWS integration in nOps?** > > Only **Admin** users in your organization can connect AWS, remove an integration, or use **Manage** on an existing integration. **Members** cannot. See [Users and roles](/platform/users). > **How does nOps use my Cost and Usage Report?** > > nOps reads **Legacy CUR** files that AWS delivers to **Amazon S3**. You configure the export in the AWS Billing console (or let the CloudFormation option create it) and tell nOps the bucket name, export name, and optional S3 prefix so ingestion can find your data. nOps can also read a **CUR 2.0** export alongside it for Amazon Bedrock details. See [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports). > **Can I use an existing CUR export instead of creating a new one?** > > Yes. You can **bring your own** Legacy CUR instead of creating a new export, as long as it meets [nOps CUR requirements](#bring-your-own-cur). In Step 2, enter your existing export name and the S3 bucket (and prefix) where AWS already delivers it. The suggested name `nops_cur_{your_nops_client_id}_hourly` is only for teams that choose to create a new export in AWS. > **I'm already connected. Can I add CUR 2.0 later?** > > Yes. Your Legacy CUR keeps working, and you add CUR 2.0 from **Manage** without redeploying your original stack. See [Add CUR 2.0 to an existing integration](#add-cur-2-0-to-an-existing-integration). > **What happens if my existing CUR does not meet the requirements?** > > nOps may fail to ingest data, show incomplete cost visibility, or miss resource-level detail. Update the export in **Billing > Data Exports** to match the [requirements checklist](#cur-requirements-checklist), or create a separate Legacy CUR export that does and point nOps at that bucket and export name. > **Is this the same as AWS Commitment Management setup?** > > No. This flow connects **billing and cost visibility** (CUR + integration IAM role). **Commitment Management** is optional and uses separate CloudFormation templates and roles. After this integration is active, Admins/Owners can start CM from the AWS integration card (**Enable CM**). See [AWS Commitment Management setup](/aws/commitment-management-setup). > **Can nOps deploy the IAM role and policies for me?** > > Yes. In **Step 2**, choose **CloudFormation (Recommended)**. Enter an S3 bucket name, choose a permission level, and click **Deploy Integration Stack (CloudFormation)** to launch AWS CloudFormation with the template pre-filled. The stack creates a **new** S3 bucket with the name you entered, your Legacy CUR export, your CUR 2.0 export, the customer-managed IAM policies for your permission level, and the cross-account role. Copy the **RoleArn** output back into nOps to finish. If you'd rather create the policies and role yourself, choose **Manual IAM** instead and follow [Step 3](#step-3-iam-policy-creation-manual-iam). > > Two things to know before you deploy: > > * **The bucket name must not already exist in your account.** The stack creates it, so a name that is already taken fails the deployment. If you already have a CUR bucket, see the next question. > * **Deploy in `us-east-1`.** The nOps link opens CloudFormation in `us-east-1` for you, so don't change the region. AWS only offers the Legacy CUR resource type there, and deploying elsewhere fails with `Unrecognized resource types: [AWS::CUR::ReportDefinition]`. > **I already have an S3 bucket for my CUR. Can I still use the CloudFormation option?** > > Yes, with one extra step. In the CloudFormation console, set the **CreateCurBucket** parameter to `false` and enter your existing bucket name. > > When you do this, nOps does **not** touch your bucket's policy. A bucket policy is a single document, so writing one would replace everything already on your bucket, so we'd rather leave your permissions alone. That means your bucket must already let AWS billing deliver the report: `s3:GetBucketAcl`, `s3:GetBucketPolicy`, and `s3:PutObject` for the `billingreports.amazonaws.com` service. Buckets that already receive a CUR normally have this. If yours doesn't, AWS fails the export with *"Failed to verify customer bucket permission"*. Add the grant and redeploy. > > The stack's **CurBucketPolicyManaged** output tells you which happened: `true` means nOps created the bucket and its delivery policy, `false` means the bucket is yours to grant. > > The same applies to CUR 2.0: an existing bucket must also allow `bcm-data-exports.amazonaws.com`. See [Let AWS Data Exports write to an existing bucket](#let-aws-data-exports-write-to-an-existing-bucket). > **What is the difference between Minimum Platform and Full Platform permissions?** > > Choose a **permission level** at the top of the setup screen (**Step 2** with CloudFormation, **Step 3** with Manual IAM): > > * **Minimum Platform** (`nOpsMinimumPlatformPermissions`): **Savings Analysis**: read-focused access for CUR ingestion, Cost Explorer commitment visibility, and organization metadata. Use this when you only need cost and savings insights. > * **Full Platform** (`nOpsFullPlatformPermissions`): **Inform & Operate**: includes **all Minimum Platform permissions** plus additional read and write actions for broader inventory, recommendations, and operational workflows. Full Platform also attaches the AWS-managed `ReadOnlyAccess` policy and a customer-managed Deny policy. > > Minimum Platform uses two customer-managed policies (`nOpsBucketPolicy` + `nOpsMinimumPlatformPermissions`). Full Platform uses four customer-managed policies (`nOpsBucketPolicy`, `nOpsFullPlatformDenyList1`, `nOpsFullPlatformDenyList2`, `nOpsFullPlatformPermissions`) plus the AWS-managed `ReadOnlyAccess` policy. See [Permissions & Resources](/aws/permissions-and-resources) for the full breakdown. > **My stack deployed fine, but the ce:… permission checks fail with "User not enabled for cost explorer access"** > > This is an AWS account setting, not a problem with your policies. AWS blocks Cost Explorer API calls until the account is opted in, so redeploying the stack won't clear it. Follow [Turn on Cost Explorer in your payer account](#turn-on-cost-explorer-in-your-payer-account), then re-run **Check**. The rest of your integration keeps working in the meantime. > **Why is Cluster Name missing in Kubernetes Explorer?** > > Kubernetes Explorer **Cluster Name** needs Amazon EKS [Split Cost Allocation Data (SCAD)](https://docs.aws.amazon.com/cur/latest/userguide/split-cost-allocation-data.html) **and** the AWS-generated cost allocation tag **`aws:eks:cluster-name`** active in your payer account. Without that tag, nOps never receives the warehouse column `resource_tags_aws_eks_cluster_name`, and Explorer shows that Cluster Name isn't available for this account. > > Check all three: > > 1. In **Billing and Cost Management** preferences, opt in to Split Cost Allocation Data for **Amazon EKS** (payer account). See [Enabling Split Cost Allocation Data](https://docs.aws.amazon.com/cur/latest/userguide/enabling-split-cost-allocation-data.html). > 2. On your **Legacy CUR** export, enable **Split cost allocation data** under Additional export content (CloudFormation-created exports already include this; bring-your-own must match). > 3. Under **Cost allocation tags**, confirm **`aws:eks:cluster-name`** is **Active**. AWS enables this tag by default for new accounts, but a tag that was previously deactivated stays off until you activate it again. > > After you activate the tag, allow about **24–48 hours** for CUR delivery and nOps ingest before Cluster Name appears in Explorer. *** ## Overview **You're setting up savings analysis for AWS**: linking your organization's billing data to nOps so we can help you understand costs and find ways to save. The in-app wizard walks you through it. Open **Connect Amazon Web Services** from [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings). The wizard has these steps: 1. **Account:** Payer account ID, integration name, optional AWS Organization ID 2. **Setup:** Choose **CloudFormation (Recommended)** or **Manual IAM**: * **CloudFormation:** Deploy one stack that creates the S3 bucket, your Legacy CUR export, your CUR 2.0 export, and the IAM role. This is the whole setup; there is no Step 3. * **Manual IAM:** Configure your Legacy CUR in **Billing > Data Exports** (new export or [bring your own](#bring-your-own-cur)) and enter the bucket, export name, and path in nOps. Either way, the step includes an **AWS CUR 2.0** section. See [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports). 3. **IAM Policy Creation** (Manual IAM only): Choose **Minimum** or **Full Platform** permissions, create customer-managed policies and a cross-account role with an **external ID**, then submit the **Role ARN** 4. **Verify:** Run verification to confirm nOps can access your account > [!TIP] > > **Not sure which to pick?** Choose **CloudFormation** unless you already have a Legacy CUR you want to reuse as-is, or your security team requires that IAM be created by hand. For AWS documentation on creating the export, see [Creating a Legacy CUR export](https://docs.aws.amazon.com/cur/latest/userguide/dataexports-create-legacy.html). > [!NOTE] > > **Who can do this:** Only **Admin** users in your nOps organization can connect or manage AWS integrations. **Members** cannot. See [Users and roles](/platform/users). Backend APIs enforce the same restriction. *** ## Prerequisites Before you start, make sure you can: * Use the **payer (management) account** (or have someone available who can) for **AWS Billing** and **IAM** * Create or use an **S3 bucket** where the Legacy CUR is (or will be) delivered, including an [existing export you bring yourself](#bring-your-own-cur), if it meets the requirements * Create **IAM policies** and a **cross-account IAM role** in your account * Turn on **Cost Explorer** in the payer account (see below). This is separate from the IAM policies * Optional: know your **AWS Organizations** ID (`o-…`) if you want to group this integration in nOps ### Turn on Cost Explorer in your payer account AWS blocks all Cost Explorer API calls until the account is opted in, **no matter which IAM permissions you grant**. If Cost Explorer has never been opened in your payer account, nOps permission checks report the `ce:…` actions as failing with *"User not enabled for cost explorer access"* even though your policy is correct. In the payer account: 1. Open [**Billing and Cost Management**](https://console.aws.amazon.com/costmanagement/) → **Cost Explorer** and choose **Launch Cost Explorer**. You can't do this through the API, and your cost data takes up to 24 hours to appear. 2. Signed in as the **root user**, go to the **Account** page and turn on **IAM user and role access to Billing information**. Without this, roles are denied Cost Explorer even with the right policies. Then re-run **Check** on the integration in nOps. *** ## Step 1: Account > [!WARNING] > > **Important:** Savings Analysis onboarding must be completed using your AWS Organizations **payer (management) account**. **Child/member accounts are not supported** for Savings Analysis onboarding. **1. Open Cloud Provider Integrations** Log in to **nOps** and go to [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings). Under **Add a provider**, click **Amazon Web Services** (AWS). **2. Enter payer account and integration name** * **Payer AWS Account ID:** The 12-digit account ID of your AWS Organizations **management (payer)** account (the account that receives the consolidated bill). Child/member account IDs are not supported for Savings Analysis onboarding. * **Integration name:** A friendly label (for example, your company name plus “AWS Production”). **3. Optional: AWS Organization ID** If you use Organizations, you can enter **AWS Organization ID** (`o-xxxxxxxxxx`) so nOps can group accounts consistently. You can select an existing org from the dropdown or enter a new ID. **4. Continue to setup** Click **Next** to go to **Step 2: Setup**, where you choose CloudFormation or Manual IAM. *** ## Step 2: Setup After **Next** on the Account step, choose how to connect your payer account. | | **CloudFormation (Recommended)** | **Manual IAM** | | - | - | - | | You do | Name a bucket, deploy one stack, paste the Role ARN | Create the CUR export and the IAM policies and role yourself in the AWS console | | Creates for you | S3 bucket, Legacy CUR export, CUR 2.0 export, IAM policies, cross-account role | Nothing: you create each piece | | Wizard steps | Setup, then Verify | CUR export, IAM policy creation, then Verify | | Use it when | You're starting fresh | You have a Legacy CUR to reuse, or IAM must be created by hand | ### Option A: CloudFormation (Recommended) **1. Choose CloudFormation and a permission level** Select **CloudFormation**. At the top, choose **Minimum Platform** (Savings Analysis) or **Full Platform** (Inform & Operate). See [Choose a permission level](#choose-a-permission-level) for the difference. **2. Name the S3 bucket** Under **S3 bucket**, enter a name that **doesn't exist yet**. The stack creates it in `us-east-1`. Already have a CUR bucket? See the [FAQ](#faqs), or choose **Manual IAM** instead. **3. Check AWS CUR 2.0** Leave **Enable AWS CUR 2.0 (BCM Data Exports)** checked and the fields blank. nOps fills in defaults when you deploy. Details are in [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports). **4. Deploy the payer stack** Under **Step 1: Deploy payer stack**, click **Deploy Integration Stack (CloudFormation)**. AWS opens with the template pre-filled. Keep the region on `us-east-1`, select the box acknowledging that CloudFormation may create IAM resources, and create the stack. Wait for it to show **CREATE\_COMPLETE**. **5. Paste the Role ARN** On the stack's **Outputs** tab, copy **RoleArn**. Paste it into **Role ARN** in nOps. **6. Optional: deploy child roles** Under **Step 2: Deploy child roles via StackSets**, you can give nOps read access to your member accounts. It isn't required to finish onboarding, and you can do it later. See [Permissions & Resources](/aws/permissions-and-resources#sa-child-roles). **7. Start onboarding** Click **Start Onboarding**, then [run verification](#verify). ### Option B: Manual IAM Select **Manual IAM**. In the **AWS Billing console**, open **Data Exports**, choose **Create**, and select **Legacy CUR export**. Align the export with the following so nOps can rely on the data shape and delivery behavior. **1. Export name** Use an **existing** Legacy CUR export name if you already deliver CUR to S3. You do not need to create a new export. nOps only suggests a name like `nops_cur__hourly` (shown in the UI) when you are setting up a new export in AWS. **2. Billing view and report settings** Use **Billing view: Primary** and **View: Primary View** (as shown in the nOps wizard summary). **3. Include resource IDs and Split Cost Allocation Data** Under **Additional export content**, enable **Include resource IDs** so line items include resource identifiers where applicable. For Kubernetes Explorer **Cluster Name**, also enable **Split cost allocation data** on the Legacy CUR (CloudFormation-created exports already include it; bring-your-own must match) and keep the AWS-generated cost allocation tag **`aws:eks:cluster-name`** active — see the [CUR requirements checklist](#cur-requirements-checklist). **4. Refresh and format** Keep **automatic refresh** enabled so AWS continues delivering updates. Set **Report data time granularity** to **Hourly**. Set **Report versioning** to **Overwrite existing report** (not “Create new report version”). Set **Compression type** to **Parquet**. **5. Enter S3 details in nOps** In nOps, enter: * **S3 bucket:** Bucket name only (for example `my-cur-bucket`), not an `s3://` URL * **S3 path prefix** (optional): Prefix AWS uses under the export path, if you configured one in Data Exports **6. Set up CUR 2.0** Below the Legacy CUR settings, the wizard shows an **AWS CUR 2.0** section with **Enable AWS CUR 2.0 (BCM Data Exports)** checked. Fill it in using [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports) below. **7. Continue to IAM** Click **Next** to open [Step 3: IAM Policy Creation](#step-3-iam-policy-creation-manual-iam). *** ## CUR 2.0 (BCM Data Exports) CUR 2.0 is AWS's newer cost and usage export. AWS also calls it a **standard data export** or **BCM Data Exports**. nOps reads it **in addition to** your Legacy CUR. It does not replace it, so you still complete the Legacy CUR settings above. CUR 2.0 is part of **Step 2** in the wizard. You'll see an **AWS CUR 2.0** section on the setup screen (below the Legacy CUR settings with Manual IAM). **Enable AWS CUR 2.0 (BCM Data Exports)** is checked by default. Keep it checked so nOps can show Amazon Bedrock details, including which IAM principal made each model call. ### What you enter in nOps | Field | Required | What to enter | | - | - | - | | **S3 bucket** | Yes | Bucket name only (for example `my-billing-bucket`), not an `s3://` URL. It can be the same bucket as your Legacy CUR. | | **S3 path prefix** | No | The folder AWS writes the export under. With CloudFormation, the default is `nops-cur2`. | | **Export name** | Yes | The name of the CUR 2.0 export in AWS. With CloudFormation, the suggested name is `nops_cur2_{your_nops_client_id}_hourly`. | Use the exact bucket and export name AWS shows. nOps grants its role access to that bucket only, so a blank or mismatched value stops nOps from finding your data. > [!NOTE] > > **Already connected with a Legacy CUR only?** Skip to [Add CUR 2.0 to an existing integration](#add-cur-2-0-to-an-existing-integration). Setting up AWS for the first time? Pick the tab that matches how you're connecting. **CloudFormation (recommended)** The stack creates the CUR 2.0 export for you. You don't need to open the AWS Data Exports console. **1. Choose CloudFormation** In Step 2, select **CloudFormation** and choose **Minimum Platform** or **Full Platform** at the top. See [Option A](#option-a-cloudformation-recommended). **2. Name the S3 bucket** Enter an **S3 bucket name** that doesn't exist yet. The stack creates it. **3. Fill in AWS CUR 2.0** In **AWS CUR 2.0**, leave **Enable AWS CUR 2.0 (BCM Data Exports)** checked. To keep it simple, leave the fields blank. When you deploy, nOps fills them in with: * **S3 bucket:** the same bucket you named above * **S3 path prefix:** `nops-cur2` * **Export name:** `nops_cur2_{your_nops_client_id}_hourly` **4. Deploy the stack** Under **Step 1: Deploy payer stack**, click **Deploy Integration Stack (CloudFormation)**. Leave the region on `us-east-1`, then create the stack in AWS. It creates your Legacy CUR export, your CUR 2.0 export, and the IAM role. **5. Paste the Role ARN** Copy the **RoleArn** output from CloudFormation, paste it into **Role ARN** in nOps, and continue. > [!NOTE] > > **Using a different bucket for CUR 2.0?** Enter it in **S3 bucket** under **AWS CUR 2.0**. That bucket must already exist and already allow AWS Data Exports to write to it ([see the policy](#let-aws-data-exports-write-to-an-existing-bucket)). The stack doesn't change the policy on a bucket you own. nOps access to the bucket is added for you when you deploy. **Manual IAM** You create the CUR 2.0 export in AWS, then tell nOps where it delivers. **1. Create the export in AWS** In the AWS Billing console, open **Data Exports**, click **Create**, and choose **Standard data export**. **2. Match these settings** * **Export name:** any name you like (for example `nops_cur2_{your_nops_client_id}_hourly`). You'll enter it in nOps. * **Table:** Cost and usage report (CUR 2.0), with **all columns** selected * **Billing view:** Primary * **Additional export content:** turn on **Include resource IDs**, **Split cost allocation data**, **Include caller IAM principal**, and **Include capacity reservation data** * **Time granularity:** Hourly * **Compression and file format:** Parquet * **File versioning:** Overwrite existing export file * **S3 bucket and prefix:** the bucket (and optional prefix) where you want the files delivered Turn on **Include caller IAM principal**. nOps uses it for Amazon Bedrock details. Without it, Bedrock details are missing. **3. Enter the details in nOps** Back in Step 2, under **AWS CUR 2.0**, keep **Enable AWS CUR 2.0 (BCM Data Exports)** checked. Enter the **S3 bucket** and **Export name** exactly as they appear in AWS. Add the **S3 path prefix** if you set one. **4. Copy the bucket policy in Step 3** In [Step 3](#step-3-iam-policy-creation-manual-iam), copy the `nOpsBucketPolicy` JSON from the wizard. If your CUR 2.0 bucket differs from your Legacy CUR bucket, the JSON already includes both. Copy it from the wizard instead of the example on this page. ### Check that it's working On the AWS integration card in [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings), a **CUR 2.0** badge shows the export's status: | Badge | What it means | | - | - | | **CUR 2.0** (green) | Data is arriving. | | **CUR 2.0 (waiting)** | nOps is waiting for AWS to deliver the export's files. New exports can take a while to produce their first files. | | **CUR 2.0 (failed)** | Ingest hit a problem. Hover over the badge to see the error. Check the bucket name, export name, and bucket access above. | CUR 2.0 status is tracked separately from your Legacy CUR. A CUR 2.0 problem never changes the health of your main integration. In **Manage**, the **AWS CUR 2.0** section also shows the last sync result. *** ## Add CUR 2.0 to an existing integration Use this if you already connected AWS with a Legacy CUR and want to add CUR 2.0 now. Your Legacy CUR keeps working and nothing about it changes. You add CUR 2.0 from **Manage**, with a small **add-on stack** that creates the export (and, if you want, its bucket) without touching the stack you deployed originally. ### Before you start * You're an **Admin** in nOps and can create CloudFormation stacks in your AWS payer account. * Decide where the CUR 2.0 files will land. The easiest choice is a **new bucket**, because the add-on stack sets it up completely. Reusing your Legacy CUR bucket or another bucket you own means editing that bucket's policy first (see [below](#let-aws-data-exports-write-to-an-existing-bucket)). ### Choose an option | Your situation | Pick this in the add-on card | Extra work | | - | - | - | | You don't have a CUR 2.0 export and want the simplest path | **Create the export and a new S3 bucket** | None. Enter a bucket name that doesn't exist yet. | | You don't have a CUR 2.0 export but want to reuse a bucket (for example your Legacy CUR bucket) | **Create the export in an existing bucket** | Add two statements to that bucket's policy before you deploy. | | You already created a CUR 2.0 export in AWS | **I already have a CUR 2.0 export** | None. Enter its exact bucket and export name. nOps only gets access. | ### Steps **1. Open Manage** Go to [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings) and click **Manage** on your AWS integration. **2. Fill in AWS CUR 2.0** The wizard opens on the CUR settings. Leave your Legacy CUR settings alone. In the **AWS CUR 2.0** section below them, make sure **Enable AWS CUR 2.0 (BCM Data Exports)** is checked, then enter: * **S3 bucket.** A new bucket name, or the existing bucket you're reusing. * **Export name.** For a new export, use `nops_cur2_{your_nops_client_id}_hourly`. For an export you already have, use the exact name AWS shows. * **S3 path prefix** (optional). Leave blank to use `nops-cur2` for a new export. For an export you already have, enter the prefix it uses. **3. Deploy the add-on stack** In the **Set up CUR 2.0 with CloudFormation** card, select the option from the table above and click **Deploy add-on stack**. AWS opens with the stack pre-filled in `us-east-1`. Keep that region, select the box acknowledging that CloudFormation may create IAM resources, create the stack, and wait for **CREATE\_COMPLETE**. The stack also attaches a separate `nOpsCur2BucketPolicy` to your existing nOps role, so nOps can read the bucket. **4. Save in nOps** Back in nOps, click **Next** through the wizard (nothing else needs to change) and click **Save changes**. This is what tells nOps which bucket and export to read, so don't skip it. **5. Check the badge** On the AWS integration card, the **CUR 2.0** badge shows **waiting** until AWS delivers the first files, which can take a while for a new export. See [Check that it's working](#check-that-its-working). ### If the stack fails | Error | What to do | | - | - | | The bucket already exists | You picked **new bucket** for a bucket that exists. Delete the failed stack and redeploy with **existing bucket**. | | *Failed to verify customer bucket permission* | Your bucket doesn't allow AWS Data Exports yet. Add the policy statements [below](#let-aws-data-exports-write-to-an-existing-bucket), delete the failed stack, and redeploy. | | The export name already exists | You already have a CUR 2.0 export with that name. Delete the failed stack and redeploy with **I already have a CUR 2.0 export**. | ### Other ways to do it Prefer not to add a stack? Pick **one** of these instead: * **Update your original stack.** Set **CreateCur2Export** to `true` and **Cur2BucketName** to your bucket, then update the stack. * **Do it by hand.** Create the export in AWS using the **Manual IAM** tab [above](#cur-2-0-bcm-data-exports), then copy the `nOpsBucketPolicy` JSON from [Step 3](#step-3-iam-policy-creation-manual-iam) over your existing policy. Don't combine these with the add-on stack. That puts the same access in two places, and two stacks that both create the export fail on the name. ### Let AWS Data Exports write to an existing bucket When a stack creates the bucket, it also lets AWS Data Exports write to it. When you use a bucket you already own, the stack never edits your bucket policy. A bucket policy is a single document, so writing one would replace everything already on it. If AWS fails the export with *"Failed to verify customer bucket permission"*, add these two statements to the `Statement` list in the bucket's policy (replace `YOUR_BUCKET` and `YOUR_ACCOUNT_ID`) and deploy again: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} [ { "Sid": "NopsCur2GetBucketMetadata", "Effect": "Allow", "Principal": { "Service": "bcm-data-exports.amazonaws.com" }, "Action": ["s3:GetBucketAcl", "s3:GetBucketPolicy"], "Resource": "arn:aws:s3:::YOUR_BUCKET", "Condition": { "StringEquals": { "aws:SourceAccount": "YOUR_ACCOUNT_ID" }, "ArnLike": { "aws:SourceArn": "arn:aws:bcm-data-exports:us-east-1:YOUR_ACCOUNT_ID:export/*" } } }, { "Sid": "NopsCur2PutObject", "Effect": "Allow", "Principal": { "Service": "bcm-data-exports.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::YOUR_BUCKET/*", "Condition": { "StringEquals": { "aws:SourceAccount": "YOUR_ACCOUNT_ID" }, "ArnLike": { "aws:SourceArn": "arn:aws:bcm-data-exports:us-east-1:YOUR_ACCOUNT_ID:export/*" } } } ] ``` This is separate from the `billingreports.amazonaws.com` grant your Legacy CUR uses. A bucket that already receives a Legacy CUR usually needs both. *** ## Bring your own CUR You do **not** need to create a new Cost and Usage Report if you already deliver a **Legacy CUR** to Amazon S3 from your **payer (management) account**. Many teams reuse an export they configured for another FinOps or billing tool. **Bring your own** means you keep your existing export in AWS and tell nOps where to read it (export name, S3 bucket, and optional prefix). nOps does not require a specific export name, only that the export’s settings match what ingestion expects. ### When bring-your-own works well * You already have a **Legacy CUR export** delivering **Parquet** files to S3. A CUR 2.0 / standard data export alone does not satisfy this onboarding path, but you set up CUR 2.0 alongside it (see [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports)) * The export is on the **same payer account** you connect in Step 1 * You can grant the nOps integration role **read access** to that bucket ([Step 3](#step-3-iam-policy-creation-manual-iam) updates `nOpsBucketPolicy` with your bucket ARN) * You are willing to **change export settings** in AWS if your current export does not match the checklist below ### CUR requirements checklist Your export must meet **all** of the following. If any item differs, update the export in [AWS Billing > Data Exports](https://console.aws.amazon.com/billing/home#/dataexports) before onboarding (or create a second export that complies and use that one with nOps). | Requirement | Required setting | Why nOps needs it | | - | - | - | | Export type | **Legacy CUR export** | nOps ingests the classic CUR delivery layout AWS writes to S3 | | Account | **Payer (management) account** | Consolidated billing and organization-level cost data | | Billing view | **Primary** | Matches the management account’s primary billing view | | View | **Primary View** | Consistent scope for line items | | Resource detail | **Include resource IDs** enabled | Resource-level cost allocation and showback | | Split Cost Allocation Data | **Split cost allocation data** enabled on the Legacy CUR | EKS pod/namespace split lines for Kubernetes cost views. CloudFormation-created exports already include this; bring-your-own must match | | EKS cluster cost allocation tag | AWS-generated tag **`aws:eks:cluster-name`** **Active** under Cost allocation tags (warehouse column `resource_tags_aws_eks_cluster_name`) | Without this tag, **Cluster Name** is unavailable in Kubernetes Explorer | | Refresh | **Automatic refresh** enabled | Ongoing daily (or more frequent) file delivery | | Time granularity | **Hourly** | Hour-level usage and cost analysis | | Report versioning | **Overwrite existing report** | Predictable object paths; avoids version sprawl nOps does not expect | | Compression | **Parquet** | Columnar format used by the ingestion pipeline | | Delivery | **Amazon S3** in your account | nOps reads objects from the bucket you specify | > [!WARNING] > > **CUR 2.0 / non-legacy exports:** This onboarding path (the primary AWS integration) requires a **Legacy CUR** export. If you only have a newer **standard** data export and not a Legacy CUR to S3, create a Legacy CUR export as described in Step 2 or in [Creating a Legacy CUR export](https://docs.aws.amazon.com/cur/latest/userguide/dataexports-create-legacy.html). You can keep your CUR 2.0 export and point nOps at it in the **AWS CUR 2.0** section of the same step. See [CUR 2.0 (BCM Data Exports)](#cur-2-0-bcm-data-exports). ### What to enter in nOps (Step 2) Use the **exact** values AWS shows for your existing export: 1. **Export name:** The Legacy CUR export name in Data Exports (not the S3 object filename). 2. **S3 bucket:** Bucket name only (for example `company-cur-prod`), not an `s3://` URL. 3. **S3 path prefix** (optional): Only if you configured a prefix in the export’s storage settings; leave blank if files land at the bucket root under AWS’s default path. The suggested name `nops_cur_{client_id}_hourly` is for **new** exports. For bring-your-own, type your existing export name instead. ### S3 bucket access The integration IAM role must be able to **list** the bucket and **get** CUR objects. In [Step 3](#step-3-iam-policy-creation-manual-iam), replace `` in `nOpsBucketPolicy` with your CUR bucket name. If you use a bucket policy, ensure it allows the nOps role (after you create it) to read the CUR prefix. ### If your export is close but not exact | Situation | What to do | | - | - | | Granularity is **Daily** instead of Hourly | Edit the export to **Hourly**, or add a new hourly Legacy CUR export for nOps | | Versioning is **Create new report version** | Switch to **Overwrite existing report** (nOps expects a stable delivery pattern) | | Compression is **CSV** or **GZIP** | Create or reconfigure an export with **Parquet** | | **Include resource IDs** is off | Enable it under **Additional export content** (may increase file size) | | CUR is in a **member account** bucket | Use payer-account delivery, or copy/consolidate to a bucket the payer integration role can access | After you change export settings, AWS may take up to **24 hours** before new files reflect the update. For historical months in a different format, see [Request a manual CUR backfill](#request-a-manual-cur-backfill). *** ## Step 3: IAM Policy Creation (Manual IAM) This step is only for **Manual IAM**. If you chose CloudFormation, the stack already created everything here and you can skip to [Verify](#verify). Create **customer managed policies** and a **cross-account role** that trusts nOps using the **external ID** shown in the wizard. > [!TIP] > > **Would you rather not do this by hand?** Go back and choose **CloudFormation** in Step 2. It creates the same policies and role in a single stack. ### Choose a permission level At the top of the setup screen, select **Minimum Platform** or **Full Platform**. This controls which platform policy JSON nOps shows and which IAM policy name to create: | Level | IAM policy name | Use when | | - | - | - | | **Minimum Platform** | `nOpsMinimumPlatformPermissions` | **Savings Analysis:** cost visibility, CUR, and commitment *read* APIs only | | **Full Platform** | `nOpsFullPlatformPermissions` | **Inform & Operate:** everything in Minimum, plus broader inventory reads and selected write actions (rightsizing, purchasing prep, support cases) | > [!NOTE] > > **Full Platform is a superset of Minimum**, but attaches more than a single swapped-in policy. See the next step for what each level requires. The bucket policy (`nOpsBucketPolicy`) is the same for both levels. **1. Create customer managed policies in IAM** In **IAM > Policies**, create the policies shown in nOps for your selected permission level: * **Minimum Platform:** `nOpsBucketPolicy` + `nOpsMinimumPlatformPermissions` (two policies) * **Full Platform:** `nOpsBucketPolicy` + `nOpsFullPlatformDenyList1` + `nOpsFullPlatformDenyList2` + `nOpsFullPlatformPermissions` (four policies). You'll also attach the AWS-managed `ReadOnlyAccess` policy when you attach policies below, which has no JSON to create In the modal, each policy block is labeled with the policy name and permission level. Use **Copy Policy** to copy each JSON document. > [!NOTE] > > Prefer **Copy Policy** in the nOps wizard so you apply the latest policy version for your account. The accordion below shows **Minimum Platform** JSON for reference; see [Permissions & Resources](/aws/permissions-and-resources) for the complete **Full Platform** breakdown (`nOpsFullPlatformDenyList1` + `nOpsFullPlatformDenyList2` + `nOpsFullPlatformPermissions`). > **IAM Policy: nOpsBucketPolicy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "s3:ListBucket", > "s3:GetBucketPolicy", > "s3:GetEncryptionConfiguration", > "s3:GetBucketVersioning", > "s3:GetBucketPolicyStatus", > "s3:GetBucketLocation", > "s3:GetBucketAcl", > "s3:GetBucketLogging", > "s3:GetObject", > "s3:PutBucketPolicy", > "s3:PutObject" > ], > "Resource": [ > "arn:aws:s3:::", > "arn:aws:s3:::/*" > ] > } > ] > } > ``` > > If your [CUR 2.0 export](#cur-2-0-bcm-data-exports) uses a bucket other than your Legacy CUR bucket, the wizard adds a second pair of ARNs for it to this same policy. Copy the JSON from the app rather than this example so you get both. > **IAM Policy: nOpsMinimumPlatformPermissions (Minimum Platform)** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "bcm-data-exports:ListExports", > "bcm-data-exports:ListTables", > "bcm-data-exports:GetExport", > "bcm-data-exports:GetExecution", > "bcm-data-exports:CreateExport", > "bcm-data-exports:UpdateExport", > "bcm-data-exports:ListExecutions", > "ce:GetReservationCoverage", > "ce:GetReservationPurchaseRecommendation", > "ce:GetReservationUtilization", > "ce:GetSavingsPlanPurchaseRecommendationDetails", > "ce:GetSavingsPlansCoverage", > "ce:GetSavingsPlansPurchaseRecommendation", > "ce:GetSavingsPlansUtilization", > "ce:GetSavingsPlansUtilizationDetails", > "ce:ListSavingsPlansPurchaseRecommendationGeneration", > "cur:GetClassicReport", > "cur:GetClassicReportPreferences", > "cur:GetUsageReport", > "cur:DescribeReportDefinitions", > "cur:PutReportDefinition", > "ec2:DescribeReservedInstances", > "organizations:ListAccounts", > "organizations:DescribeOrganization", > "organizations:ListRoots", > "savingsplans:DescribeSavingsPlanRates", > "savingsplans:DescribeSavingsPlans", > "savingsplans:DescribeSavingsPlansOfferingRates", > "savingsplans:DescribeSavingsPlansOfferings", > "savingsplans:ListTagsForResource", > "support:CreateCase", > "support:DescribeCases" > ], > "Resource": "*" > }, > { > "Effect": "Allow", > "Action": "sts:AssumeRole", > "Resource": "arn:aws:iam::*:role/nops-sa-child-role-minimal" > } > ] > } > ``` > **IAM Policy: nOpsFullPlatformDenyList1/2 + nOpsFullPlatformPermissions (Full Platform)** > > **Full Platform** doesn't use a single allow-only policy. It attaches the AWS-managed `ReadOnlyAccess` policy plus three customer-managed documents: `nOpsFullPlatformDenyList1` and `nOpsFullPlatformDenyList2` (split Deny lists that carve sensitive read actions out of `ReadOnlyAccess`; split to stay under IAM's policy-size quota) and `nOpsFullPlatformPermissions` (writes and reads `ReadOnlyAccess` doesn't cover). > > Use **Copy Policy** in the nOps wizard for each document when **Full Platform** is selected, or see the full breakdown in [Permissions & Resources](/aws/permissions-and-resources#customer-managed-policies). **2. Create the IAM role** In **IAM > Roles**, create a role for **Another AWS account** (or create the role and switch to a custom trust relationship). nOps shows a **Suggested role name** (for example `nops-integration-role-`), and you can copy it from the modal. **3. Enter the custom trust policy** In nOps, copy the trust relationship JSON with **Copy trust policy**, then paste it into the IAM role trust policy. This policy includes your integration-specific external ID and trusts the nOps connector role. > **IAM Policy: trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam::861341088565:role/nops-data-connector" > }, > "Action": "sts:AssumeRole", > "Condition": { > "StringEquals": { > "sts:ExternalId": "" > } > } > } > ] > } > ``` **4. Attach policies to the role** Attach the policies matching your permission level: * **Minimum Platform:** `nOpsBucketPolicy` + `nOpsMinimumPlatformPermissions` * **Full Platform:** `nOpsBucketPolicy` + `nOpsFullPlatformDenyList1` + `nOpsFullPlatformDenyList2` + `nOpsFullPlatformPermissions` + the AWS-managed **`ReadOnlyAccess`** policy (search and attach; no JSON to paste for this one). A Deny always overrides an Allow, so attaching `ReadOnlyAccess` alongside the Deny lists cannot grant back anything those lists block. **5. Paste Role ARN and start onboarding** From the IAM role summary, copy the role ARN and paste it into **Role ARN** in nOps, then click **Start Onboarding**. Next, [run verification](#verify). **6. Optional: deploy child roles for member accounts** To let nOps read resource inventory (and, on Full Platform, tags) from your AWS Organization's **member accounts**, deploy the matching child role template (`nops-sa-child-role` or `nops-sa-child-role-minimal`) via CloudFormation StackSets from your payer/management account. Not required to finish onboarding. See [Permissions & Resources](/aws/permissions-and-resources#sa-child-roles) for details. *** ## Verify The last step of the wizard checks that nOps can reach your account. Click **Run verification** and wait for the results. Each check shows whether it passed and, if not, what to fix. Common fixes: * **`ce:…` checks fail with "User not enabled for cost explorer access":** turn on Cost Explorer, as described in [Turn on Cost Explorer in your payer account](#turn-on-cost-explorer-in-your-payer-account). * **CUR checks fail:** confirm the bucket name, export name, and prefix, and that the export meets the [requirements](#cur-requirements-checklist). * **Role can't be assumed:** confirm the Role ARN, and for Manual IAM that the trust policy has the external ID from the wizard. Data from a new CUR can take up to 24 hours to appear after AWS first delivers files. *** ## Manage an existing integration **Admin** users can open **Manage** on an active AWS integration card to walk through the same steps again (for example, to update the CUR bucket, export name, or role). Manage skips the CloudFormation-or-manual choice and opens the CUR settings directly, then the IAM step, and ends with **Save changes**. To add CUR 2.0 to an integration you already have, follow [Add CUR 2.0 to an existing integration](#add-cur-2-0-to-an-existing-integration). *** ## Request a manual CUR backfill If you need historical CUR data that is not yet available in nOps, use **Request Backfill** to open a guided modal and create an AWS Support ticket. In AWS Support Console, create the case using these selections: * **Related Issue:** Account and Billing * **Service:** Billing * **Category:** Consolidated Billing Questions * **Severity:** General question Follow these steps: 1. Open [AWS Support Console](https://console.aws.amazon.com/support/home#/case/create). 2. Select: * **Related Issue:** Account and Billing * **Service:** Billing * **Category:** Consolidated Billing Questions * **Severity:** General question 3. Click **Next step: Additional information**. 4. Paste the prefilled values from the modal: * **Subject:** `CUR Backfill Request` * **Description:** ```text theme={"theme":{"light":"github-light","dark":"github-dark"}} Please Backfill our CUR for the following: CUR Report name: Time Period: to Master Payer account: Type of CUR: Legacy CUR Reason: We are leveraging a FinOps solution that requires all CURs to be in parquet format, and would like historical information for the dates listed to be backfilled. ``` 5. Click **Next step: Solve now or contact us**. 6. Switch to the **Contact us** tab. 7. Select **Web**. 8. Submit the case. *** ## Next steps > **[Users and roles](/platform/users)** > > Invite team members and assign **Admin** or **Owner** roles where integration access is needed. > **[AWS Commitment Management](/aws/commitment-management-setup)** > > Optional: enable CM from your AWS integration card after onboarding. Uses separate IAM roles and CloudFormation templates. > **[Permissions & Resources](/aws/permissions-and-resources)** > > Complete reference of all IAM roles, policies, and trust relationships for Savings Analysis and Commitment Management. # Amazon Web Services - Permissions & Resources Source: https://help.nops.io/aws/permissions-and-resources Complete reference of all IAM roles, policies, and trust relationships nOps requires in your AWS environment for Savings Analysis and Commitment Management. ## Overview nOps AWS access is configured in two layers: 1. **Platform integration** ([Integration setup](/aws/integration-setup)): CUR delivery + a cross-account IAM role in your payer account. Choose **Minimum Platform** (Savings Analysis) or **Full Platform** (Inform & Operate) during IAM setup. 2. **Commitment Management** ([CM setup](/aws/commitment-management-setup)): Optional. Three additional cross-account IAM roles (CloudFormation) for inventory reads and commitment purchasing. **Minimum Platform** is a single allow-only customer-managed policy. **Full Platform** layers a smaller customer-managed allow-list and a customer-managed Deny policy on top of the AWS-managed `ReadOnlyAccess` policy, to match the broader read coverage of nOps's legacy integration role. *** ## Platform permission levels Select the level on the setup screen of the AWS integration wizard (**Step 2** with CloudFormation, **Step 3: IAM Policy Creation** with Manual IAM). | Level | IAM policy name | Product scope | When to use | | - | - | - | - | | **Minimum Platform** | `nOpsMinimumPlatformPermissions` | Savings Analysis | CUR ingestion, billing exports, Cost Explorer commitment *read* APIs, Organizations metadata | | **Full Platform** | `nOpsFullPlatformPermissions` | Inform & Operate | Everything in Minimum, plus broader inventory reads (Compute Optimizer, EC2/RDS/EKS, etc.) and selected write actions for rightsizing and operational workflows | Both levels also require `nOpsBucketPolicy` on the same role. **Full Platform is a superset of Minimum**, but it attaches more than a single swapped-in policy. See [Customer-Managed Policies](#customer-managed-policies) below for what each level actually requires. *** ## Permissions -- Platform integration The platform integration uses a **single cross-account IAM role** in your payer (management) account. The policies attached to it depend on your selected permission level (see below). ### IAM Role | Role name | Account | Purpose | | - | - | - | | `nops-integration-role-` | Payer / management | Cross-account role for nOps data ingestion and cost analysis | ### Trust Policy The role trusts a single nOps connector role with an integration-specific external ID: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::861341088565:role/nops-data-connector" }, "Action": "sts:AssumeRole", "Condition": { "StringEquals": { "sts:ExternalId": "" } } } ] } ``` ### Customer-Managed Policies **Minimum Platform** attaches two customer-managed policies. **Full Platform** attaches four customer-managed policies (bucket, Deny list parts 1 and 2, and a trimmed allow-list) plus the AWS-managed `ReadOnlyAccess` policy. > **nOpsBucketPolicy: S3 access for CUR delivery** > > Grants read and write access to the S3 bucket where AWS delivers your Cost and Usage Report. When the CUR 2.0 add-on points at a different bucket, this same policy lists that bucket's ARNs too. > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "s3:ListBucket", > "s3:GetBucketPolicy", > "s3:GetEncryptionConfiguration", > "s3:GetBucketVersioning", > "s3:GetBucketPolicyStatus", > "s3:GetBucketLocation", > "s3:GetBucketAcl", > "s3:GetBucketLogging", > "s3:GetObject", > "s3:PutBucketPolicy", > "s3:PutObject" > ], > "Resource": [ > "arn:aws:s3:::", > "arn:aws:s3:::/*" > ] > } > ] > } > ``` > **nOpsMinimumPlatformPermissions: Minimum Platform (Savings Analysis)** > > Allow-only policy for Savings Analysis: CUR and Data Exports, Cost Explorer commitment reads, Organizations metadata, and support case creation. > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "bcm-data-exports:ListExports", > "bcm-data-exports:ListTables", > "bcm-data-exports:GetExport", > "bcm-data-exports:GetExecution", > "bcm-data-exports:CreateExport", > "bcm-data-exports:UpdateExport", > "bcm-data-exports:ListExecutions", > "ce:GetReservationCoverage", > "ce:GetReservationPurchaseRecommendation", > "ce:GetReservationUtilization", > "ce:GetSavingsPlanPurchaseRecommendationDetails", > "ce:GetSavingsPlansCoverage", > "ce:GetSavingsPlansPurchaseRecommendation", > "ce:GetSavingsPlansUtilization", > "ce:GetSavingsPlansUtilizationDetails", > "ce:ListSavingsPlansPurchaseRecommendationGeneration", > "cur:GetClassicReport", > "cur:GetClassicReportPreferences", > "cur:GetUsageReport", > "cur:DescribeReportDefinitions", > "cur:PutReportDefinition", > "ec2:DescribeReservedInstances", > "organizations:ListAccounts", > "organizations:DescribeOrganization", > "organizations:ListRoots", > "savingsplans:DescribeSavingsPlanRates", > "savingsplans:DescribeSavingsPlans", > "savingsplans:DescribeSavingsPlansOfferingRates", > "savingsplans:DescribeSavingsPlansOfferings", > "savingsplans:ListTagsForResource", > "support:CreateCase", > "support:DescribeCases" > ], > "Resource": "*" > }, > { > "Effect": "Allow", > "Action": "sts:AssumeRole", > "Resource": "arn:aws:iam::*:role/nops-sa-child-role-minimal" > } > ] > } > ``` > **Full Platform (Inform & Operate): four documents** > > Full Platform doesn't use a single allow-only policy. It attaches four documents to the role instead: > > | Document | Type | Purpose | > | - | - | - | > | `ReadOnlyAccess` | AWS-managed | Broad read coverage across AWS services | > | `nOpsFullPlatformDenyList1` | Customer-managed (Deny) | Deny list part 1 of 2: carves sensitive read actions (for example Secrets Manager, Cognito, KMS key material, DynamoDB item reads) out of `ReadOnlyAccess`. Split with part 2 to stay under IAM's 6,144-character customer-managed policy size quota. A Deny always overrides an Allow. | > | `nOpsFullPlatformDenyList2` | Customer-managed (Deny) | Deny list part 2 of 2: continues the sensitive-action carve-out from `ReadOnlyAccess`. | > | `nOpsFullPlatformPermissions` | Customer-managed (Allow) | Actions `ReadOnlyAccess` doesn't cover: a handful of writes needed for rightsizing/operational workflows, a few reads the Deny lists above block that nOps still needs, and `sts:AssumeRole` for the optional [SA child role](#sa-child-roles) | > > > [!NOTE] > > > > Use **Copy Policy** in the nOps wizard for each document to get the current JSON. The Deny lists together cover 180+ entries and are best copied directly rather than retyped. ### SA Child Roles To extend read access to your AWS Organization's **member accounts**, deploy a child role via CloudFormation StackSets from your payer account. This is optional and not required to finish onboarding. | Role name | Deployed via | Matches | | - | - | - | | `nops-sa-child-role` | StackSets, from payer account | Full Platform payer role | | `nops-sa-child-role-minimal` | StackSets, from payer account | Minimum Platform payer role | Each child role trusts only the payer integration role (passed as the `PayerRoleArn` CloudFormation parameter), and its permissions mirror the payer role's own tier. A payer role can only assume the child role name matching its own tier. A Full Platform payer role can't assume `nops-sa-child-role-minimal`, and vice versa. *** ## Permissions -- Commitment Management Commitment Management uses **three additional cross-account IAM roles** deployed via CloudFormation. These are separate from the Savings Analysis role. ### Role Summary | Role name | Account | Purpose | How nOps reaches it | | - | - | - | - | | `NopsCMCrossAccountAssume` | Any org account | Assume child read roles across member accounts | nOps bridge → this role (with external ID) | | `NopsCMReadEC2Instances` | Each member account (via StackSets) | Read-only EC2, RDS, ElastiCache, and Savings Plans inventory | Central role → this role | | `nops-sharesave-mgt` | Dedicated child account | Commitment purchasing and management | nOps bridge → this role (with external ID) | ### Role 1: NopsCMCrossAccountAssume (Central Role) Deployed in **any account in your AWS Organization** (not required to be the payer / management account). This role's only permission is to assume the child read role in member accounts. > **Trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam::861341088565:role/NopsCMCentralClientAccountAssume" > }, > "Action": "sts:AssumeRole", > "Condition": { > "StringEquals": { > "sts:ExternalId": "" > } > } > } > ] > } > ``` > **Inline policy: NopsCMAssumeChildRoles** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": "sts:AssumeRole", > "Resource": "arn:aws:iam::*:role/NopsCMReadEC2Instances" > } > ] > } > ``` ### Role 2: NopsCMReadEC2Instances (Child Read Role) Deployed in **every member account** via CloudFormation StackSets. Provides read-only access to compute and commitment metadata. > **Trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam:::role/NopsCMCrossAccountAssume" > }, > "Action": "sts:AssumeRole" > } > ] > } > ``` > > > [!NOTE] > > > > The `CentralRoleArn` parameter in the CloudFormation template is set to the ARN of your `NopsCMCrossAccountAssume` role. Only that central role can assume this child read role. > **Inline policy: NopsCMReadEC2Policy** > > | Action | Service | Purpose | > | - | - | - | > | `ec2:DescribeInstances` | EC2 | List running instances for coverage analysis | > | `ec2:DescribeReservedInstances` | EC2 | List active EC2 Reserved Instances | > | `savingsplans:DescribeSavingsPlans` | Savings Plans | List active Savings Plans | > | `rds:DescribeDBInstances` | RDS | List RDS instances for coverage analysis | > | `rds:DescribeReservedDBInstances` | RDS | List active RDS Reserved Instances | > | `elasticache:DescribeReservedCacheNodes` | ElastiCache | List active ElastiCache Reserved Cache Nodes | > | `organizations:ListAccounts` | Organizations | List organization member accounts (returns data only in the payer account) | > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "ec2:DescribeInstances", > "ec2:DescribeReservedInstances", > "savingsplans:DescribeSavingsPlans", > "rds:DescribeDBInstances", > "rds:DescribeReservedDBInstances", > "elasticache:DescribeReservedCacheNodes", > "organizations:ListAccounts" > ], > "Resource": "*" > } > ] > } > ``` ### Role 3: nops-sharesave-mgt (ShareSave Role) Deployed in a **dedicated child account** within your AWS Organization. This role has the permissions needed to purchase and manage commitments. Purchased commitments automatically apply across the organization via RI/SP sharing. > **Trust policy** > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Principal": { > "AWS": "arn:aws:iam::861341088565:role/CrossAccountSharesaveMgt" > }, > "Action": "sts:AssumeRole", > "Condition": { > "StringEquals": { > "sts:ExternalId": "" > } > } > } > ] > } > ``` > **AWS managed policies (5)** > > | Managed Policy ARN | Policy Name | Purpose | > | - | - | - | > | `arn:aws:iam::aws:policy/AWSSavingsPlansFullAccess` | AWS Savings Plans Full Access | Create, describe, list, and return Savings Plans | > | `arn:aws:iam::aws:policy/AWSOrganizationsReadOnlyAccess` | AWS Organizations Read-Only Access | List and describe organization accounts and structure | > | `arn:aws:iam::aws:policy/AWSCloudTrail_ReadOnlyAccess` | AWS CloudTrail Read-Only Access | Read CloudTrail event history for auditing | > | `arn:aws:iam::aws:policy/AWSSupportAccess` | AWS Support Access | Create and view AWS support cases | > | `arn:aws:iam::aws:policy/ServiceQuotasFullAccess` | Service Quotas Full Access | View and request service quota increases | > **Inline policy: NopsSharesaveMgtPolicy** > > | Action | Service | Purpose | > | - | - | - | > | `ec2:CreateTags` | EC2 | Tag purchased Reserved Instances | > | `ec2:DescribeReservedInstances` | EC2 | List active EC2 RIs | > | `ec2:DescribeReservedInstancesListings` | EC2 | View RI marketplace listings | > | `ec2:DescribeReservedInstancesModifications` | EC2 | Track RI modification status | > | `ec2:DescribeReservedInstancesOfferings` | EC2 | Discover available RI offerings | > | `ec2:ModifyReservedInstances` | EC2 | Modify RI scope or Availability Zone | > | `ec2:PurchaseReservedInstancesOffering` | EC2 | Purchase EC2 Reserved Instances | > | `ec2:CreateReservedInstancesListing` | EC2 | List RIs on the RI Marketplace | > | `ec2:CancelReservedInstancesListing` | EC2 | Cancel RI Marketplace listings | > | `ec2:DeleteQueuedReservedInstances` | EC2 | Cancel a queued (not-yet-fired) RI purchase | > | `ec2:GetReservedInstancesExchangeQuote` | EC2 | Get pricing for convertible RI exchange | > | `ec2:AcceptReservedInstancesExchangeQuote` | EC2 | Execute convertible RI exchange | > | `rds:DescribeReservedDBInstances` | RDS | List active RDS RIs | > | `rds:DescribeReservedDBInstancesOfferings` | RDS | Discover available RDS RI offerings | > | `rds:PurchaseReservedDBInstancesOffering` | RDS | Purchase RDS Reserved Instances | > | `elasticache:DescribeReservedCacheNodes` | ElastiCache | List active ElastiCache RIs | > | `elasticache:DescribeReservedCacheNodesOfferings` | ElastiCache | Discover available ElastiCache RI offerings | > | `elasticache:PurchaseReservedCacheNodesOffering` | ElastiCache | Purchase ElastiCache Reserved Cache Nodes | > | `savingsplans:ReturnSavingsPlan` | Savings Plans | Return (cancel) a Savings Plan within the return window | > | `savingsplans:TagResource` | Savings Plans | Tag purchased Savings Plans | > | `ce:*` | Cost Explorer | Full access to cost and reservation analysis | > > ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} > { > "Version": "2012-10-17", > "Statement": [ > { > "Effect": "Allow", > "Action": [ > "ec2:CreateTags", > "ec2:DescribeReservedInstances", > "ec2:DescribeReservedInstancesListings", > "ec2:DescribeReservedInstancesModifications", > "ec2:DescribeReservedInstancesOfferings", > "ec2:ModifyReservedInstances", > "ec2:PurchaseReservedInstancesOffering", > "ec2:CreateReservedInstancesListing", > "ec2:CancelReservedInstancesListing", > "ec2:DeleteQueuedReservedInstances", > "ec2:GetReservedInstancesExchangeQuote", > "ec2:AcceptReservedInstancesExchangeQuote", > "rds:DescribeReservedDBInstances", > "rds:DescribeReservedDBInstancesOfferings", > "rds:PurchaseReservedDBInstancesOffering", > "elasticache:DescribeReservedCacheNodes", > "elasticache:DescribeReservedCacheNodesOfferings", > "elasticache:PurchaseReservedCacheNodesOffering", > "savingsplans:ReturnSavingsPlan", > "savingsplans:TagResource", > "ce:*" > ], > "Resource": "*" > } > ] > } > ``` *** ## Complete Role Summary > **All roles at a glance (Savings Analysis + Commitment Management)** > > | Account | Role | Platform integration | Commitment Management | > | - | - | :-: | :-: | > | Payer | `nops-integration-role-` | Yes (Minimum or Full Platform) | -- | > | Each member (StackSets, optional) | `nops-sa-child-role` or `nops-sa-child-role-minimal` | Yes (optional) | -- | > | Any org account | `NopsCMCrossAccountAssume` | -- | Yes | > | Payer (direct stack) | `NopsCMReadEC2Instances` | -- | Yes (management-account inventory) | > | Each member (StackSets) | `NopsCMReadEC2Instances` | -- | Yes | > | Dedicated child | `nops-sharesave-mgt` | -- | Yes | *** ## Resources Created During the setup process, nOps CloudFormation templates create the following resources in your AWS environment. | Resource | Account | Created by | | - | - | - | | S3 bucket for CUR delivery (the name you enter in the wizard) | Payer | CloudFormation (skipped if you point the stack at an existing bucket) | | S3 bucket policy on that bucket, allowing AWS billing to deliver the report | Payer | CloudFormation (only for a bucket the stack creates; see [CUR delivery bucket policy](#cur-delivery-bucket-policy)) | | Legacy CUR export `nops_cur__hourly` | Payer | AWS Billing console (manual) or CloudFormation | | IAM role `nops-integration-role-` | Payer | Manual (setup wizard) or CloudFormation | | IAM policy `nOpsBucketPolicy` | Payer | Manual (setup wizard) or CloudFormation | | IAM policy `nOpsCur2BucketPolicy` | Payer | CloudFormation add-on stack (only when granting a CUR 2.0 bucket to a stack that was already deployed) | | IAM policy `nOpsMinimumPlatformPermissions` or (`nOpsFullPlatformDenyList1` + `nOpsFullPlatformDenyList2` + `nOpsFullPlatformPermissions`) | Payer | Manual (setup wizard; one set per integration) or CloudFormation | | IAM role `nops-sa-child-role` or `nops-sa-child-role-minimal` | Each member account | CloudFormation StackSet (optional) | | IAM role `NopsCMCrossAccountAssume` | Any org account | CloudFormation stack | | IAM role `NopsCMReadEC2Instances` | Each member account | CloudFormation StackSet | | IAM role `nops-sharesave-mgt` | Dedicated child account | CloudFormation stack | > [!NOTE] > > All IAM roles use **external IDs** in their trust policies (where applicable) to prevent the [confused deputy problem](https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html). External IDs are unique per integration and generated by nOps during onboarding. ### CUR delivery bucket policy When AWS creates a Cost and Usage Report, it checks that the destination bucket lets the billing service write to it. The Billing console adds that permission for you; CloudFormation does not. So when the integration stack creates the bucket, it also attaches this policy: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "Version": "2012-10-17", "Statement": [ { "Sid": "NopsCurGetBucketMetadata", "Effect": "Allow", "Principal": { "Service": "billingreports.amazonaws.com" }, "Action": ["s3:GetBucketAcl", "s3:GetBucketPolicy"], "Resource": "arn:aws:s3:::", "Condition": { "StringEquals": { "aws:SourceAccount": "", "aws:SourceArn": "arn:aws:cur:us-east-1::definition/*" } } }, { "Sid": "NopsCurPutObject", "Effect": "Allow", "Principal": { "Service": "billingreports.amazonaws.com" }, "Action": "s3:PutObject", "Resource": "arn:aws:s3:::/*", "Condition": { "StringEquals": { "aws:SourceAccount": "", "aws:SourceArn": "arn:aws:cur:us-east-1::definition/*" } } } ] } ``` This grants AWS billing, and nobody else, the ability to deliver reports into the bucket. It does not grant nOps anything. nOps reads the CUR through `nOpsBucketPolicy` on the integration role. > [!WARNING] > > **nOps never writes a bucket policy on a bucket you already own.** A bucket policy is one document, so attaching ours would replace everything already on your bucket. If you point the stack at an existing bucket (`CreateCurBucket=false`), that bucket must already allow `billingreports.amazonaws.com`. Otherwise AWS rejects the export with *"Failed to verify customer bucket permission"*. The stack's **CurBucketPolicyManaged** output tells you which case applies. *** ## Cross-Account Role Chains nOps uses two role-assumption chains to access your AWS resources. Each chain starts from an nOps-owned bridge role. ### Commitment Inventory (read path) ``` nOps bridge role (NopsCMCentralClientAccountAssume) → NopsCMCrossAccountAssume (your central account, with external ID) → NopsCMReadEC2Instances (your member accounts) ``` ### Commitment Operations (purchase path) ``` nOps bridge role (CrossAccountSharesaveMgt) → nops-sharesave-mgt (your dedicated child account, with external ID) ``` *** ## Security Model | Layer | Protection | | - | - | | **External IDs** | Prevent confused deputy attacks; unique per integration | | **Separate IAM roles** | Purchase permissions are scoped to a dedicated role (`nops-sharesave-mgt`), isolated from your integration role | | **Scoped trust policies** | Each role trusts only the specific nOps bridge role that needs to assume it | | **Least-privilege inline policies** | Child read role has only 7 read-only actions; ShareSave role has only the actions needed for commitment operations | | **AWS managed policies** | Used for well-defined access scopes (Savings Plans, Organizations, CloudTrail, Support, Service Quotas) | | **Verification checks** | nOps verifies role assumption and API access before enabling CM | *** ## Network Requirements nOps does not require any VPC peering, VPN connections, or network-level access to your AWS environment. All communication uses standard AWS API calls via cross-account role assumption over HTTPS. *** ## Related Guides > **[AWS Integration Setup](/aws/integration-setup)** > > Connect your payer account for Savings Analysis (CUR + IAM role). > **[AWS Commitment Management Setup](/aws/commitment-management-setup)** > > Step-by-step guide to deploy the three CM roles via CloudFormation. > **[Users and Roles](/platform/users)** > > Manage team members and Admin/Owner roles for integration access. > **[Platform Integrations](/platform/integrations)** > > Overview of all cloud integrations and setup entry points. # Microsoft Azure - Commitment Management Setup Source: https://help.nops.io/azure/commitment-management-setup Let nOps staff buy Azure Reservations and Savings Plans for you by delegating a subscription you choose with Azure Lighthouse. ## FAQs > **What is Azure Commitment Management?** > > Commitment Management lets nOps buy and manage Azure Reservations and Savings Plans for you. nOps watches your usage, recommends commitment levels, and buys when it finds savings. > **What is the difference between Reservations and Savings Plans?** > > * **Reservations**: discounts on a specific resource type (for example Virtual Machines or SQL Database) in a specific region. They save the most (up to 72%) but are less flexible. > * **Savings Plans**: discounts on an hourly spend commitment across a broader range of compute services. They're more flexible and save a little less. > > nOps manages both to get you the most savings. > **What access does nOps need to buy commitments?** > > nOps staff buy in the Azure portal through **Azure Lighthouse**. You delegate each subscription purchases are billed to with one template, the **nOps Commitment Management** delegation. It gives the nOps Customer Access Operators group, in the nOps tenant: > > * **Reader**, to see the subscription > * **Reservation Purchaser** and **Savings plan Purchaser**, to buy commitments billed to it > > Your enrollment or billing profile must also allow purchases: on EA, the **Reserved Instances** and **Add Savings Plan** policies; on MCA, the billing profile's **Azure Reservation purchases** and **Azure Savings Plan** policies, set to **Yes**. Commitment Management adds nothing at the tenant, billing, or storage level, and nothing for the nOps.io application. > **Where do the commitments nOps buys live?** > > In the nOps tenant. When nOps staff buy through Lighthouse, Azure creates the reservation or savings plan order in the buyer's tenant. You still pay for it, because it's billed to your purchase subscription, and it applies to your resources: shared commitments cover your enrollment or billing profile. You see it in **Cost Management + Billing**, not under **Reservations** in your own tenant. > > If you stop using nOps, nOps moves your reservations to your tenant. Savings plans can't change tenant after purchase, so they stay in the nOps tenant until they end. > **Which subscription should I use?** > > Any active subscription in your enrollment or billing profile works, including one you already use or one that already has commitments. It must sit under the management group you connected in Savings Analysis. nOps only bills purchases to it. If you prefer to keep purchasing apart from your workloads, create an empty subscription for it. > > * **EA**: one subscription in your enrollment. Shared commitments cover every subscription in the enrollment. > * **MCA**: one subscription in each billing profile you want nOps to buy for. Shared commitments cover the subscriptions in that subscription's billing profile. > **Do I grant access once for my billing account, or for each billing profile?** > > Both, for different things: > > * **Seeing costs and commitments: once, at the billing account.** Savings Analysis already gives nOps.io Billing account reader, which covers every billing profile, including ones you add later. > * **Buying: once per billing profile.** Microsoft only lets someone buy a reservation through a subscription where they hold Owner or Reservation Purchaser, even billing account owners. The subscription's billing profile decides which invoice pays and which subscriptions a shared commitment covers, and a shared commitment never covers another billing profile. So nOps needs one delegated subscription in each billing profile it buys for, and no billing account role replaces that. > > With many billing profiles, the wizard lists them all and gives you one command that delegates every subscription at once. > **What if a billing profile already has reservations or savings plans?** > > Set it up the same way. Your existing commitments keep applying and stay where they are, and nOps sees them in the billing data Savings Analysis already reads. > > If nOps already buys for that billing profile through an earlier nOps delegation, enter the same subscription. Deploying the template updates that delegation in place, and nOps keeps managing what it bought. If Azure rejects the update, remove the old delegation under **Service providers** and deploy again. > **Can nOps exchange or refund commitments?** > > nOps can exchange or refund the reservations it buys, without extra roles: the buyer owns the order. nOps also makes its operations team a co-owner of every order it buys, including earlier ones, so managing a commitment never depends on one person's account. Partial exchanges are allowed, and Microsoft limits refunds to USD 50,000 in a rolling 12 months per enrollment or billing profile. Savings plans can't be canceled, refunded, or exchanged by anyone. > > Reservations you bought yourself live in your tenant. Lighthouse can't delegate them, so nOps can't exchange or refund them there. If you want nOps to manage one, its owner can move it to nOps with **Change directory**; your nOps contact will walk you through it. Moving it doesn't change who pays or which subscriptions a shared reservation covers. Savings plans can't change tenant after purchase, so you keep managing the ones you bought (their scope and renewal). > **What happens when I add a billing profile later?** > > Verify lists the billing profiles nOps has no purchase subscription for, so a new one shows up there. **Check connectivity** in Settings runs the same check, and you see the list when you open the integration's Verify step. To include it, open the integration, enter a subscription for the new profile in step 1, deploy the delegation on that subscription, turn on the purchase policies on the new billing profile, and Verify again. > **What happens to Savings Analysis while I set this up?** > > Nothing. Savings Analysis stays active the whole time, even if a Commitment Management check fails. Only Verify turns Commitment Management on. Once it has passed, it turns off only when a Verify finds something missing, such as the delegation or a policy. A read that failed doesn't change it. > **Do I need Inform to view Commitment Inventory?** > > No. [Commitment Inventory](/optimize/commitment-inventory) is included on every nOps plan when your Azure integration is **active**. Inform is only required to **email** or **schedule** inventory reports. *** ## Overview **Commitment Management** is the second tier of Azure onboarding. It builds on [Savings Analysis](/azure/integration-setup) and lets nOps: * Buy and manage Azure **Reservations** for you * Buy and manage Azure **Savings Plans** for you * Watch utilization and adjust commitment levels > [!WARNING] > > **Set up Savings Analysis first.** Commitment Management is added to a verified Savings Analysis integration. If you haven't set it up yet, start with [Savings Analysis Setup](/azure/integration-setup). > [!NOTE] > > **Before you start** > > * A verified Savings Analysis integration. Find it in [nOps Settings > Cloud Provider Integrations](https://clara.nops.io/settings) and look for **Enable CM**. > * **Owner** on each subscription you'll use for purchases, to deploy the delegation. > * **EA:** an Enterprise Administrator, if the purchase policies need turning on. > * **MCA:** a billing profile owner or contributor, if the purchase policies need turning on. > * **MCA billing account:** keep the **Billing account reader** role on nOps.io from Savings Analysis. Verify uses it to check which billing profile each purchase subscription bills to. *** ## What Commitment Management adds | Scope | Savings Analysis | Commitment Management adds | | - | - | - | | Purchase subscription (each) | Reader for nOps.io (inherited from your management group) | The nOps Commitment Management Lighthouse delegation for nOps staff: Reader, Reservation Purchaser, and Savings plan Purchaser | | EA enrollment, MCA billing account or billing profile | Read-only billing role | Nothing. The purchase policies must allow purchases: **Reserved Instances** and **Add Savings Plan** on (EA enrollment), or **Azure Reservation purchases** and **Azure Savings Plan** set to **Yes** (each MCA billing profile you buy for) | | Tenant, storage account, nOps.io | No change | Nothing | > [!NOTE] > > Earlier versions of this setup asked for Reservation Purchaser and Savings plan Purchaser for nOps.io, Reservations Administrator and Savings Plan Reader at the tenant, EA Purchaser or Billing account contributor, and Owner on the export storage account. None of these are needed now: nOps staff buy through the Lighthouse delegation. If you already have the older "nOps FinOps Management (Dedicated Subscription)" delegation, deploying the new template replaces it. If Azure rejects that, remove the old delegation under **Service providers** and deploy again. If Commitment Management is already on from the earlier setup, it stays on: open the integration and click **Verify Permissions** to run the new check. On EA, a service principal holds only one EA billing role. If you gave nOps.io EA Purchaser for the earlier setup, it replaced EnrollmentReader. If you remove EA Purchaser, assign EnrollmentReader to nOps.io again so Savings Analysis keeps its billing access. *** ## Step 1: Choose purchase subscriptions **1. Open the wizard** In [**nOps Settings > Cloud Provider Integrations**](https://clara.nops.io/settings), find your verified Azure integration and click **Enable CM**. Or click **Set Up Commitment Management** after Savings Analysis verifies. **2. Enter the subscriptions** The wizard shows the layout for how you connected Savings Analysis: * **EA**: one subscription. We fill in your Savings Analysis export subscription; change it if you like. * **MCA billing account**: one row for each billing profile in your billing account. Enter a subscription billed to each profile you want nOps to buy for, and leave the others blank. If you only want some profiles managed, fill in only those. If nOps can't list your billing profiles, you get a plain list instead: add one subscription per billing profile, and Verify tells you which profile each one bills to. * **MCA billing profiles**: one row for each billing profile you connected. Enter a subscription billed to that profile, or leave a row blank to skip the profile. To add a profile, connect it in Savings Analysis first. A subscription bills to one billing profile, so the wizard won't take the same subscription twice. **3. Click Continue** nOps saves the subscriptions and opens Run Setup. > [!TIP] > > A subscription's billing profile is on its **Overview** page in the Azure portal. *** ## Run the setup The wizard walks you through two steps, **A** and **B**. **A. Delegate purchasing to nOps** Do this on every purchase subscription. You need **Owner** on it. **1. Open the template** In the wizard, click **Deploy to Azure**. It opens the nOps Commitment Management template in the Azure portal. **2. Deploy it** Select the purchase subscription and any region, then click **Review + create** > **Create**. The deployment takes under a minute. **3. Repeat** Deploy it again for each other purchase subscription. Prefer the command line? The wizard shows a ready-to-run command for your subscriptions; run it in Azure Cloud Shell (Bash). For one subscription it looks like this: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} az deployment sub create --subscription "" --location eastus \ --name nops-commitment-management \ --template-uri "https://axb8wyvkymvzx0t0.public.blob.vercel-storage.com/azure/templates/lighthouse-portal-write-sub.json" ``` For several billing profiles, the wizard gives you one loop over every purchase subscription. It keeps going if one fails and prints **Delegated** or **FAILED** for each, so you can fix and re-run only what failed. Running it again is safe. ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} for sub in \ \ ; do az deployment sub create --subscription "$sub" --location eastus --name nops-commitment-management --template-uri "https://axb8wyvkymvzx0t0.public.blob.vercel-storage.com/azure/templates/lighthouse-portal-write-sub.json" --only-show-errors --output none && echo "Delegated $sub" || echo "FAILED $sub" done ``` You'll see the delegation under **Service providers** in the Azure portal, where you can remove it at any time. **B. Check the purchase policies** Microsoft only lets subscription purchasers buy commitments when your enrollment or billing profile allows it. **Enterprise Agreement (EA)** **1. Open Policies** Go to [**Cost Management + Billing**](https://portal.azure.com/#view/Microsoft_Azure_GTM/ModernBillingMenuBlade/~/Overview), select your EA billing account, then **Policies**. **2. Turn on purchases** Turn on **Reserved Instances** and **Add Savings Plan**, then click **Save**. An Enterprise Administrator can change these. **Microsoft Customer Agreement (MCA)** **1. Open the billing profile's Policies** Go to [**Cost Management + Billing**](https://portal.azure.com/#view/Microsoft_Azure_GTM/ModernBillingMenuBlade), select the billing account, then **Billing profiles**, the profile, and **Policies**. **2. Allow purchases** Under **Azure Reservations**, set **Azure Reservation purchases** to **Yes**. Under **Azure Savings Plan**, set **Azure Savings Plan** to **Yes**. Then click **Save**. A billing profile owner or contributor can change these. Repeat for each billing profile you buy for. When you're done, click **I've completed all steps**. *** ## Verify **1. Wait a few minutes** A new delegation can take a few minutes to show up. **2. Click Verify Permissions** For each purchase subscription, nOps checks that: * nOps can see the subscription (Reader from Savings Analysis covers it), and it is active, not disabled or deleted * **MCA billing account:** it is billed to your billing account * the nOps Commitment Management delegation is on it and gives nOps staff **Reservation Purchaser** and **Savings plan Purchaser** * **MCA:** it bills to the billing profile you chose * the purchase policies allow purchases: **Reserved Instances** and **Add Savings Plan** on (EA), or **Azure Reservation purchases** and **Azure Savings Plan** set to **Yes** (MCA) If the delegation is missing **Reader** (an older template), or nOps can't read a purchase policy, Verify shows a note instead of failing. It also notes two subscriptions that bill to the same billing profile, since one is enough. **MCA billing account:** nOps must also read which billing profile each subscription bills to. If it can't, Verify fails and asks you to check that nOps.io still has **Billing account reader**, then run Verify again. If Commitment Management is already on, it stays on. On a billing profiles connection, that read only shows a note. **MCA:** Verify also says how many of your billing profiles have a purchase subscription and names the ones that don't. On a billing account connection, a subscription counts only for the billing profile nOps confirms it bills to. Skipping a profile is fine; the list is there so a new billing profile doesn't go unnoticed. **3. Review the result** Verify also re-checks Savings Analysis. When Savings Analysis and every purchase subscription pass, you'll see **Commitment Management Verified**, and nOps can start buying for you. *** ## Additional resources * [Azure Lighthouse](https://learn.microsoft.com/en-us/azure/lighthouse/overview) * [Who can buy a reservation](https://learn.microsoft.com/en-us/azure/cost-management-billing/reservations/prepare-buy-reservation) * [Permissions to buy a savings plan](https://learn.microsoft.com/en-us/azure/cost-management-billing/savings-plan/permission-buy-savings-plan) * [Shared reservations cover one billing profile](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/mca-section-invoice#azure-reservation-benefits-might-not-apply-to-all-subscriptions) * [Move a reservation to another tenant](https://learn.microsoft.com/en-us/azure/cost-management-billing/reservations/troubleshoot-reservation-transfers-between-tenants) * [Azure Reservations overview](https://learn.microsoft.com/en-us/azure/cost-management-billing/reservations/save-compute-costs-reservations) * [Azure Savings Plans overview](https://learn.microsoft.com/en-us/azure/cost-management-billing/savings-plan/savings-plan-compute-overview) * [Azure built-in roles](https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles) # Microsoft Azure - Savings Analysis Setup Source: https://help.nops.io/azure/integration-setup Connect your Azure environment to nOps for read-only cost visibility, resource inventory, optimization recommendations, and daily FOCUS cost exports. ## FAQs > **What does Grant Admin Consent do?** > > It adds the **nOps.io** enterprise application (a service principal) to your Microsoft Entra ID tenant. It also approves the app's permissions for your whole organization, so no one else is asked to approve them. > > Microsoft's consent screen shows the app **nOps.io** from **nOps Inc** (a verified publisher). It lists these permissions: > > | Permission | What Microsoft says it allows | > | - | - | > | Access Azure Resource Manager as organization users | Allows the application to access Azure Resource Manager acting as users in the organization | > | Read directory data | Allows the app to read data in your organization's directory, such as users, groups and apps | > | Sign in and read user profile | Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users | > > The screen also says that if you accept, the app gets access to the specified resources for all users in your organization, and no one else will be prompted to review these permissions. > > Consent by itself gives nOps **no access** to your subscriptions, billing, or storage. nOps only gets Azure access from the roles you assign in [Run the Setup](#3-run-the-setup). > > nOps never signs in as your users. When Microsoft sends you back to nOps, nOps only learns your tenant ID and whether you accepted. After that, nOps connects with the app's own identity, using only the roles you assign. > > You need **Global Administrator** or **Privileged Role Administrator** to grant consent. To stop nOps's access later, delete or disable the **nOps.io** enterprise application in **Microsoft Entra ID** → **Enterprise applications**. You can also remove the role assignments you made during setup. > **Why does nOps need Reader on the management group?** > > A role you assign on a management group applies to every subscription under it, including subscriptions you add later. With **Reader** there, nOps can see all your subscriptions and their resources, with no setup on each subscription. > > Reader is read-only. nOps can't create, change, or delete anything. It can't read data inside storage accounts, and it can't read Key Vault secrets. > > To cover everything, use your tenant root management group. Its ID is your tenant ID. > **Why does nOps need a reader role at the billing account level?** > > You create the FOCUS export at your billing account (MCA) or enrollment (EA). nOps uses **Billing account reader** (MCA) or **EnrollmentReader** (EA) to find your billing account and billing profiles, and to check that the FOCUS export exists and runs. > > These roles are read-only. nOps can't change billing settings or make purchases. For MCA, one assignment at the billing account covers every billing profile, including profiles you add later. > **Should I connect the billing account or specific billing profiles?** > > We recommend the billing account. One **Billing account reader** assignment covers every billing profile, including profiles you add later, and you only need one FOCUS export. > > Choose billing profiles only if your organization gives access per billing profile. In that case: > > * You need a **Billing profile owner** for each profile. > * Each profile needs its own FOCUS export. > * Billing profiles you don't add aren't included in Savings Analysis. > > Billing profiles apply to MCA only. EA always connects at the enrollment. > **I'm a Global Administrator. Can I do the billing steps myself?** > > * **MCA:** Yes. First, give yourself **Billing account owner**. In [Cost Management + Billing](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade), open **Billing scopes**, select the box to view all billing accounts, and open your billing account. Then go to **Access control (IAM)** → **Add**, choose **Billing account owner**, and add yourself. Microsoft explains this in [Elevate access to manage billing accounts](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/elevate-access-global-admin). > * **EA:** No. A Global Administrator can't give themselves EA billing roles. An **Enterprise Administrator** has to do the EA billing steps. > **My billing account has some billing profiles from a CSP partner and some that are MCA. Does that change onboarding?** > > No. The setup steps are the same. A mix of CSP and MCA billing profiles under your billing account doesn't change anything in onboarding. > > You still need a billing account of your own (EA or MCA). Tenants billed only through a CSP partner aren't supported. > **Why does nOps use FOCUS exports?** > > FOCUS (FinOps Open Cost and Usage Specification) is an open standard format for cost data. Azure writes a daily FOCUS export to a storage account you own, and nOps reads those files. > > One export at the billing account covers every subscription and billing profile in it. It includes amortized costs for reservations and savings plans, and the discounts you receive. The files stay in your storage account, and you control them. > **Why does nOps need roles for the usage (FOCUS) export?** > > There are two sides: > > * **The person who sets up the export** needs a billing role at the billing scope, because that's where the export is created. They also need rights to create a storage account in the export subscription, such as **Owner** or **Contributor**. > * **nOps** needs the billing reader role to find the export and check that it runs daily. It also needs **Storage Blob Data Owner** on that one storage account to read the export files. > > The storage role applies only to that storage account, which only holds the export files. > **What resources do I create during setup?** > > You create these yourself in the Azure portal, in [Step C](#c-focus-cost-export). nOps doesn't create them. > > * A resource group named `nops-focus-exports-rg` > * A storage account named `nopsfocus` + the first 15 characters of your tenant ID (without dashes), with a container named `focus-exports` > * A FOCUS cost export with the prefix `nops-clara`, at your billing account (MCA), your enrollment (EA), or each billing profile you connect > > You choose the region when you create the storage account. These resources cost only the storage for the export files. > **Can I use an existing storage account instead?** > > No. Create the new storage account the wizard names in Step C. A dedicated storage account keeps the export files on their own, and the **Storage Blob Data Owner** role you give nOps.io applies to that storage account only. > **What if my organization restricts storage account network access?** > > If your organization uses Azure Policy to enforce storage account firewalls, allow the nOps IP addresses on the FOCUS export storage account. > > 1. Go to the storage account > **Security + networking** > **Networking** > 2. Under **Firewall**, add the nOps IP addresses: `44.246.45.84`, `52.11.53.164`, and `52.39.155.200` > 3. Make sure **"Allow Azure services on the trusted services list"** is checked > 4. Click **Save** > **How often is billing data refreshed?** > > FOCUS cost exports run **daily**. Cost data is typically available within 24-48 hours of the export run. Your first **Run now** includes the current month, and the backfill runs in Step C add the previous three months. > **How long does it take for Azure role assignments to propagate?** > > Azure role assignments typically take **2-5 minutes** to take effect. In some cases, it can take up to 10 minutes. If verification fails right after you finish setup, wait a few minutes and try again. *** ## Overview **Savings Analysis** is the first tier of Azure onboarding. It gives nOps **read-only** access to your Azure environment for: * Cost visibility across all subscriptions * Resource inventory (VMs, disks, networks) * Optimization recommendations (rightsizing, idle resources) * Daily FOCUS cost exports for cost tracking > [!NOTE] > > **Supported Billing Account Types:** nOps supports **Enterprise Agreement (EA)** and **Microsoft Customer Agreement (MCA)** billing accounts only. If you have a Pay-As-You-Go (MOSP) subscription, please contact your Microsoft account representative to upgrade to an EA or MCA billing account before proceeding. > [!NOTE] > > Savings Analysis does **not** allow purchasing reservations or savings plans. To enable automated commitment purchasing, complete this setup first, then follow the [Commitment Management Setup](/azure/commitment-management-setup) guide. > [!NOTE] > > **Prerequisites** -- Before you start, review the [Azure Integration Prerequisites](/azure/prerequisites). You'll need: > > * Your billing account type (EA or MCA) > * **EA only:** Your EA enrollment number. In [Cost Management + Billing](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade), select your EA billing account and copy the **Billing account ID** from **Settings > Properties** > * Your Management Group ID (or your tenant ID, to cover every subscription) > * A subscription to hold the storage account for the FOCUS export > * The three roles listed under [Required access](#required-access). Different people often hold them, so you may need help from other teams The nOps Azure Savings Analysis wizard has 4 steps: 1. **Get Started** -- Name your integration, pick your billing account type, and confirm your team has the required access 2. **Grant Admin Consent** -- Add the nOps.io app to your Microsoft Entra ID tenant 3. **Run Setup** -- Assign roles and create the FOCUS cost export in the Azure portal (Steps A–D) 4. **Verify** -- nOps checks that everything is in place *** ## 1. Get Started > [!TIP] > > **Before you begin:** make sure your organization has its own EA or MCA billing account. Tenants billed only through a CSP partner aren't supported. The wizard's **Before you begin** box shows how to run [Microsoft's CSP eligibility check](/azure/prerequisites#how-to-check-for-csp-subscriptions). You can also run the [nOps onboarding qualifier](/azure/prerequisites#recommended-run-the-nops-onboarding-qualifier), a read-only script that classifies each billing account (**EA / MCA / Reseller / CSP**) and gives a **PASS / FAIL** verdict. **1. Open Cloud Provider Integrations** Log in to **nOps** and go to [**Settings > Cloud Provider Integrations**](https://clara.nops.io/settings). Scroll down to the **Add a provider** section and click the **Microsoft Azure** card. **2. Enter an Integration Name** Provide a friendly name for this integration (e.g., "Production Azure Environment"). This name helps you identify the integration in the nOps dashboard. **3. Select Your Billing Account Type** Choose **EA** (Enterprise Agreement) or **MCA** (Microsoft Customer Agreement). This decides which billing steps you follow later. If you are unsure which type you have, see [Understanding Billing Account Types](/azure/prerequisites#1-understanding-billing-account-types). **4. Enter Your EA Enrollment Number (EA only)** If you selected **EA**, enter your **EA enrollment number**. You need it to continue. Find it in [Azure Portal > Cost Management + Billing](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade): select your EA billing account and copy the **Billing account ID** from **Settings > Properties**. For an EA, this is your numeric enrollment number. MCA users skip this step. **5. Check the Required Access List** The wizard lists the three roles your team needs (described in [Required access](#required-access) below). Tick each one you have, or know who has. You can continue once all three are ticked. **6. Click Continue** Click **Continue** to move on to Grant Admin Consent. ### Required Access Setup needs three roles. Different people often hold them, so check who on your team has each one before you start. 1. **Global Administrator** or **Privileged Role Administrator** (a Microsoft Entra ID role) * **Used for:** [Grant Admin Consent](#2-grant-admin-consent) * **nOps gets:** its app, the **nOps.io** enterprise application, in your tenant 2. **A billing role** (separate from Microsoft Entra ID roles and Azure RBAC roles) * **MCA billing account (default):** **Billing account owner** * **MCA billing profiles option:** **Billing profile owner** on each profile * **EA:** **Enterprise Administrator**. **Enterprise Administrator (read only)** can't do it, and neither can Department Administrator or Account Owner * **Used for:** Run Setup [Step A](#a-billing-role) and [Step C](#c-focus-cost-export) * **nOps gets:** **Billing account reader** (MCA), **Billing profile reader** on each selected profile, or **EnrollmentReader** (EA), plus a FOCUS export at that billing scope 3. **Owner** (an Azure RBAC role) on the management group and on the export subscription * **Used for:** Run Setup Steps [B](#b-reader-on-the-management-group), [C](#c-focus-cost-export), and [D](#d-storage-blob-data-owner) * **nOps gets:** **Reader** on the management group and **Storage Blob Data Owner** on the export storage account * **User Access Administrator** can do the role assignments in Steps B and D but can't create the storage account in Step C, so pair it with **Contributor** on the export subscription **MCA: billing account or billing profiles** By default, the wizard shows **nOps connects at your billing account (recommended)**. If you only have access to specific billing profiles, click **Only have access to specific billing profiles?** and then **Connect billing profiles instead**. You'll need a Billing profile owner for each profile, and each profile gets its own FOCUS export. To switch back, click **Use the billing account instead (recommended)**. EA always connects at the enrollment, so there's no billing profile option. > [!TIP] > > **MCA: are you a Global Administrator?** You can give yourself **Billing account owner** first. In [Cost Management + Billing](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade), open **Billing scopes**, select the box to view all billing accounts, and open your billing account. Then go to **Access control (IAM)** → **Add** → **Billing account owner**, and add yourself. See Microsoft's guide, [Elevate access to manage billing accounts](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/elevate-access-global-admin). > > This doesn't work for EA. An Enterprise Administrator has to do the EA billing steps. *** ## 2. Grant Admin Consent Admin consent adds the **nOps.io** enterprise application (a service principal) to your Microsoft Entra ID tenant. You need to do this before you can assign any roles to nOps. **1. Click Grant Admin Consent** In the nOps wizard, click the **Grant Admin Consent** button. Microsoft's sign-in page opens. **2. Sign In with an Admin Account** Sign in with an account that has the **Global Administrator** or **Privileged Role Administrator** role in Microsoft Entra ID. **3. Review and Accept Permissions** Microsoft shows the app **nOps.io** from **nOps Inc** (a verified publisher) and the permissions it asks for. Review them and click **Accept**. **4. Return to nOps** Microsoft sends you back to the nOps wizard. Your **Azure Tenant ID** now shows, which confirms that consent was granted. ### Understanding Admin Consent * Consent adds the nOps.io enterprise application to your tenant and approves its permissions for your whole organization, so no one else is asked to approve them. For the full list of permissions, see **What does Grant Admin Consent do?** in the [FAQs](#faqs). * Consent by itself gives nOps **no access** to your subscriptions, billing, or storage. nOps only gets Azure access from the roles you assign in [Run the Setup](#3-run-the-setup). * nOps never signs in as your users. It connects with the app's own identity, using only the roles you assign. > [!NOTE] > > **What is an enterprise application?** It's how an app from another organization appears in your Microsoft Entra ID tenant. It's also called a service principal. Consent adds it to your tenant. It isn't an app registration: the nOps app registration lives in nOps's own tenant, not yours. > [!WARNING] > > **Don't delete the nOps.io enterprise application** after you grant consent. If you delete it, nOps loses access and you'll need to grant admin consent again from the wizard. *** ## 3. Run the Setup You do this part in the Azure portal. It has four parts, **A** to **D**. Only the EA billing role in Step A needs the Azure CLI. > [!NOTE] > > The nOps wizard walks you through the same steps (labeled **A** through **D**), with your own values filled in. Follow along in the wizard or use the steps below. | Step | What you do | Why nOps needs it | | - | - | - | | **A. Billing role** | Give nOps.io a billing reader role | To find your billing account and billing profiles, and check your FOCUS export | | **B. Reader** | Give nOps.io **Reader** on your management group | To see your subscriptions and their resources | | **C. FOCUS cost export** | Create a daily FOCUS cost export and its storage account | So Azure writes your cost data to a storage account you own | | **D. Storage Blob Data Owner** | Give nOps.io **Storage Blob Data Owner** on that storage account | To read the export files | For every role, its ID, and what it allows, see [Permissions & Resources](/azure/permissions-and-resources). ### A. Billing Role Follow **only** the tab that matches your billing account type and how you connect it. **MCA: billing account (recommended)** > [!WARNING] > > **You need Billing account owner** on the MCA billing account. Azure RBAC **Owner** doesn't include billing roles. If you're a **Global Administrator**, you can give yourself Billing account owner first (see the tip under [Required access](#required-access)). If you can't, ask your Billing account owner to do this step. To see who holds this role, go to [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) → select your billing account → **Access control (IAM)**. **1. Open Your Billing Account** Go to [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) in the Azure portal and select your **Microsoft Customer Agreement** billing account. **2. Assign Billing account reader** 1. Click **Access control (IAM)** in the left menu. 2. Click **Add** at the top. 3. Select the role **Billing account reader**. 4. Search for **"nOps.io"** and select it. 5. Click **Review + assign** (or **Save**). **MCA: billing profiles** > [!NOTE] > > Use this tab only if your organization gives access per billing profile. Billing profiles you don't add aren't included in Savings Analysis. > [!WARNING] > > **You need Billing profile owner** on each billing profile you add. If you don't have it, ask the Billing profile owner of that profile to do this step. **1. Enter Your Billing Account and Billing Profile IDs** In the nOps wizard, enter your **billing account ID** and the **billing profile ID** of each profile you want to connect. * **Billing account ID:** in [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade), open your billing account → **Properties** * **Billing profile ID:** open **Billing profiles** → select the profile → **Properties** **2. Assign Billing profile reader on Each Profile** Do this on **each** billing profile you entered: 1. In **Cost Management + Billing**, open your billing account → **Billing profiles** → select the profile. 2. Click **Access control (IAM)** → **Add**. 3. Select the role **Billing profile reader**. 4. Search for **"nOps.io"** and select it. 5. Click **Review + assign** (or **Save**). **Enterprise Agreement (EA)** > [!WARNING] > > **You must be an Enterprise Administrator** on the EA enrollment to complete this step. Microsoft requires enrollment write access to assign EnrollmentReader to a service principal, so **Enterprise Administrator (read only)**, Department Administrator, and Account Owner cannot do it. Global Administrator and Azure RBAC Owner don't include EA billing roles, and a Global Administrator can't give themselves one. If you don't have this role, ask an Enterprise Administrator to run the script below. Check who holds it in [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) → select your EA billing account → **Access control (IAM)**. > [!WARNING] > > Microsoft only supports assigning EA billing roles (such as EnrollmentReader) to a service principal through the REST API, not the Azure portal. Run the script below in [Azure Cloud Shell](https://shell.azure.com) (Bash, not PowerShell) or a local terminal with the Azure CLI installed. You run this script yourself. nOps doesn't assign billing roles. **1. Sign in to Azure CLI** Open [Azure Cloud Shell](https://shell.azure.com) (Bash) or run `az login` in your local terminal. **2. Run the EnrollmentReader assignment script** Copy and run the following script. Replace ``, ``, and `` with your values (the nOps wizard pre-fills these in its generated script): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # Assign EnrollmentReader role to nOps service principal # Run in Azure Cloud Shell (Bash, not PowerShell) or a local terminal with Azure CLI NOPS_APP_CLIENT_ID="" # Look up the nOps service principal Object ID NOPS_SP_OBJECT_ID=$(az ad sp show --id "$NOPS_APP_CLIENT_ID" --query "id" -o tsv 2>/dev/null || true) if [ -z "$NOPS_SP_OBJECT_ID" ]; then echo "ERROR: nOps service principal not found. Complete the Admin Consent step first." exit 1 fi echo "Found nOps service principal: $NOPS_SP_OBJECT_ID" ROLE_ASSIGNMENT_GUID=$(uuidgen 2>/dev/null || cat /proc/sys/kernel/random/uuid) az rest --method PUT \ --url "https://management.azure.com/providers/Microsoft.Billing/billingAccounts//billingRoleAssignments/${ROLE_ASSIGNMENT_GUID}?api-version=2024-04-01" \ --body '{ "properties": { "principalId": "'"$NOPS_SP_OBJECT_ID"'", "principalTenantId": "", "roleDefinitionId": "/providers/Microsoft.Billing/billingAccounts//billingRoleDefinitions/24f8edb6-1668-4659-b5e2-40bb5f3a7d7e" } }' echo "Done. A 200 OK response confirms the EnrollmentReader role was assigned." ``` > [!TIP] > > The nOps wizard generates a ready-to-run script with all values pre-filled (App Client ID, enrollment number, and tenant ID). Copy it directly from the wizard for the easiest experience. > [!NOTE] > > **Fallback:** If `az ad sp show` fails, you can find the service principal manually: `az ad sp list --filter "startswith(displayName, 'nops')" --query "[].{name:displayName, objectId:id}" -o table` and use the **objectId** value. A `200 OK` response confirms the role was assigned. Service principal role assignments on an EA enrollment are not shown in the Azure portal, so use the nOps **Verify** step to confirm access. If you have more than one EA billing account, repeat the script for each enrollment. ### B. Reader on the Management Group Assign **Reader** on the management group that holds the subscriptions you want in Savings Analysis. You need **Owner** or **User Access Administrator** on that management group. **1. Enter Your Management Group ID** In the nOps wizard, enter the **Management Group ID**. To cover every subscription, click **Use tenant root**. Your tenant ID is the ID of the root management group. Find your management groups in [Azure Portal > Management Groups](https://portal.azure.com/#view/Microsoft_Azure_ManagementGroups/ManagementGroupBrowseBlade). **2. Open the Management Group** Go to [**Management Groups**](https://portal.azure.com/#view/Microsoft_Azure_ManagementGroups/ManagementGroupBrowseBlade) in the Azure portal and select the management group. **3. Open Access Control** Click **Access control (IAM)** in the left menu, then click **Add** > **Add role assignment**. **4. Select the Role** On the **Role** tab, search for and select **Reader**, then click **Next**. **5. Assign to nOps.io** 1. On the **Members** tab, set **"Assign access to"** to **"User, group, or service principal"** (not "Managed identity"). 2. Click **"+ Select members"**. 3. Search for **"nOps.io"** by name and select it. 4. Click **Select**. 5. Click **Review + assign**. Repeat only if your subscriptions are split across separate management groups. ### C. FOCUS Cost Export **1. Choose the Export Subscription** In the nOps wizard, enter the subscription that will hold the export's storage account. Choose the subscription with the most spend. To create the storage account, you need **Owner** or **Contributor** on this subscription. **2. Register Resource Providers** Make sure these resource providers are registered on that subscription: `Microsoft.Storage`, `Microsoft.CostManagement`, and `Microsoft.CostManagementExports`. Go to [**Subscriptions**](https://portal.azure.com/#view/Microsoft_Azure_Billing/SubscriptionsBlade) → select the subscription → **Settings** → **Resource providers**, and click **Register** on any that aren't registered. Most subscriptions already have these registered. If a provider already shows "Registered", no action is needed. **3. Open Exports and Set the Scope** Go to [**Cost Management > Exports**](https://portal.azure.com/#view/Microsoft_Azure_CostManagement/Menu/~/exports) in the Azure portal. At the top, click **Change scope** if needed, and select: * **MCA billing account:** your Microsoft Customer Agreement billing account * **EA:** your EA enrollment (the same enrollment number you entered in the nOps wizard, e.g., `12345678`) * **MCA billing profiles:** one of your billing profiles. You'll create a separate export for each profile **4. Create the Export** 1. Click **+ Create**. 2. **Basics** tab: Select the **"Cost and usage (FOCUS)"** template. 3. **Datasets** tab: Set the export prefix to `nops-clara`. The template sets the frequency to **Daily**. * **MCA billing profiles only:** use the prefix the nOps wizard shows for that profile. It's `nops-clara-` followed by letters and digits from the billing profile ID, in lowercase. This keeps the exports from overwriting each other. 4. **Destination** tab: * Storage type: **Azure blob storage** * Subscription: the subscription you entered in the nOps wizard * Storage account: Click **Create new** * Resource group: create a new one named `nops-focus-exports-rg` * Name: `nopsfocus` + the first 15 characters of your tenant ID, without dashes * Region: any region you choose * Container: `focus-exports` * Directory: `nops-clara` * Format: **Parquet** * Compression type: **Snappy** * File partitioning: **checked** * Overwrite data: **checked** 5. Click **Review + create**, then **Create**. **5. Run the Export and Backfill 3 Months** 1. Open the export and click **Run now** to trigger the first export. 2. Click **Export selected dates** to backfill the previous 3 months, one run per month: * **Run 1:** Start date = first day of three months ago, End date = last day of three months ago * **Run 2:** Start date = first day of two months ago, End date = last day of two months ago * **Run 3:** Start date = first day of previous month, End date = last day of previous month Data will be available within a few hours. > [!NOTE] > > **MCA billing profiles:** repeat these export steps for each billing profile you connect, with that profile's prefix. After the first profile, select the storage account you already created instead of creating a new one. > [!TIP] > > The nOps wizard shows the exact storage account name, resource group, container, and directory you need. Copy these values from the wizard so they match what nOps checks in Verify. ### D. Storage Blob Data Owner You must be an **Owner** or **User Access Administrator** on the storage account to assign Storage Blob Data Owner. **1. Open the Storage Account** Search for **"Storage accounts"** in the Azure portal's top search bar, then select the storage account you created in Step C (e.g., `nopsfocus`). **2. Assign Storage Blob Data Owner** 1. Go to **Access control (IAM)** → **Add** → **Add role assignment**. 2. Under **Job function roles**, select **Storage Blob Data Owner**. 3. Select **User, group, or service principal**. 4. Search for and select **nOps.io**. 5. Click **Review + assign**. **3. Configure Firewall (if applicable)** If your organization restricts storage account network access (through Azure Policy or manual settings): 1. Go to the storage account > **Security + networking** > **Networking** 2. Under **Firewall**, add the nOps IP addresses: `44.246.45.84`, `52.11.53.164`, and `52.39.155.200` 3. Make sure **"Allow Azure services on the trusted services list"** is checked 4. Click **Save** > [!NOTE] > > Skip this step if your storage account allows public network access (the default). nOps reads the export files from outside Azure, so if a firewall is on, it must allow the nOps IP addresses. > [!NOTE] > > Azure role assignments can take **2-5 minutes** to propagate. If verification fails right after you assign roles, wait a few minutes and try again. ### Finish in nOps When you've completed Steps A through D, return to the nOps wizard and click **"I've completed all steps"** to go to Verify. *** ## 4. Verify Connection nOps checks that each part of the setup is in place. **1. Click Verify Permissions** Click the **Verify Permissions** button. nOps checks: * **Reader** -- nOps can list your subscriptions * **Billing role** -- nOps has Billing account reader (MCA), Billing profile reader (MCA billing profiles), or EnrollmentReader (EA) * **FOCUS export** -- a FOCUS export exists at the right billing scope * **Storage Blob Data Owner** -- nOps can list the export container If you connected billing profiles, nOps checks **Billing profile reader** and a FOCUS export on each profile. It skips a profile's export check until that profile's billing role is in place. **2. Review Results** The wizard shows a pass or fail result for each check. When they all pass, you'll see **"Savings Analysis Verified"** with the number of connected subscriptions. > [!WARNING] > > **Verification Failed?** -- If some checks don't pass yet: > > 1. Wait a few more minutes. Azure role assignments can take time to propagate > 2. Check that each role was assigned to **nOps.io** at the right scope: the billing role (Step A), Reader on the management group (Step B), and Storage Blob Data Owner on the storage account (Step D) > 3. Check that the FOCUS export exists at your billing account, enrollment, or each billing profile you connected (Step C) > 4. Click **Verify Permissions** to check again *** ## Next Steps Once the Savings Analysis integration is verified, nOps begins ingesting your cost data and generating optimization recommendations. To enable automated purchasing and management of Azure Reservations and Savings Plans, you can upgrade your integration to the Commitment Management tier: > **[Azure Commitment Management Setup](/azure/commitment-management-setup)** > > Configure nOps to manage Azure Reservations and Savings Plans on your behalf, including automated purchasing and optimization. # Microsoft Azure - Permissions & Resources Source: https://help.nops.io/azure/permissions-and-resources Complete reference of all permissions nOps requires and all resources nOps creates in your Azure environment. ## Overview nOps offers two integration tiers, each requiring different levels of access: 1. **[Savings Analysis](/azure/integration-setup)** -- Read-only cost visibility, resource inventory, and optimization recommendations 2. **[Commitment Management](/azure/commitment-management-setup)** -- Automated purchasing and management of Azure Reservations and Savings Plans (builds on Savings Analysis) > [!WARNING] > > **Cloud Solution Provider (CSP) subscriptions are NOT supported.** nOps only works with direct Microsoft agreements -- Enterprise Agreement (EA) or Microsoft Customer Agreement (MCA). *** ## Permissions -- Savings Analysis Savings Analysis uses three roles: **Reader**, **Storage Blob Data Owner**, and one billing role. That's the complete list. You assign all of them to **nOps.io** during [Run the Setup](/azure/integration-setup#3-run-the-setup). ### Management Group Scope | Role | Role Definition ID | Purpose | | - | - | - | | Reader | `acdd72a7-3385-48ef-bd42-f606fba81ae7` | View all subscriptions and their resources, including subscriptions you add later | ### Storage Account Scope | Role | Role Definition ID | Purpose | | - | - | - | | Storage Blob Data Owner | `b7e6dc6d-f1e8-4753-8033-0f276bb0955b` | Read FOCUS cost export files from the storage account (data plane) | > [!NOTE] > > The **Storage Blob Data Owner** role is granted only on the storage account you create for the FOCUS export (`nopsfocus`) -- it does not grant access to any other resources in your environment. Savings Analysis does **not** need the Azure RBAC **Owner** role on the storage account. Owner is a management-plane role and cannot read blob data. ### Billing Scope You assign **one** of these, depending on your billing account type and how you connect it: | Billing Account Type | Role | Role Definition ID | Scope | Purpose | | - | - | - | - | - | | Microsoft Customer Agreement (MCA), billing account (default) | Billing account reader | `50000000-aaaa-bbbb-cccc-100000000002` | Billing account | Find your billing account and billing profiles, and check that the FOCUS export exists and runs | | Microsoft Customer Agreement (MCA), billing profiles option | Billing profile reader | `40000000-aaaa-bbbb-cccc-100000000002` | Each selected billing profile | Check the billing profile and its FOCUS export | | Enterprise Agreement (EA) | EnrollmentReader | `24f8edb6-1668-4659-b5e2-40bb5f3a7d7e` | Enrollment (billing account) | Find your enrollment and check that the FOCUS export exists and runs | These billing roles are read-only. nOps can't change billing settings or make purchases with them. > [!NOTE] > > **Not used by Savings Analysis:** Cost Management Contributor, Monitoring Reader, Reservations Reader, Savings Plan Reader, Owner on the storage account, Azure Lighthouse, and Azure Policy. (Commitment Management uses Lighthouse.) *** ## Permissions -- Commitment Management Commitment Management adds one **Azure Lighthouse delegation** on each **purchase subscription**, the subscription each reservation or savings plan is billed to. nOps staff buy in the Azure portal through it, signed in to the nOps tenant. Nothing is added at the tenant, billing, or storage level, or for the nOps.io application. ### Purchase Subscription Scope (nOps Commitment Management delegation) The delegation gives the **nOps Customer Access Operators** group in the nOps tenant (`9a93f7e1-76f9-4a8d-a15e-5eeb73cf1d18`) these roles: | Role | Role Definition ID | Purpose | | - | - | - | | Reader | `acdd72a7-3385-48ef-bd42-f606fba81ae7` | See the subscription under My customers | | Reservation Purchaser | `f7b75c60-3036-4b75-91c3-6b41c27c1689` | Buy reservations billed to this subscription | | Savings plan Purchaser | `3d24a3a0-c154-4f6f-a5ed-adc8e01ddb74` | Buy savings plans billed to this subscription | * **EA:** one subscription in your enrollment. * **MCA:** one subscription in each billing profile nOps buys for (shared commitments apply per billing profile). Any active subscription under the management group you connected works, including one that already has commitments. If you'd rather keep purchasing apart from your workloads, use an empty one. You can see or remove the delegation under **Service providers** in the Azure portal. > [!NOTE] > > **Billing account or billing profile?** Visibility is granted once, at the billing account: the Billing account reader role from Savings Analysis covers every billing profile, including new ones. Buying is per billing profile. Microsoft requires Owner or Reservation Purchaser on the subscription a purchase is billed to, even for billing account owners, and a shared commitment covers only that subscription's billing profile. No billing account role replaces the purchase subscription in each profile. > > Commitment Management Verify also uses Billing account reader to check which billing profile each purchase subscription bills to. On a billing account connection, Verify fails if it can't. > [!NOTE] > > **Where purchases live.** A reservation or savings plan nOps staff buy is created in the nOps tenant and owned by the buyer, so nOps can exchange or refund the reservations it buys. It's billed to your purchase subscription and applies to your resources. If you stop using nOps, nOps moves your reservations to your tenant; savings plans can't change tenant. > [!NOTE] > > **Not used by Commitment Management:** purchaser roles for nOps.io, Reservations Administrator or Savings Plan Reader at the tenant, EA Purchaser, Billing account or profile contributor, Cost Management Contributor, Monitoring Reader, and Owner on the storage account. ### Complete Role Summary > **All roles at a glance (Savings Analysis + Commitment Management)** > > | Scope | Role | Savings Analysis | Commitment Management | > | - | - | :-: | :-: | > | Management Group | Reader | Yes | (from SA) | > | Storage Account (FOCUS export) | Storage Blob Data Owner | Yes | (from SA) | > | Billing Account (MCA) | Billing account reader | Yes (default) | (from SA) | > | Billing Profile (MCA) | Billing profile reader | Yes (billing profiles option) | (from SA) | > | Billing Account (EA enrollment) | EnrollmentReader | Yes | (from SA) | > | Purchase Subscription (each) | Reader, Reservation Purchaser, Savings plan Purchaser (nOps staff, through Lighthouse) | -- | Yes | *** ## Resources in Your Environment Admin consent adds the nOps.io enterprise application to your tenant. You create everything else yourself during setup: the FOCUS export resources for Savings Analysis, and for Commitment Management the Lighthouse delegation on each purchase subscription. ### nOps.io Enterprise Application (created by admin consent) When you grant admin consent, Microsoft adds the **nOps.io** enterprise application (a service principal) to your Microsoft Entra ID tenant. This is the identity nOps uses to connect to Azure. It isn't an app registration: the nOps app registration lives in nOps's own tenant. Consent by itself gives nOps no access to your subscriptions, billing, or storage. nOps only gets access from the roles you assign. ### FOCUS Export Resources (created by you) You create these in the Azure portal during [Step C of the setup](/azure/integration-setup#c-focus-cost-export). nOps doesn't create them. | Resource | Name | Where | | - | - | - | | Resource Group | `nops-focus-exports-rg` | The export subscription you choose (region of your choice) | | Storage Account | `nopsfocus` + the first 15 characters of your tenant ID, without dashes | In `nops-focus-exports-rg` (region of your choice) | | Blob Container | `focus-exports` | In the storage account | | FOCUS Cost Export | Prefix `nops-clara` (billing profiles option: the per-profile prefix the nOps wizard shows, starting with `nops-clara-`) | Your billing account (MCA), enrollment (EA), or each billing profile you connect | > [!NOTE] > > These resources cost only the storage for the exported cost data. ## Required Resource Providers ### FOCUS Export Subscription | Resource Provider | Purpose | | - | - | | `Microsoft.Storage` | Storage account for FOCUS export data | | `Microsoft.CostManagement` | Cost queries and management | | `Microsoft.CostManagementExports` | FOCUS export creation and scheduling | *** ## Required Purchase Policies Required for **Commitment Management** only. | Billing Account Type | Policy Location | Setting | Required Value | | - | - | - | - | | Enterprise Agreement (EA) | EA billing account > Policies | Reserved Instances | **On** | | Enterprise Agreement (EA) | EA billing account > Policies | Add Savings Plan | **On** | | Microsoft Customer Agreement (MCA) | Billing profile > Policies | Azure Reservation purchases | **Yes** | | Microsoft Customer Agreement (MCA) | Billing profile > Policies | Azure Savings Plan | **Yes** | Verify reads these through the `reservationPurchases` and `savingsPlanPurchases` billing policy properties. When nOps can't read them, Verify shows a note instead of failing. *** ## Network Requirements If your organization enforces storage account firewalls, whitelist the following nOps IP addresses on the FOCUS export storage account: | IP Address | | - | | `44.246.45.84` | | `52.11.53.164` | | `52.39.155.200` | Also ensure **"Allow Azure services on the trusted services list"** is enabled on the storage account firewall. > [!NOTE] > > If your storage account allows public network access (the default), no firewall configuration is needed. *** ## Related Guides > **[Prerequisites](/azure/prerequisites)** > > Prepare your Azure environment for nOps onboarding. > **[Savings Analysis Setup](/azure/integration-setup)** > > Step-by-step guide to connect Azure for read-only cost visibility. > **[Commitment Management Setup](/azure/commitment-management-setup)** > > Configure automated purchasing of Azure Reservations and Savings Plans. # Microsoft Azure - Prerequisites Source: https://help.nops.io/azure/prerequisites Understand billing account types, locate your Management Group ID, and prepare your Azure environment for nOps onboarding. ## FAQs > **What is the difference between EA and MCA billing accounts?** > > * **Enterprise Agreement (EA)**: A contract between your organization and Microsoft for large-scale Azure usage. EA billing accounts use numeric enrollment numbers (e.g., `12345678`). > * **Microsoft Customer Agreement (MCA)**: A newer billing model available through Microsoft sales representatives or the Azure portal. MCA billing accounts use GUID-based IDs (e.g., `5e98e158-xxxx-xxxx-xxxx-xxxxxxxxxxxx:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx_2019-05-31`). > > If you are unsure which type you have, go to [Cost Management + Billing](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) in the Azure Portal and check the **Properties** of your billing account. > **What is a Management Group?** > > A Management Group is a container in Azure that helps you manage access, policies, and compliance across multiple subscriptions. All subscriptions within a management group automatically inherit the conditions applied to the management group, including RBAC role assignments. > > During setup, you give nOps the **Reader** role on a management group, so every subscription under it is covered, including subscriptions you add later. > **Why does nOps require admin consent?** > > nOps uses a **multi-tenant Azure application** called **nOps.io**. When you grant admin consent, Microsoft adds the nOps.io **enterprise application** (a service principal) to your Microsoft Entra ID tenant. This is the identity nOps uses to connect to Azure. You don't give nOps any passwords or keys. > > Consent by itself gives nOps no access to your subscriptions, billing, or storage. nOps only gets access from the roles you assign during setup. > **Can I use the root management group?** > > Yes. If you want nOps to have visibility across **all** subscriptions in your tenant, use your **Tenant ID** as the Management Group ID. The root management group in Azure always matches the Tenant ID. *** ## Overview Integrate your **Microsoft Azure** environment with the nOps platform for comprehensive cost tracking, optimization recommendations, and commitment management. This integration uses Azure's native RBAC system and FOCUS cost exports to provide full visibility into your Azure spending. nOps supports two onboarding tiers: 1. **[Savings Analysis](/azure/integration-setup)** -- Read-only cost visibility, resource inventory, and optimization recommendations 2. **[Commitment Management](/azure/commitment-management-setup)** -- Automated purchasing and management of Azure Reservations and Savings Plans (requires Savings Analysis first) *** ## What You'll Need Setup needs three kinds of roles. Different people on your team often hold them. * **Microsoft Entra ID:** **Global Administrator** or **Privileged Role Administrator** -- to grant admin consent for the nOps.io app * **Azure RBAC:** **Owner** or **User Access Administrator** on the management group and on the export subscription -- to assign roles to nOps.io. To create the export storage account, you also need **Owner** or **Contributor** on the export subscription * **Billing role (Savings Analysis):** * **MCA (default):** **Billing account owner** on the MCA billing account -- to assign the **Billing account reader** role to nOps.io and create the FOCUS export. Find who holds this role in [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) → select billing account → **Access control (IAM)**. * **MCA, billing profiles option:** if your organization only gives access to specific billing profiles, you can connect those instead. You need a **Billing profile owner** on each profile -- to assign the **Billing profile reader** role to nOps.io and create a FOCUS export on each profile. Find who holds this role in **Cost Management + Billing** → select billing account → **Billing profiles** → select profile → **Access control (IAM)**. * **EA:** **Enterprise Administrator** on the EA enrollment -- to assign the **EnrollmentReader** role to nOps.io and create the FOCUS export. Microsoft only lets an Enterprise Administrator with write access assign EA billing roles; **Enterprise Administrator (read only)**, Department Administrator, and Account Owner cannot. Microsoft only supports assigning EA billing roles to a service principal through the REST API, not the Azure Portal. Find who holds this role in [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) → select your EA billing account → **Access control (IAM)**. * Your **Management Group ID** -- determines the scope of nOps visibility * An **Azure Subscription** -- to hold the storage account for the FOCUS cost export. You create these resources yourself during setup * Knowledge of your **Billing Account Type** -- Enterprise Agreement (EA) or Microsoft Customer Agreement (MCA) **Additional requirements for Commitment Management:** * A **purchase subscription** that purchases are billed to: one in your EA enrollment, or one in each MCA billing profile nOps buys for. Any active subscription works, as long as it sits under the management group you connect for Savings Analysis. An empty one is optional * **Owner** on each purchase subscription -- to deploy the **nOps Commitment Management** Azure Lighthouse delegation, which lets nOps staff buy commitments billed to it * The purchase policies allowing purchases: **Reserved Instances** and **Add Savings Plan** on for EA (an Enterprise Administrator can change them), or **Azure Reservation purchases** and **Azure Savings Plan** set to **Yes** on each MCA billing profile (a billing profile owner or contributor can change them) * **MCA billing account:** keep **Billing account reader** on nOps.io. Commitment Management Verify uses it to find each purchase subscription's billing profile > [!WARNING] > > **Entra ID roles ≠ Azure RBAC roles ≠ billing roles.** Being a Global Administrator in Microsoft Entra ID does **not** automatically give you permissions on Azure resources (subscriptions, management groups). Azure RBAC Owner doesn't include billing roles either. > > * **MCA:** a Global Administrator can give themselves **Billing account owner** first. See Microsoft's guide, [Elevate access to manage billing accounts](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/elevate-access-global-admin). > * **EA:** a Global Administrator can't give themselves EA billing roles. An **Enterprise Administrator** (not read only) must do the EA billing steps. > > If you are a Global Admin but have never managed Azure resources, follow the steps below to enable Azure RBAC access. *** ## Enabling Azure RBAC Access for Global Admins Azure has three separate permission systems that are commonly confused: | System | What It Controls | Example Roles | | - | - | - | | **Microsoft Entra ID roles** | Identity, directory, and app registration management | Global Administrator, User Administrator | | **Azure RBAC roles** | Azure resource operations (subscriptions, VMs, storage, etc.) | Owner, Contributor, Reader | | **Billing roles** | Billing accounts, billing profiles, and EA enrollments | Billing account owner, Billing profile owner (MCA); Enterprise Administrator (EA) | The nOps setup requires **Azure RBAC permissions** (Owner or User Access Administrator) to assign roles to nOps.io. If you are a Global Administrator without Azure RBAC roles, you'll need to enable elevated access. The steps below cover Azure RBAC only. For billing roles, see the warning above. **1. Enable Elevated Access** 1. Go to [**Microsoft Entra ID > Properties**](https://portal.azure.com/#view/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/~/Properties) in the Azure Portal 2. Find **"Access management for Azure resources"** 3. Toggle to **Yes** and click **Save** This grants your Global Admin account the `User Access Administrator` role at the root scope, which cascades to all management groups and subscriptions. **2. Sign Out and Sign Back In** You must sign out of the Azure Portal and sign back in to pick up the new `User Access Administrator` role: 1. Click your profile picture in the top-right corner of the Azure Portal 2. Click **Sign out** 3. Navigate back to [portal.azure.com](https://portal.azure.com) and sign in again > [!NOTE] > > Azure uses Continuous Access Evaluation (CAE) which may invalidate cached tokens when permissions change. After signing back in, if you still see permission errors, wait 2-3 minutes for the role to fully propagate. **3. Assign Yourself Owner on the Subscription** The `User Access Administrator` role only allows managing role assignments. You also need `Owner` to register resource providers and manage resources: 1. Go to [**Subscriptions**](https://portal.azure.com/#view/Microsoft_Azure_Billing/SubscriptionsBlade) in the Azure Portal 2. Select the subscription where you'll run the nOps setup 3. Click **Access control (IAM)** in the left menu 4. Click **Add** > **Add role assignment** 5. In the **Role** tab, search for and select **Owner** 6. In the **Members** tab, click **+ Select members** 7. Search for your email address and select your user account 8. Click **Select**, then **Review + assign** **4. Verify Access** To confirm you now have the necessary permissions: 1. Go to the subscription you just assigned Owner to 2. Click **Access control (IAM)** in the left menu 3. Click **View my access** (top button) 4. You should see both **User Access Administrator** (inherited from root) and **Owner** (subscription-level) listed > [!NOTE] > > The first time you access Management Groups or run certain operations, Azure may automatically register resource providers like `Microsoft.Management`. This one-time operation can take 30-60 seconds. > [!NOTE] > > For more details, see Microsoft's documentation on [Elevating access to manage all Azure subscriptions](https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin). *** ## 1. Understanding Billing Account Types Your billing account type determines how nOps configures billing access. You must select the correct type during onboarding. **Follow only the path that matches your agreement.** EA and MCA are two separate setup paths. > [!NOTE] > > **Supported Billing Account Types:** nOps supports **Enterprise Agreement (EA)** and **Microsoft Customer Agreement (MCA)** billing accounts only. If you have a Pay-As-You-Go (MOSP) subscription, please contact your Microsoft account representative to upgrade to an EA or MCA billing account before proceeding. ### Path A: If you have an Enterprise Agreement (EA) Use this path if your organization has a direct **Enterprise Agreement** with Microsoft. **What you need:** * **EA Enrollment Number:** A numeric ID (e.g., `12345678`) that identifies your EA billing account. You will enter this in the nOps wizard in **Get Started**. * **Where to find it:** Go to [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) in the Azure Portal, select your Enterprise Agreement billing account, then open **Settings > Properties** and copy the **Billing account ID**. For an EA, the billing account ID is your enrollment number. * **Billing hierarchy:** Enrollment → Departments → Accounts → Subscriptions. nOps always connects at the enrollment (billing account) scope, for both the billing role and the FOCUS export. EA has no billing profile option. * **How to confirm:** In Cost Management + Billing, open your billing account → **Settings > Properties**. The **Agreement type** field must show **"Enterprise Agreement"**. ### Path B: If you have a Microsoft Customer Agreement (MCA) Use this path if your organization has a **Microsoft Customer Agreement** (the newer billing model, often via Microsoft sales or the Azure portal). **What you need:** * **Billing Account:** Your MCA billing account (GUID-style ID). You do **not** need to enter a numeric enrollment number. By default, nOps connects at your billing account (recommended), which covers every billing profile in it. * **Billing profiles option:** If your organization only gives access to specific billing profiles, you can connect those instead. You'll enter your billing account ID and each billing profile ID in the nOps wizard, and you'll need a **Billing profile owner** for each profile. Billing profiles you don't add aren't included in Savings Analysis. * **Where to find it:** Go to [**Cost Management + Billing**](https://portal.azure.com/#blade/Microsoft_Azure_GTM/ModernBillingMenuBlade) in the Azure Portal and select your **Microsoft Customer Agreement** billing account. The billing account ID is under **Properties**. For a billing profile ID, open **Billing profiles** → select the profile → **Properties**. Commitment Management doesn't add a billing role: it uses one purchase subscription in each billing profile nOps buys for. * **Billing hierarchy:** Billing Account → Billing Profiles → Invoice Sections → Subscriptions. * **How to confirm:** In Cost Management + Billing, open your billing account → **Settings > Properties**. The **Agreement type** field must show **"Microsoft Customer Agreement"**. ### Quick reference: EA vs MCA | Feature | Enterprise Agreement (EA) | Microsoft Customer Agreement (MCA) | | - | - | - | | **ID Format** | Numeric enrollment number (e.g., `12345678`) | GUID format (e.g., `5e98e158-xxxx-..._2019-05-31`) | | **Billing Hierarchy** | Enrollment > Departments > Accounts > Subscriptions | Billing Account > Billing Profiles > Invoice Sections > Subscriptions | | **Billing Role for nOps (Savings Analysis)** | EnrollmentReader | Billing account reader (or Billing profile reader on each profile, with the billing profiles option) | | **How to Check** | Properties show "Enterprise Agreement" | Properties show "Microsoft Customer Agreement" | *** ## 2. Verifying You Do NOT Have a CSP Subscription > [!WARNING] > > **Cloud Solution Provider (CSP) subscriptions are NOT supported.** nOps only works with direct Microsoft agreements (EA or MCA). If your Azure account is through a reseller or partner using the CSP program, you cannot use nOps. A **Cloud Solution Provider (CSP)** is a Microsoft partner who resells Azure services. CSP subscriptions are billed through the partner, not directly by Microsoft. This creates a different billing structure that nOps does not currently support. ### Recommended: run the nOps onboarding qualifier The fastest way to confirm eligibility is the **nOps onboarding qualifier**, a read-only script that groups your subscriptions by billing account, classifies each as **EA / MCA / Reseller / CSP**, shows month-to-date spend, and prints an overall verdict. **What it does, and does not do** * It is completely read-only. It does not create, modify, deploy, or configure anything in your environment, and it does not grant nOps any access. * It reads only billing metadata (the billing account, profile, and agreement type each subscription belongs to) and month-to-date spend per subscription. * Nothing is transmitted anywhere. The script prints its results to your screen, and you decide what to share. > [!NOTE] > > For spend figures, the account you sign in with needs **Cost Management Reader** (or **Reader**) at subscription scope. Without it, those subscriptions show `n/a` instead of a number, and the EA / MCA / CSP classification still works. **Run it in Azure Cloud Shell (about two minutes)** Cloud Shell already has the Azure CLI and `jq` installed and is signed in as you, so there is nothing to install and no separate login. **1. Sign in, then open Cloud Shell** Sign in to the [Azure portal](https://portal.azure.com) with an account that can view your billing (ideally whoever manages billing for your organization), confirm your organization's directory is selected (top right), then open **Cloud Shell** with the `>_` icon in the top toolbar. Choose **Bash** if prompted. **2. Add the script** Upload `nops-onboarding-qualifier.sh` (**Manage files → Upload**), or copy the script below and paste it into Cloud Shell. **3. Run it** Run `bash nops-onboarding-qualifier.sh`. It finishes in a few seconds. Add `--csv results.csv` to also write a CSV, `--last-month` for the previous month's spend, or `--help` for all options. > [!TIP] > > Prefer your own terminal? With the [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli) and [jq](https://jqlang.github.io/jq/download/) installed, run `az login` and then `bash nops-onboarding-qualifier.sh`. > **nops-onboarding-qualifier.sh (click to expand)** > > ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} > #!/usr/bin/env bash > # === nOps onboarding qualifier === > # Groups subscriptions by billing account -> profile, classifies each account > # EA / MCA / Reseller / CSP, shows spend, gives an onboard verdict. Read-only. > # Best run as the customer's billing admin, in their tenant. > # > # Hardened: portable (no md5sum), honest failures (n/a vs 0.00), preflight > # checks, RBAC caveat, safe arg parsing, mixed-currency flagging. > set -u > CSV=""; SKIP_COST=0; WINDOW="MonthToDate" > while [ $# -gt 0 ]; do case "$1" in > --csv) [ $# -ge 2 ] || { echo "--csv needs a FILE argument" >&2; exit 1; }; CSV="$2"; shift 2;; > --last-month) WINDOW="TheLastMonth"; shift;; > --skip-cost) SKIP_COST=1; shift;; > -h|--help) echo "Usage: $0 [--csv FILE] [--last-month] [--skip-cost]"; exit 0;; > *) echo "unknown option: $1" >&2; exit 1;; esac; done > > command -v jq >/dev/null || { echo "jq not found — install jq and retry" >&2; exit 1; } > command -v az >/dev/null || { echo "az (Azure CLI) not found — install it and run 'az login'" >&2; exit 1; } > az account show >/dev/null 2>&1 || { echo "not logged in — run 'az login' first" >&2; exit 1; } > > D=$(mktemp -d) || { echo "mktemp -d failed" >&2; exit 1; }; trap 'rm -rf "$D"' EXIT; : > "$D/rows"; mkdir -p "$D/pc" > > echo "Signed in as : $(az account show --query user.name -o tsv 2>/dev/null)" > echo "Tenant : $(az account show --query tenantId -o tsv 2>/dev/null)" > echo "Note : costs need Cost Management Reader (or Reader) at subscription scope;" > echo " subscriptions without it show 'n/a', not 0.00." > echo "Qualifying..." > > # billing accounts the signed-in identity has a billing role on (visibility flag) > az rest --method get \ > --url "https://management.azure.com/providers/Microsoft.Billing/billingAccounts?api-version=2024-04-01" 2>/dev/null \ > | jq -r '.value[]?.name' > "$D/visible" || true > > BODY="{\"type\":\"ActualCost\",\"timeframe\":\"$WINDOW\",\"dataset\":{\"granularity\":\"None\",\"aggregation\":{\"totalCost\":{\"name\":\"Cost\",\"function\":\"Sum\"}}}}" > > az account list --all --query "[?state=='Enabled'].{i:id,n:name}" -o tsv | while IFS=$'\t' read -r SUBID SUBNM; do > BP=$(az rest --method get \ > --url "https://management.azure.com/subscriptions/$SUBID/providers/Microsoft.Billing/billingProperty/default?api-version=2024-04-01" 2>/dev/null) > AG=$(echo "$BP" | jq -r '.properties.billingAccountAgreementType // ""') > BA=$(echo "$BP" | jq -r '.properties.billingAccountDisplayName // "NO BILLING ACCESS"') > BAID=$(echo "$BP" | jq -r '.properties.billingAccountId // ""') > PROFID=$(echo "$BP" | jq -r '.properties.billingProfileId // ""') > PROFD=$(echo "$BP" | jq -r '.properties.billingProfileDisplayName // "-"') > PROFNM=$(printf '%s' "$PROFID" | sed -n 's#.*/billingProfiles/\([^/]*\).*#\1#p'); [ -z "$PROFNM" ] && PROFNM="-" > > REL=""; IND="" > if [ "$AG" = "MicrosoftCustomerAgreement" ] && [ -n "$PROFID" ]; then > # portable per-profile cache key (no md5sum: missing on stock macOS) > CK="$D/pc/$(printf '%s' "$PROFID" | tr -c 'A-Za-z0-9' '_')" > [ -f "$CK" ] || az rest --method get --url "https://management.azure.com${PROFID}?api-version=2024-04-01" 2>/dev/null \ > | jq -r '[(.properties.billingRelationshipType // ""),(.properties.indirectRelationshipInfo.displayName // "")]|@tsv' > "$CK" 2>/dev/null > [ -s "$CK" ] && IFS=$'\t' read -r REL IND < "$CK" > fi > > case "$AG" in > EnterpriseAgreement) TYPE="EA"; VR="OK";; > MicrosoftPartnerAgreement) TYPE="CSP"; VR="NO";; > MicrosoftCustomerAgreement) > if [ -n "$IND" ] || { [ -n "$REL" ] && [ "$REL" != "Direct" ]; }; then TYPE="Reseller"; VR="CHK"; > elif [ "$REL" = "Direct" ]; then TYPE="MCA"; VR="OK"; > else TYPE="MCA"; VR="CHK"; fi;; # REL unconfirmed: could be indirect/reseller -> review, not auto-pass > MicrosoftOnlineServicesProgram) TYPE="PAYG"; VR="CHK";; > "") TYPE="?"; VR="CHK";; > *) TYPE="$AG"; VR="CHK";; > esac > [ "$AG" = "MicrosoftCustomerAgreement" ] && [ "$TYPE" = "MCA" ] && [ -z "$REL" ] && IND="(direct/reseller unconfirmed)" > > ACCTSEG=$(printf '%s' "$BAID" | sed -n 's#.*/billingAccounts/\([^/]*\).*#\1#p') > VIS="vis"; [ -n "$ACCTSEG" ] && ! grep -qxF "$ACCTSEG" "$D/visible" 2>/dev/null && VIS="hidden" > > if [ "$SKIP_COST" = 0 ]; then > Q=$(az rest --method post \ > --url "https://management.azure.com/subscriptions/$SUBID/providers/Microsoft.CostManagement/query?api-version=2025-03-01" \ > --headers "Content-Type=application/json" --body "$BODY" 2>/dev/null) > # empty COST = "couldn't read cost" (no access / API error), distinct from a real 0.00 > if [ $? -ne 0 ] || [ -z "$Q" ] || printf '%s' "$Q" | jq -e '.error' >/dev/null 2>&1; then > COST=""; CUR="n/a" > else > COST=$(echo "$Q" | jq -r '(.properties.columns//[]) as $c|([ $c|to_entries[]|select(.value.name=="Cost" or .value.name=="PreTaxCost")|.key ]|first // 0) as $i|(.properties.rows[0][$i] // 0)' 2>/dev/null) > CUR=$(echo "$Q" | jq -r '(.properties.columns//[]) as $c|([ $c|to_entries[]|select(.value.name=="Currency")|.key ]|first) as $i|(if $i!=null then (.properties.rows[0][$i] // "-") else "-" end)' 2>/dev/null) > [ -z "$COST" ] && { COST=""; CUR="n/a"; } > fi > else COST=""; CUR="-"; fi > > printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" \ > "$BA" "$BAID" "$TYPE" "$VR" "$PROFD" "$PROFNM" "$SUBNM" "$COST" "$CUR" "$IND" "$VIS" >> "$D/rows" > done > > read -r OKA CHKA NOA <<<"$(awk -F'\t' '!s[$2]++{if($4=="OK")o++;else if($4=="NO")n++;else c++}END{print o+0,c+0,n+0}' "$D/rows")" > if [ "$OKA" -gt 0 ] && [ "$NOA" = 0 ] && [ "$CHKA" = 0 ]; then H="PASS — onboardable"; > elif [ "$OKA" -gt 0 ]; then H="PARTIAL — some accounts onboardable, review the rest"; > elif [ "$NOA" -gt 0 ] && [ "$OKA" = 0 ] && [ "$CHKA" = 0 ]; then H="FAIL — CSP/partner-billed, not supported"; > else H="REVIEW — couldn't confirm billing control"; fi > echo; echo "VERDICT: $H" > echo " by billing account: OK $OKA onboardable CHK $CHKA review CSP/other $NOA unsupported" > echo > > LC_ALL=C sort -t$'\t' -k2,2 -k6,6 -k8,8rn "$D/rows" | awk -F'\t' ' > function cf(x, s,n,ip,d,sg,r,i,c){ s=sprintf("%.2f",x+0); n=index(s,"."); ip=substr(s,1,n-1); d=substr(s,n); > if(substr(ip,1,1)=="-"){sg="-";ip=substr(ip,2)} r="";c=0; for(i=length(ip);i>=1;i--){r=substr(ip,i,1) r;c++; if(c%3==0&&i>1)r="," r} return sg r d } > function spend(seen,v,cur){ return (seen?cf(v):"n/a") (cur!=""?" " cur:"") } > BEGIN{ S="\001"; ca=S; cp=S } > { > if($2!=ca){ > if(ca!=S){ printf " profile spend: %s\n",spend(pseen,ps,pcur) > printf " ACCOUNT SPEND: %s\n\n",spend(aseen,as,acur) } > v=($4=="OK")?"✓ onboard":(($4=="NO")?"✗ not supported":"⚠ review") > f=""; if($11=="hidden") f=f" (billing acct not visible to you)" > if($3=="Reseller" && $10!="") f=f" via "$10 > if($3=="MCA" && $10!="") f=f" "$10 > idf=$2; sub(/^.*\/billingAccounts\//,"",idf); if(idf=="") idf="(no access)" > printf "BILLING ACCOUNT: %s [%s] %s%s\n id: %s\n",$1,$3,v,f,idf > ca=$2; as=0; acur=""; aseen=0; cp=S > } > if($6!=cp){ if(cp!=S) printf " profile spend: %s\n",spend(pseen,ps,pcur) > printf " profile: %s\n",($6=="-"?$5:$6); cp=$6; ps=0; pcur=""; pseen=0 } > printf " %-40s %14s %s\n",substr($7,1,40),($8==""?"n/a":cf($8)),($8==""?"":($9=="-"?"":$9)) > if($8!=""){ ps+=$8; as+=$8; pseen=1; aseen=1; > if($9!="-"&&$9!="n/a"){ if(pcur!=""&&pcur!=$9)pcur="MIXED"; else if(pcur!="MIXED")pcur=$9; > if(acur!=""&&acur!=$9)acur="MIXED"; else if(acur!="MIXED")acur=$9 } } > } > END{ if(ca!=S){ printf " profile spend: %s\n",spend(pseen,ps,pcur); printf " ACCOUNT SPEND: %s\n",spend(aseen,as,acur) } }' > > if [ -n "$CSV" ]; then > { echo "billing_account,billing_account_id,type,verdict,profile,profile_id,subscription,cost,currency,partner_or_note,visibility" > LC_ALL=C sort "$D/rows" | awk -F'\t' 'BEGIN{OFS=","}{for(i=1;i<=NF;i++){gsub(/"/,"\"\"",$i); if($i~/[",]/)$i="\""$i"\""} print}' > } > "$CSV"; echo; echo "CSV written to $CSV" > fi > ``` **Reading the verdict** | Verdict | What it means | | - | - | | **PASS** | Every billing account is EA or direct MCA. You are good to proceed. | | **PARTIAL** | Some accounts are onboardable; others need a closer look (reseller-billed MCA, or billing you cannot read). | | **FAIL** | Only CSP / partner-billed accounts were found. Not supported. | | **REVIEW** | Could not confirm billing control (often missing billing access). Re-run as a billing admin, or send the output to your nOps contact. | Each billing account is also flagged **✓ onboard**, **✗ not supported**, or **⚠ review** in the output. If you are working with an nOps contact, you can share the output (or the CSV written by `--csv results.csv`) so they can confirm your billing scope. The easiest way is to copy everything the script printed, top to bottom, and paste it into your reply. Prefer not to run a script? You can check in the Azure Portal instead (below). ### How to Check for CSP Subscriptions The easiest way to verify you don't have CSP subscriptions is through the Azure Marketplace eligibility checker: **1. Go to Private Offer Management** Navigate to [**Azure Portal → Marketplace → Private Offers Center**](https://portal.azure.com/#view/Microsoft_Azure_Marketplace/PrivateOffersCenter.ReactView) **2. Click Check Eligibility** Click the **Check Eligibility** button on the right-hand side **3. Review the Results** Look for the eligibility check results. You should see: * ✅ **Green checkmark**: "No Cloud Solution Provider (CSP) subscription found." **You can use nOps** * ❌ **Red X**: "Cloud Solution Provider (CSP) subscription found." **You cannot use nOps** > [!NOTE] > > If you find that you have CSP subscriptions, please contact your CSP reseller/partner for cost optimization solutions. You may need to migrate to a direct EA or MCA agreement with Microsoft if you want to use nOps in the future. *** ## 3. Finding Your Management Group ID During setup, you give nOps the **Reader** role on a management group. This gives nOps visibility across all subscriptions in that group. 1. Go to [**Management Groups**](https://portal.azure.com/#view/Microsoft_Azure_ManagementGroups/ManagementGroupBrowseBlade) in the Azure Portal. 2. If you want nOps to see **all subscriptions**, use the **Tenant Root Group** -- its ID matches your **Tenant ID**. In the nOps wizard, the **Use tenant root** button fills it in for you. 3. If you want to limit nOps to a subset of subscriptions, find the appropriate management group and note its **ID**. > [!TIP] > > If your organization does not use management groups, you can use your **Tenant ID** as the Management Group ID. This is equivalent to the root management group and covers all subscriptions. *** ## 4. Preparing a Subscription for FOCUS Exports You will need an Azure subscription to hold the storage account for the FOCUS cost export. Choose the subscription with the most spend. > [!NOTE] > > During setup, you create a resource group and a storage account in this subscription. The FOCUS export itself lives at your billing scope (billing account, enrollment, or billing profile) and writes its files to that storage account. nOps doesn't create these resources. They cost only storage for the export files. ### Required Resource Providers #### For FOCUS Exports (on the export subscription) These must be registered on the subscription where the storage account will be created: | Resource Provider | Purpose | | - | - | | `Microsoft.Storage` | Storage account for FOCUS export data | | `Microsoft.CostManagement` | Cost queries and management | | `Microsoft.CostManagementExports` | FOCUS export creation and scheduling | **Portal** 1. Go to [**Subscriptions**](https://portal.azure.com/#view/Microsoft_Azure_Billing/SubscriptionsBlade) > select your export subscription > **Settings** > **Resource providers** 2. Search for each provider above and click **Register** 3. Wait for all three to show **Registered** (1-2 minutes) **CLI** Run in [Azure Cloud Shell](https://shell.azure.com): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} az provider register --namespace Microsoft.Storage --subscription "" && \ az provider register --namespace Microsoft.CostManagement --subscription "" && \ az provider register --namespace Microsoft.CostManagementExports --subscription "" ``` > [!NOTE] > > Most subscriptions already have `Microsoft.Storage` and `Microsoft.CostManagement` registered. `Microsoft.CostManagementExports` is the one most likely to require manual registration, especially on newer subscriptions. ### Storage Account Network Access The nOps data ingestion service reads the exported cost data from outside Azure. If your organization enforces storage account firewalls via Azure Policy, allow the nOps IP addresses (`44.246.45.84`, `52.11.53.164`, and `52.39.155.200`) on the storage account after creation, and check **"Allow Azure services on the trusted services list"**. *** ## 5. Understanding RBAC Roles for nOps nOps requires specific Azure RBAC roles to operate. These roles are assigned at different scopes depending on the integration tier. ### Savings Analysis Roles (Read-Only) | Scope | Role | Role Definition ID | Purpose | | - | - | - | - | | Management Group | Reader | `acdd72a7-3385-48ef-bd42-f606fba81ae7` | View all subscriptions and their resources | | Storage Account (FOCUS export) | Storage Blob Data Owner | `b7e6dc6d-f1e8-4753-8033-0f276bb0955b` | Read FOCUS export files from the storage account (data plane) | These two roles, plus one billing role below, are the complete list for Savings Analysis. > [!NOTE] > > The **Storage Blob Data Owner** role is granted only on the storage account you create for the FOCUS export (`nopsfocus`) -- it does not grant access to any other resources in your environment. Savings Analysis does **not** need the Azure RBAC **Owner** role on the storage account. Owner is a management-plane role and cannot read blob data, so it does not replace Storage Blob Data Owner. ### Billing Access Roles Savings Analysis uses one of these billing roles: | Billing Account Type | Role Assigned | Role Definition ID | Scope | Who Can Assign It | | - | - | - | - | - | | Microsoft Customer Agreement (MCA), billing account (default) | Billing account reader | `50000000-aaaa-bbbb-cccc-100000000002` | Billing account | Billing account owner (Azure Portal) | | Microsoft Customer Agreement (MCA), billing profiles option | Billing profile reader | `40000000-aaaa-bbbb-cccc-100000000002` | Each selected billing profile | Billing profile owner of each profile (Azure Portal) | | Enterprise Agreement (EA) | EnrollmentReader | `24f8edb6-1668-4659-b5e2-40bb5f3a7d7e` | Billing account (enrollment) | Enterprise Administrator (REST API only) | ### Commitment Management Roles (Additional) Commitment Management adds one Azure Lighthouse delegation on each purchase subscription and nothing else. It gives the nOps Customer Access Operators group (nOps tenant) these roles: | Scope | Role | Role Definition ID | Purpose | | - | - | - | - | | Purchase subscription (each) | Reader | `acdd72a7-3385-48ef-bd42-f606fba81ae7` | See the subscription under My customers | | Purchase subscription (each) | Reservation Purchaser | `f7b75c60-3036-4b75-91c3-6b41c27c1689` | Buy reservations billed to this subscription | | Purchase subscription (each) | Savings plan Purchaser | `3d24a3a0-c154-4f6f-a5ed-adc8e01ddb74` | Buy savings plans billed to this subscription | Commitment Management doesn't need roles for nOps.io, tenant-scope roles, a billing write role (EA Purchaser or Billing account or profile contributor), Owner on the storage account, Cost Management Contributor, or Monitoring Reader. *** ## 6. Purchase Policies (Commitment Management Only) Microsoft lets subscription purchasers buy commitments only when the enrollment or billing profile allows it. Without these policies, only billing administrators can buy, and nOps can't. | Billing Account Type | Policy Location | Setting | | - | - | - | | Enterprise Agreement (EA) | EA billing account > Policies | **Reserved Instances** and **Add Savings Plan** must be **On** | | Microsoft Customer Agreement (MCA) | Billing profile > Policies | **Azure Reservation purchases** and **Azure Savings Plan** must be **Yes** | > [!NOTE] > > For MCA, only the billing profiles you buy for need these policies. You don't need to change other billing profiles. *** ## Next Steps Once you have your Management Group ID, know your billing account type, have a subscription ready for FOCUS exports, and know who on your team holds each required role, you are ready to connect Azure to nOps. > [!TIP] > > **Ready to connect?** Go to [nOps Settings > Cloud Provider Integrations](https://clara.nops.io/settings) and click the **Microsoft Azure** card to start the integration wizard. nOps offers two onboarding tiers. Start with Savings Analysis, then upgrade to Commitment Management when ready: > **[Savings Analysis Setup](/azure/integration-setup)** > > Read-only cost visibility, resource inventory, optimization recommendations, and daily FOCUS cost exports. > **[Commitment Management Setup](/azure/commitment-management-setup)** > > Automated purchasing and management of Azure Reservations and Savings Plans. Requires Savings Analysis first. # Microsoft Azure - Security Source: https://help.nops.io/azure/security Security architecture, API usage, RBAC requirements, and resource footprint for the nOps Azure integration. ## Security & API Access Overview Prepared for customer security assessment. ## Integration Summary | Auth Model | Write Access to Resources | Supported Agreements | Data Scope | | - | - | - | - | | nOps.io enterprise application (admin consent) | Savings Analysis: only blob data in the FOCUS export storage account (Storage Blob Data Owner). No write access anywhere else. Commitment Management adds: the nOps Customer Access Operators group, through the Lighthouse delegation, can buy reservations and savings plans billed to the purchase subscriptions you choose | EA and MCA (No CSP) | FOCUS cost exports, subscription list, billing account structure | ## 1. Purpose of This Document This document is provided to support your organisation's security assessment of the nOps Azure integration. It lists the Azure API calls nOps makes, the exact RBAC permissions required, the resources in your environment, and what nOps does not access. nOps offers two integration tiers: * Savings Analysis: Read-only cost visibility, resource inventory, and optimisation recommendations. * Commitment Management: Automated purchasing and lifecycle management of Azure Reservations and Savings Plans. This tier builds on Savings Analysis and adds one Azure Lighthouse delegation on each purchase subscription. It gives nOps staff Reader, Reservation Purchaser, and Savings plan Purchaser there. > [!NOTE] > > **Supported Agreement Types** > > nOps supports Enterprise Agreement (EA) and Microsoft Customer Agreement (MCA) only. Cloud > Solution Provider (CSP) subscriptions are not supported. ## 2. Authentication Model nOps uses a multi-tenant app called **nOps.io**. Its app registration lives in nOps's own tenant. During onboarding, a Global Administrator or Privileged Role Administrator grants admin consent through Microsoft's standard admin-consent flow. This adds the nOps.io **enterprise application** (a service principal) to your Microsoft Entra ID tenant. No app registration is created in your tenant, and nOps never stores your credentials. ### 2.1 What the Consent Screen Shows Microsoft's consent screen shows the app **nOps.io** from publisher **nOps Inc** (verified publisher) and lists exactly these permissions: | Permission | Description shown by Microsoft | | - | - | | Access Azure Resource Manager as organization users | Allows the application to access Azure Resource Manager acting as users in the organization | | Read directory data | Allows the app to read data in your organization's directory, such as users, groups and apps | | Sign in and read user profile | Allows users to sign-in to the app, and allows the app to read the profile of signed-in users. It also allows the app to read basic company information of signed-in users | The screen also says that if you accept, the app gets access to the specified resources for all users in your organisation, and no one else will be prompted to review these permissions. ### 2.2 What Consent Does and Does Not Do * Consent adds the nOps.io enterprise application to your tenant and approves the permissions above for your whole organisation, so no one else is prompted. * Consent by itself gives nOps **no access** to your subscriptions, billing, or storage. nOps only gets Azure access from the roles you assign during setup (Section 4). * nOps never signs in as your users. The consent callback only receives your tenant ID and whether consent was granted. * nOps connects using the app's own identity: app-only tokens from Microsoft Entra ID, with only the roles you assign. * For the Azure integration, nOps does not call Microsoft Graph. | Item | Detail | | - | - | | Identity in your tenant | nOps.io enterprise application (service principal), added by admin consent | | Credential Type | App-only tokens for the nOps.io multi-tenant app | | Token Endpoint | `https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token` | | OAuth Scopes | `https://management.azure.com/.default` (Azure Resource Manager) and `https://storage.azure.com/.default` (reading the export files) | | Token Lifetime | 1 hour (auto-refreshed) | | Revocation | Delete or disable the nOps.io enterprise application in Microsoft Entra ID → Enterprise applications, and/or remove the role assignments. Access stops once those are gone | ## 3. Azure APIs Called The following tables list the API endpoints nOps calls, grouped by service area. Apart from getting a token (#1) and the optional backfill run (#10), every Savings Analysis call is a read. Calls use the base URL [https://management.azure.com](https://management.azure.com) unless a full URL is shown. ### 3.1 Sign-In, Subscriptions & Role Assignments | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 1 | POST | `https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token` | -- | Get an app-only token from Microsoft Entra ID | SA | | 2 | GET | `/subscriptions` | 2016-06-01 | List the subscriptions nOps can access (confirms Reader) | SA | | 2a | GET | `/providers/Microsoft.Management/managementGroups/{id}/descendants` | 2020-05-01 | List the subscriptions in the management group you connected, so nOps only uses those | SA | | 3 | GET | `/subscriptions/{id}/providers/Microsoft.ManagedServices/registrationAssignments?$expandRegistrationDefinition=true` | 2022-10-01 | Confirm the nOps Commitment Management delegation on a purchase subscription (Commitment Management Verify, see 3.4) | CM | ### 3.2 Billing Account Discovery Used to find your billing account structure. All calls are reads. | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 4 | GET | `/providers/Microsoft.Billing/billingAccounts` | 2024-04-01 | Find your EA or MCA billing account | SA | | 5 | GET | `/providers/Microsoft.Billing/billingAccounts/{id}` | 2024-04-01 | Check your EA enrollment | SA (EA) | | 6 | GET | `/providers/Microsoft.Billing/billingAccounts/{id}/billingProfiles` | 2024-04-01 | List billing profiles. Commitment Management also uses it to give each billing profile a purchase subscription row and to report the ones nOps can't buy for | SA, CM (MCA) | | 7 | GET | `/providers/Microsoft.Billing/billingAccounts/{id}/billingProfiles/{profileId}` | 2024-04-01 | Check each selected billing profile (billing profiles option) | SA (MCA) | > [!NOTE] > > **nOps does not assign billing roles.** For EA, you assign EnrollmentReader yourself by > running a script in Azure Cloud Shell (a PUT to > `/providers/Microsoft.Billing/billingAccounts/{id}/billingRoleAssignments/{guid}`), > because Microsoft only supports assigning EA billing roles to a service principal through > the REST API. For MCA, you assign the billing role in the Azure portal. ### 3.3 FOCUS Export & Export Files nOps does not create the FOCUS export or change its settings. You create it during setup. nOps reads its settings, its run history, and the files it writes. If you ask nOps to backfill history, nOps also starts a one-off run of the export for each past month. | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 8 | GET | `{billingScope}/providers/Microsoft.CostManagement/exports` | 2023-07-01-preview | Find the FOCUS export at your billing scope | SA | | 9 | GET | `{billingScope}/providers/Microsoft.CostManagement/exports/{name}/runHistory` | 2023-07-01-preview | Check that the export runs | SA | | 10 | POST | `{billingScope}/providers/Microsoft.CostManagement/exports/{name}/run` | 2023-07-01-preview | Run the export for a past month (only when you ask nOps to backfill history) | SA | | 11 | GET | `https://{storageAccount}.blob.core.windows.net/focus-exports?restype=container&comp=list` | -- | List the export container (confirms Storage Blob Data Owner) | SA | | 12 | GET | `https://{storageAccount}.blob.core.windows.net/focus-exports/{blobPath}` | -- | Read the export files (data plane) | SA | > [!NOTE] > > **FOCUS Export Data Flow** > > The FOCUS export you create writes daily Parquet files to *focus-exports/nops-clara* > inside the dedicated storage account. The nOps data ingestion service reads these files from outside Azure using static IPs *44.246.45.84*, *52.11.53.164*, and *52.39.155.200*. If you enforce storage firewalls, only these three IPs need to be whitelisted, with "Allow Azure services on the trusted services list" enabled. ### 3.4 Commitment Management Checks During Verify For Commitment Management, Verify reads the Lighthouse delegations on each purchase subscription (#3), the billing profile list (#6, MCA billing account), and the two calls below. All of them are reads, made by nOps.io with the Reader and billing reader roles from Savings Analysis. | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 13 | GET | `/providers/Microsoft.Billing/billingAccounts/{id}/billingSubscriptions/{subscriptionId}` | 2024-04-01 | Find which billing profile a purchase subscription bills to (Verify, and the setup wizard placing a saved subscription in its profile's row) | CM (MCA) | | 14 | GET | `{enrollment or billing profile}/policies/default` | 2024-04-01 | Read the purchase policies (EA: Reserved Instances, Add Savings Plan; MCA: Azure Reservation purchases, Azure Savings Plan) | CM | > [!NOTE] > > Savings Analysis Verify doesn't make these calls, and doesn't check for a Lighthouse delegation. > nOps doesn't call `listKeys` on the export storage account in either tier. ### 3.5 Reservations API (Commitment Management Only) nOps staff buy in the Azure portal through the Lighthouse delegation, signed in to the nOps tenant, so the portal makes these calls for them. The PUT purchase call (#17) creates a new reservation billed to a purchase subscription. The order is created in the nOps tenant, owned by the staff member who bought it; nOps adds its operations team as a co-owner of every order. No existing resources are modified or deleted. | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 15 | GET | `/providers/Microsoft.Capacity/reservationOrders` | 2022-11-01 | List the reservation orders nOps can see | CM | | 16 | GET | `/providers/Microsoft.Capacity/reservationOrders/{id}/reservations` | 2022-11-01 | List reservations within an order | CM | | 17 | PUT | `/providers/Microsoft.Capacity/reservationOrders/{id}` | 2022-11-01 | Purchase a new Reservation | CM Only | ### 3.6 Savings Plans API (Commitment Management Only) As with reservations, the Azure portal makes these calls when nOps staff buy. The PUT purchase call (#19) creates a new savings plan billed to a purchase subscription (`billingScopeId` is `/subscriptions/{id}`), in the nOps tenant. No existing resources are modified or deleted. | # | Method | Endpoint | API Version | Purpose | Tier | | - | - | - | - | - | - | | 18 | GET | `/providers/Microsoft.BillingBenefits/savingsPlans` | 2022-11-01 | List the savings plans nOps can see | CM | | 19 | PUT | `/providers/Microsoft.BillingBenefits/savingsPlanOrders/{id}` | 2022-11-01 | Purchase a new Savings Plan | CM Only | ### 3.7 APIs nOps Does Not Call * Azure Advisor (`Microsoft.Advisor`) recommendations * Creating Cost Management exports or changing their settings (you create the FOCUS export yourself) * Assigning billing roles (for EA, you run the EnrollmentReader assignment yourself) * Microsoft Graph ## 4. Required RBAC Permissions (Savings Analysis) The following roles are assigned during the Savings Analysis onboarding process. This is the complete list. The role at the Management Group scope cascades to all subscriptions underneath. The storage-account role is scoped only to the single dedicated nopsfocus storage account. ### 4.1 Management Group Scope | Role | Role Definition ID | Purpose | | - | - | - | | Reader | acdd72a7-3385-48ef-bd42-f606fba81ae7 | List and view subscriptions and their resources | ### 4.2 Storage Account Scope (Dedicated Only) | Role | Role Definition ID | Purpose | | - | - | - | | Storage Blob Data Owner | b7e6dc6d-f1e8-4753-8033-0f276bb0955b | Read exported cost data blobs (data plane) | > [!WARNING] > > **Important: Storage Blob Data Owner scope is strictly limited** > > The Storage Blob Data Owner role is granted only on the `nopsfocus` > storage account that you create for the FOCUS export. It does not grant access to any other storage > account or resource in your environment. Savings Analysis does not require the Azure RBAC Owner role > on this storage account. Owner is a management-plane role with no blob data permissions, so it cannot > replace Storage Blob Data Owner. ### 4.3 Billing Scope You assign one of these, depending on your billing account type and how you connect it. | Billing Account Type | Role | Role Definition ID | Scope | Purpose | | - | - | - | - | - | | Microsoft Customer Agreement (MCA), billing account (default) | Billing account reader | 50000000-aaaa-bbbb-cccc-100000000002 | Billing account | Find the billing account and billing profiles; check that the FOCUS export exists and runs | | Microsoft Customer Agreement (MCA), billing profiles option | Billing profile reader | 40000000-aaaa-bbbb-cccc-100000000002 | Each selected billing profile | Check each billing profile and its FOCUS export | | Enterprise Agreement (EA) | EnrollmentReader | 24f8edb6-1668-4659-b5e2-40bb5f3a7d7e | Enrollment (billing account) | Find the enrollment; check that the FOCUS export exists and runs | > [!NOTE] > > **Not assigned for Savings Analysis:** Cost Management Contributor, Monitoring Reader, > Reservations Reader, Savings Plan Reader, Owner on the storage account, any Azure Lighthouse > delegation, and any Azure Policy assignment. ## 5. Additional Permissions (Commitment Management) Commitment Management is an optional tier that lets nOps buy and manage Reservations and Savings Plans for you. It adds one Azure Lighthouse delegation, "nOps Commitment Management", on each purchase subscription (the subscription a purchase is billed to). nOps staff use it from the nOps tenant (`9a93f7e1-76f9-4a8d-a15e-5eeb73cf1d18`) to buy in the Azure portal. Nothing is assigned to nOps.io for Commitment Management. ### 5.1 Purchase Subscription Scope The delegation gives the nOps Customer Access Operators group these built-in roles: | Role | Role Definition ID | Purpose | | - | - | - | | Reader | acdd72a7-3385-48ef-bd42-f606fba81ae7 | See the subscription under My customers | | Reservation Purchaser | f7b75c60-3036-4b75-91c3-6b41c27c1689 | Buy reservations billed to this subscription | | Savings plan Purchaser | 3d24a3a0-c154-4f6f-a5ed-adc8e01ddb74 | Buy savings plans billed to this subscription | EA uses one purchase subscription in the enrollment. MCA uses one in each billing profile nOps buys for, because shared commitments apply per billing profile. Any subscription works; an empty one keeps purchasing apart from your workloads. Lighthouse can't delegate Owner, roles that read data, or permission to assign roles, so none of these can. > [!NOTE] > > **Where purchases live.** Azure creates a commitment in the tenant of whoever buys it, so the > reservations and savings plans nOps staff buy live in the nOps tenant and are owned by the > buyer. You pay for them through your purchase subscription, they apply to your resources, and > you see them in Cost Management + Billing. Microsoft documents that reservations don't support > roles assigned through Lighthouse; purchases work, but Microsoft treats this path as unsupported. > If you stop using nOps, nOps moves your reservations to your tenant. Savings plans can't change > tenant after purchase. > [!NOTE] > > **Not assigned for Commitment Management:** no roles for nOps.io, no tenant-scope roles > (Reservations Administrator, Reservations Contributor, Savings Plan Reader or Contributor), no > billing write roles (EA Purchaser, Billing account or profile contributor), no Cost Management > Contributor or Monitoring Reader, and no Owner on the storage account. ## 6. Resources in Your Environment nOps does not deploy resources into your environment. Admin consent adds the nOps.io enterprise application, and you create everything else yourself during setup. ### 6.1 nOps.io Enterprise Application Admin consent adds the nOps.io enterprise application (a service principal) to your Microsoft Entra ID tenant. This is the identity used for all API access described in this document. It is not an App Registration: the nOps app registration lives in nOps's own tenant. ### 6.2 FOCUS Export Resources (Created by You) You create these in the Azure portal during Savings Analysis setup. nOps does not create them. | Resource Type | Name | Location | Purpose | | - | - | - | - | | Resource Group | nops-focus-exports-rg | Export subscription, region of your choice | Container for the export storage account | | Storage Account | `nopsfocus` | Region of your choice | Storage destination for FOCUS cost export data | | Blob Container | focus-exports | In the storage account | Holds the export files | | FOCUS Cost Export | Prefix nops-clara | Your billing account (MCA), enrollment (EA), or each billing profile | Daily export of FOCUS-format cost data | > [!NOTE] > > These resources incur minimal cost: only standard Azure Blob Storage fees for the exported > cost data. ### 6.3 Required Resource Providers | Scope | Resource Provider | Purpose | | - | - | - | | FOCUS Export Subscription | Microsoft.Storage | Storage account for FOCUS export data | | FOCUS Export Subscription | Microsoft.CostManagement | Cost queries and management | | FOCUS Export Subscription | Microsoft.CostManagementExports | FOCUS export creation and scheduling | ## 7. What nOps Does Not Access The following are out of scope for the nOps Savings Analysis integration. nOps does not call the APIs for these items. Where noted, the Savings Analysis roles in Section 4 also block access. | Items | Details | | - | - | | VM state, disk contents, application configs, or deployment details | Not Accessed | | Key Vault secrets, certificates, or keys | Not Accessed. Reader cannot read them | | Data in any storage account other than the dedicated nopsfocus export account | Not Accessed. nOps has no data role on other storage accounts | | Microsoft Entra ID users or groups | Not Accessed. nOps does not call Microsoft Graph | | Network topology, NSG rules, or firewall configurations | Not Accessed | | Security Center / Microsoft Defender alerts or findings | Not Accessed | | Log Analytics workspaces or diagnostic logs | Not Accessed | | Any delete or modify operation on existing Azure resources | Not Performed | | The ability to change subscription ownership or modify RBAC assignments after setup | Not possible with the Savings Analysis roles | | Invoices or payment instruments | Not Accessed | ## 8. Network Requirements If your organisation enforces firewalls on storage accounts, the following nOps IP addresses must be whitelisted on the FOCUS export storage account. Additionally, ensure Allow Azure services on the trusted services list is enabled on the storage account firewall. If your storage account allows public network access (the default), no firewall configuration is needed. | IP Address | Purpose | | - | - | | 44.246.45.84 | nOps data processing | | 52.11.53.164 | nOps data processing | | 52.39.155.200 | nOps data processing | ## 9. Billing Policy Requirements The following billing policies apply only to Commitment Management. Savings Analysis has no billing policy dependencies. | Agreement Type | Policy Location | Setting | Required Value | | - | - | - | - | | Enterprise Agreement (EA) | EA billing account > Policies | Reserved Instances | On | | Enterprise Agreement (EA) | EA billing account > Policies | Add Savings Plan | On | | Microsoft Customer Agreement (MCA) | Billing profile > Policies | Azure Reservation purchases | Yes | | Microsoft Customer Agreement (MCA) | Billing profile > Policies | Azure Savings Plan | Yes | ## 10. Security Summary The table below summarises the key security properties of the nOps Azure integration for Savings Analysis. | Property | Detail | | - | - | | Authentication | nOps.io enterprise application (service principal), added to your tenant by admin consent. nOps uses app-only tokens, never signs in as your users, and never stores your credentials. | | Write access to customer resources | Savings Analysis: none, except blob data in the FOCUS export storage account, which Storage Blob Data Owner allows. Commitment Management: nOps staff, through the Lighthouse delegation, can buy reservations and savings plans billed to the purchase subscriptions you choose. | | Storage account access | Storage Blob Data Owner, scoped only to the `nopsfocus` storage account you create for the FOCUS export | | Data accessed | FOCUS cost export files, the list of subscriptions, billing account and billing profile details, and FOCUS export settings and run history. Commitment Management Verify also reads the Lighthouse delegations on the purchase subscriptions and the purchase policies | | Data not accessed | VM config, secrets, application data, Entra ID users and groups, network config, security alerts | | Access revocation | Delete or disable the nOps.io enterprise application in Microsoft Entra ID → Enterprise applications, and/or remove the role assignments. For Commitment Management, remove the nOps Commitment Management delegation under Service providers. Access stops once those are gone | | Lighthouse | Commitment Management: one delegation on each purchase subscription to the nOps Customer Access Operators group (section 5). Savings Analysis: not used. | | CSP support | Not supported: EA and MCA only | > [!NOTE] > > For security questions, contact your nOps account team. # Canvas Source: https://help.nops.io/clara/canvas Canvas is the visual workspace at the heart of nOps. Build interactive dashboards with drag-and-drop widgets, AI-generated visualizations, and real-time cloud cost data. ## Overview A **canvas** is a flexible, drag-and-drop workspace where you combine data sources, charts, AI chat sessions, and freeform notes into a single view. Canvases auto-save as you work and support version history so you can always roll back to a previous state. > [!TIP] > > The fastest way to get started is to create a canvas from one of the **Global Templates**. These are pre-built layouts designed by the nOps team that give you a ready-to-use dashboard in seconds. Prefer to talk first? Try the [Ask Clara](/clara/clara-chat) page, then jump into a canvas when you are ready. *** ## Getting started with Global Templates Global Templates are pre-configured canvas layouts built by the nOps team. They come loaded with the right data sources, chart types, and filters for common cost optimization workflows -- so you can start analyzing costs immediately instead of building from scratch. **1. Create a new canvas** From the [Canvas](https://clara.nops.io/canvas) page, click **Create**. Give your canvas a **name** and choose a **scope** (Private or Shared). **2. Choose Load Template** In the creation dialog, select **Load template** to browse the available templates. **3. Pick a Global Template** Filter by **Global** scope to see the templates provided by nOps. Browse or search for the one that fits your use case, then click to apply it. **4. Start exploring** Your canvas is pre-populated with widgets, data sources, and configurations from the template. You can immediately interact with the data, apply filters, and customize the layout to fit your needs. You can also start from scratch or follow the onboarding walkthrough: * **Start fresh:** open an empty canvas and build from the ground up. * **Start walkthrough:** launch a guided tour that introduces the canvas controls step by step. *** ## Canvas layout The canvas is a full-page workspace built around an infinite, pannable grid. The key UI areas are: | Location | Elements | | - | - | | **Top-right** | Presence avatars, Clara button (Cmd+J), Version History, Share Reports (mail icon with pending badge) | | **Bottom-left** | Command palette (gear icon), Pan / Selection toggle | | **Bottom-center** | Palette **(+)** button | | **Bottom-right** | Save indicator (idle / saving / saved / error) | | **Minimap** | Pannable overview of the full canvas, shown inside the viewport | *** ## Adding widgets (Palette) The **(+)** button at bottom-center opens the Palette popover. It has two tabs: ### Tools tab Draggable tool pills you can drop onto the canvas: * **Scratch Pad:** freeform notes * **Text Box:** rich text labels and callouts * **Global Filters:** shared date and dimension filters that drive data source widgets * **Nexus:** commitment management (visible only on accounts with the Nexus tool enabled) ### Data Sources tab * **Search:** filter the list by name. * **Provider filter:** narrow by cloud provider: All, AWS, GCP, or Azure. Data sources for providers your organization has not onboarded are grayed out. * **Draggable cards:** drag any data source onto the canvas to create a widget. * **Refresh:** reload the data source list. * **+ New:** create a new data source (only available on accounts with elevated data source access). Widgets snap to the grid automatically when dropped. *** ## Widget reference > **Data source** > > Connect to a cloud cost data source and visualize it with any of the 19 supported chart types. Configure dimensions, measures, filters, and save the configuration as a reusable preset. > **AI chart** > > A Clara-generated chart or table. Can be created standalone by Clara or linked to a parent data source widget for AI-driven analysis. > **Scratch Pad** > > A simple notepad for freeform notes, checklists, or observations while you work. > **Text Box** > > A rich-text block for adding headings, callouts, or contextual information to your canvas. > **Global Filters** > > A filter widget that drives one or more data source widgets on the same canvas. Set shared date ranges or dimension filters once and apply them everywhere. Data source and AI chart widgets automatically receive global filter values; you can override specific filters per widget when needed (e.g., one chart with a different date range). > **Nexus** > > A commitment and purchase management widget for reviewing reservations and savings plans. Only available on accounts with the Nexus tool enabled. > **Canvas Info** > > An auto-placed header displaying the canvas name, scope badge, owner, and last-updated timestamp. Not saved as a persisted widget; it is always present. *** ## Chart types Data source widgets support 19 chart types grouped by category: | Category | Chart types | | - | - | | **Time series** | Line, Area | | **Categorical** | Bar, Horizontal Bar | | **Part-to-whole** | Pie, Donut, Treemap | | **Distribution** | Scatter, Heatmap | | **Flow / hierarchy** | Funnel, Waterfall, Sunburst | | **Statistical** | Radar, Parallel, Boxplot, Candlestick | | **Metrics** | Counter, Gauge | | **Combination** | Combo | | **Data** | Table | *** ## Configuring a data source widget **1. Select a chart type** Open the widget configuration and choose one of the 19 chart types listed above. **2. Choose an X-axis dimension** Pick the dimension for the horizontal axis (e.g. date, service, region). **3. Choose Y-axis measure(s)** Select one or more measures for the vertical axis (e.g. cost, usage). **4. Add a series dimension (optional)** Choose a series dimension to break down the data by a second attribute, creating grouped or stacked visualizations. **5. Apply filters** Add include or exclude filters and set a date range to narrow the data shown. **6. Save as preset (optional)** Save your chart configuration (chart type, dimensions, measures, and filters) as a reusable preset that you or your team can apply to future widgets. *** ## Chart customization Data source widgets support a **Chart Settings** panel for fine-tuning the visual appearance of your charts without changing the underlying data. ### Opening the Chart Settings panel Click the **settings icon** (⚙️) in the top-right corner of any data source widget to open the panel. A second settings panel may also appear to the right of the first, providing additional configuration options. ### Customization options **Title and labels** | Option | Effect | | - | - | | **Hide Title** | Remove the chart title from the visualization | | **Custom Title** | Override the chart title with your own text | | **Hide Legend** | Remove the legend from the chart | | **Legend Position** | Choose where the legend appears: auto, top, bottom, left, or right | **Series formatting** | Option | Effect | | - | - | | **Series Order** | Reorder the legend and stacking of series (for bar, line, area, and combo charts). Drag series names to rearrange | | **Series Colors** | Customize the color of any series by clicking the colored dot next to its name in the Series Order list and selecting a new color from the palette | | **Hide Labels** | Remove data labels from chart elements (e.g., bar labels, pie slice labels) | | **Show as % of Total** | **(Pie and Donut charts only)** Display each slice as a percentage of the total value. Labels and tooltips show percentages instead of raw values | **Axis and scale** | Option | Effect | | - | - | | **Y-axis Min** | Set the minimum value for the Y-axis (useful for emphasizing variation when all values are high) | | **Y-axis Max** | Set the maximum value for the Y-axis | **Rendering (for large datasets)** | Option | Effect | | - | - | | **High Fidelity** | When enabled and your dataset has over 2,000 data points, render using SVG instead of Canvas for crisper visuals (note: may impact performance on very large datasets) | ### Series color customization example 1. Open the **Chart Settings** panel on your widget. 2. Look for the **Series Order** section, which lists all series in your chart. 3. Click the **colored dot** next to any series name to open the color picker. 4. Select a color from the palette or enter a custom hex code. 5. The chart updates in real-time with the new color. **Note:** Color customizations are specific to each widget and are preserved when you save your canvas. *** ## Clara AI on canvas On canvas, Clara opens as a dedicated overlay: a different surface from the **Ask Clara** page and floating panel on Explorer, Anomalies, Recommendations, the AI pages, and more (see [Ask Clara](/clara/clara-chat)). ### Clara overlay Click the **Clara button** in the top-right corner (or press Cmd+J) to open a floating, resizable panel or docked assistant view. Clara can generate charts, answer questions about your data, and create or update widgets directly on the canvas. ### @ mentions in Clara In the Clara **composer** (overlay or dock on the canvas), type **`@`** to mention a **data source** or **widget** on the current canvas. Pick an item from the list so Clara knows exactly which data or chart you mean. This is especially helpful on busy boards with many widgets. ### Deep links and Clara Some in-app links open a canvas with Clara already active, skipping an extra click. The address bar is cleaned up automatically once Clara opens, so bookmarks stay clean. *** ## Interacting with widgets * **Move:** drag a widget by its header to reposition it on the grid. * **Resize:** drag the bottom-right corner handle. * **Copy / Paste:** select one or more widgets, then Cmd+C to copy and Cmd+V to paste. * **Select all:** Cmd+A to select every widget. * **Delete:** press Backspace or Delete to remove selected widgets. * **Lock canvas:** lock the canvas to prevent accidental moves while reviewing data (Cmd+L). *** ## Keyboard shortcuts | Shortcut | Action | | - | - | | Space | Toggle Pan / Selection mode | | Home | Pan to nearest data source | | Cmd+L | Lock / unlock canvas | | Cmd+A | Select all | | Cmd+D | Deselect all | | Cmd+C / Cmd+V | Copy / Paste | | Cmd+Shift+F | Fit view | | Cmd+J | Open Clara | | Cmd+Shift+Backspace | Clear all widgets | | Backspace / Delete | Delete selected | > [!TIP] > > On Windows and Linux, substitute Ctrl for Cmd. > Keyboard shortcuts are disabled while your cursor is in a text input, textarea, or content-editable area. *** ## Command palette Open the command palette by clicking the **gear icon** at the bottom-left of the canvas. It provides quick actions and canvas settings: **Actions** | Action | Description | | - | - | | **Templates** | Browse and apply canvas templates | | **Clear All Widgets** | Remove every widget from the canvas (with confirmation) | | **Chat History** | View previous Clara chat sessions on this canvas | | **Tour** | Restart the onboarding walkthrough | | **Download Canvas** | Export the canvas as an image | | **Refresh All Queries** | Re-run every data source query on the canvas | | **Fit View** | Zoom the viewport to show all widgets | **Settings** | Setting | Description | | - | - | | **Font Size** | Increase or decrease the base font size for widgets | | **Tooltip Limit** | Increase or decrease the number of items shown in chart tooltips | | **Series Limit** | Increase or decrease the maximum number of data series rendered in charts. Changing this value persists to your user profile. | *** ## Version history nOps automatically creates a version snapshot when you add, remove, or restore widgets. You can browse the last **10 versions** from the **Version History** button in the top-right corner. Each version shows: * **Change type:** add, remove, position change, dimension change, or restore * **Timestamp:** when the snapshot was created * **Widget count:** the number of widgets at that point * **User:** who made the change Click **Restore** on any version to replace the current canvas with that snapshot. Your current state is automatically saved as a new version before the restore takes effect. *** ## Scopes and sharing Every canvas has a **scope** that controls visibility and access: | Scope | Visibility | Who can create | | - | - | - | | **Private** | Only the owner can view and edit | Any user | | **Shared** | All organization members can view and edit | Members and admins | Change a canvas's scope from the scope badge dropdown in the canvas header. When a canvas is shared, presence avatars appear in the top-right corner, and a warning is shown if another user is actively editing. > [!NOTE] > > **Global** canvases are no longer created directly. Use **global templates** instead. Any user can apply a global template to create their own canvas from it. ### Sharing private canvases If you have a **private** canvas that you want specific team members to view or edit, create a **share link** for them: **1. Open your private canvas** From the [Canvas](https://clara.nops.io/canvas) page, open the canvas you want to share. **2. Open the share dialog** Click the **Share Reports** button (mail icon) in the top-right corner of the canvas, and find **Share private canvas link** in the panel. **3. Select recipients** Choose which team members in your organization can access the canvas via the share link. **4. Share or copy the link** Send the recipient an invitation, or copy the share link directly to share via email, chat, or your preferred method. **5. Manage share links** You can view, revoke, or create additional share links from the sharing panel at any time. **Note:** Share links are **user-specific**. They grant access only to the selected recipients. Other team members cannot use the link to access your private canvas. You can revoke any share link at any time to immediately remove access. *** ## Templates Templates let you save a canvas layout and reuse it later. They are the recommended way to get started with nOps. ### Global Templates Global Templates are created by the nOps team and available to every organization. They provide best-practice dashboards for common workflows like cost allocation, savings tracking, and commitment management. When you create a new canvas, selecting a Global Template is the fastest way to get productive. ### Saving your own template Once you have a canvas layout you like, save it as a template from the **Command palette > Templates > Save as Template**. Choose a name, description, and scope: * **Private:** visible only to you. * **Shared:** visible to your organization. * **Global:** visible to everyone (requires elevated permissions). You can also assign a **Provider** (AWS, Azure, or GCP) when saving. This tags the template so it appears under the correct cloud-provider filter in the template browser on the Canvas page. Leave it unset if the template is provider-agnostic. You can optionally add a **prompt** when saving a template. When someone applies the template, Clara will automatically run that prompt on the new canvas, useful for guiding users through a specific analysis or pre-populating charts with a common question. ### Applying a template Apply a template in two ways: 1. **When creating a canvas:** select **Load template** from the creation dialog. 2. **From the Command palette:** open **Templates**, browse or search, and apply to the current canvas. In both places, the template browser groups templates by cloud provider (AWS, Azure, GCP). Templates with no provider assigned are listed under **Unassigned**. Use the search bar or scroll within a group to find the right template. *** ## Folders Organize canvases into **folders** for better structure. New canvases created inside a folder inherit its scope by default (e.g., a canvas created inside a Private folder will be Private). This helps keep your canvases organized as your workspace grows. *** ## Automated chart refresh (canvas data) Separate from **email** reports (below), you can keep **chart data** on this canvas fresh on a schedule: 1. In the **top toolbar**, open **Auto refresh** (calendar + clock icon). 2. Use **Refresh Now** for an immediate refresh when you have edit access. 3. Turn on **Auto refresh this canvas** to let nOps refresh chart data **about once per day** while the toggle stays on. You can still refresh manually anytime. 4. Review **Past refreshes** in the same menu for recent run status. > [!TIP] > > For a deeper refresh that runs chart jobs in the background, use **Shift** + click on **Refresh Now** when the UI offers it. nOps waits for those jobs to finish before reloading the canvas. *** ## Scheduled reports **Email reports** are different from the **Auto refresh** menu above: here you configure messages sent to people’s inboxes with a snapshot of the canvas. Click the **Share Reports** button (mail icon) in the top-right corner of the canvas to send or schedule email reports. ### Send now Select recipients, add a subject and message, and send immediately. The report includes a captured thumbnail of the current canvas state. ### Schedule recurring Set a recurring schedule (daily, weekly, or monthly) with your preferred time. Scheduled reports run automatically and are delivered to the selected recipients. You can view all pending and past scheduled reports for the canvas from the same panel, and cancel any upcoming report at any time. The badge on the Share Reports button shows the number of pending scheduled reports. *** > **[Next: Users and roles](/platform/users)** > > Learn how to invite team members, assign roles, and manage permissions. # Ask Clara Source: https://help.nops.io/clara/clara-chat Chat with Clara about your cloud and AI spend, review your chat history, schedule recurring questions, and connect Clara to the tools your team already uses. ## Overview **Clara** is the AI assistant built into nOps. **Ask Clara** is its home: a full page where you can ask about cloud and AI spend, anomalies, budgets, and allocations, and pick up past conversations whenever you need them. To open it, click **Ask Clara** in the sidebar, or go to [clara.nops.io/clara](https://clara.nops.io/clara). ## Start a chat When you open Ask Clara with no conversation selected, you'll see **Every dollar, explained.** and a composer at the bottom of the page. * **Type your question** in the composer, for example, "What drove the jump in my AWS spend last week?" * **Or start from a quick action:** | Quick action | What it does | | - | - | | **Find anomalies** | Asks Clara to look for unusual spend in your account. | | **Build cost allocation** | Takes you to Cost Allocation to create a new showback. | | **Explain spend** | Asks Clara to walk through where your spend is going. | | **Savings opportunities** | Asks Clara to surface ways to save. | Clara answers in plain language, and can add charts or tables when a visual makes the answer clearer. Keep going with follow-up questions. Clara remembers the conversation. > [!NOTE] > > Clara can make mistakes. Check important figures in [Explorer](/inform/explorer) before you act on them. ## Your chats The left side of the page has your chat tools: * **New chat** starts a fresh conversation. * **Chats** lists the conversations from the last 30 days, grouped by date. Click one to reopen it. The page address updates, so you can bookmark a chat or share the link with a teammate who has access. * **MCP** opens the [MCP & Slack](#connect-clara-to-your-tools) page. * **Artifacts** is coming soon. ### Search your chats Use the search box above the list to find a past conversation. 1. Type a few words. The list narrows to chats that match. 2. If you don't see what you need, click **Not finding it? Search with AI**, or press Enter. Clara searches the meaning of your chats, not just the exact words. ### Delete a chat Use the delete action on a chat in the list to remove it. If the chat came from a scheduled question, the schedule keeps running. See [Scheduled questions](#scheduled-questions). ## Scheduled questions Have Clara answer the same question on a regular basis, such as a weekly spend summary every Monday. * **Create a schedule** by asking Clara in a chat. For example: "Send me a summary of last week's spend every Monday at 9am." * **See the results** in your chat list. Each run appears as a chat with a **Scheduled** badge, so you can open it and ask follow-up questions. * **Change a schedule** with the edit action on that chat. You can update the question and how often it runs. * **Stop a schedule** from the same edit action. Deleting the chat only removes the conversation. It does not stop the schedule. * **Send results to your team.** Scheduled results can also post to connected Slack or Teams channels. See [Slack & Teams delivery](/platform/slack-and-teams). > [!NOTE] > > You can also create schedules from [Clara MCP](/plugins/clara-mcp), the [Clara Slack Agent](/plugins/clara-slack-agent), or the [API](/developers). ## Connect Clara to your tools Open **MCP** in the left menu to reach **MCP & Slack**, where you bring Clara into the tools your team already uses. | Tile | What it does | | - | - | | **Clara MCP** | Connect Cursor, Claude, and other MCP clients to Clara. Admins turn it on, and an install guide walks you through setup. See [Clara MCP](/plugins/clara-mcp). | | **Slack Agent** | Ask Clara questions from Slack. See [Clara Slack Agent](/plugins/clara-slack-agent). | The page also shows the status of the data sources Clara can use. ## Ask Clara from other pages You don't have to leave what you're doing to ask a question. Look for the **Ask Clara** button in the bottom-right corner of these pages: * Anomalies and Recommendations (see [Insights](/inform/insights)) * [Explorer](/inform/explorer) * The [AI](/ai/introduction) pages * Cost Allocation * [Budgets](/operate/budgets) * [Contract Tracker](/operate/contract-tracker) * [Business Unit Economics](/operate/business-unit-economics) On [Canvas](/clara/canvas) and individual canvases, click the **Clara** button in the top-right corner, or press Cmd+J. > [!TIP] > > On Canvas, Clara opens as a full overlay with its own layout and shortcuts. See [Clara AI on canvas](/clara/canvas#clara-ai-on-canvas) for details, including `@` mentions for data sources and widgets. ## No cloud data yet? If your organization hasn't connected a cloud account yet, Clara can still help you explore the product and templates. Connect a provider when you're ready so Clara can analyze your live cost data. *** > **[Home page](/platform/home)** > > Choose where nOps opens when you sign in. > **[Canvas](/clara/canvas)** > > Full workspace: widgets, filters, Clara overlay, and sharing. # Authentication Source: https://help.nops.io/developers/authentication Authenticate Public API requests with nOps API keys # Authentication All `/v1` requests require an nOps API key in the `Authorization` header: ```http theme={"theme":{"light":"github-light","dark":"github-dark"}} Authorization: Bearer ``` ## Creating keys 1. Sign in to nOps as an organization admin on **Inform + Operate**. 2. Open **Settings → Security → API Keys**. 3. Create a key and assign the permissions your integration needs. 4. Copy the key when shown. It is only displayed once. ## Security rules * Keys are **never** accepted in query parameters. * Session cookies are **not** used on `/v1`. Auth is header-only. * Keys are scoped to your nOps organization and cannot be used across tenants. ## Scopes | Scope | Access | | - | - | | `cost:read` | Explorer / cost queries | | `reports:read` / `reports:write` | Saved reports | | `budgets:read` / `budgets:write` | Budgets and alerts | | `recommendations:read` | Recommendations list | | `anomalies:read` | Cost anomalies | | `feed:read` | Scheduled question runs | | `scheduled-prompts:read` / `scheduled-prompts:write` | Scheduled prompts | | `notifications:read` / `notifications:write` | Notification schedules | | `commitments:read` | Commitments (reserved; endpoint returns `501` until released) | | `cost-allocation:read` / `cost-allocation:write` | Cost Allocation showbacks, rules, and spend analytics | | `explorer-dashboards:read` / `explorer-dashboards:write` | Explorer dashboards | | `ai-optimization:read` / `ai-optimization:write` | AI Optimization default dashboard and anomalies | | `seat-tracking:read` | AI seat tracking projects, seats, limits, requests, automation, and analytics | | `seat-tracking:write` | AI seat limits, rebalance policies, limit-request decisions, and reviewer/notify settings | | `map-manager:read` / `map-manager:write` | MAP Manager projects, resources, and accounts | | `business-unit-economics:read` / `business-unit-economics:write` | Business Unit Economics models, units, items, and reports | | `contract-tracker:read` / `contract-tracker:write` | Contract Tracker contracts and burndown | | `telemetry:write` | Send OpenTelemetry data to `api.nops.io/otel`. See [Send OpenTelemetry data to nOps](/telemetry/opentelemetry) | | `mcp:read` | MCP read access (Clara agent / internal-envelope surface) | | `mcp:write` | MCP write access: requires `mcp:read` as well for mutating endpoints | When creating an API key, assign the permissions your integration needs in **Settings → Security → API Keys**. `mcp:read` and `mcp:write` gate the Clara MCP agent surface; they do not authorize API-key `/v1` calls. Use the granular scopes above for programmatic API access. ## Data visibility An API key sees all of your organization's data for the permissions you assign to it. For example, `budgets:read` lets the key read every budget, and `budgets:write` lets it edit every budget. To limit a key to the data a role can see, name the key `rbac:`. Replace `` with the slug of that role. The key then uses that role's data scope. If the role's data scope is not set up, requests with that key return `403` with the error code `forbidden_scope`. The Clara MCP scopes (`mcp:read` / `mcp:write`) are not affected. They still use the access of the signed-in user. # Errors Source: https://help.nops.io/developers/errors Public API error format and status codes # Errors Failed requests return JSON: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "error": { "code": "invalid_credentials", "message": "Invalid API key", "request_id": "550e8400-e29b-41d4-a716-446655440000" } } ``` ## Common codes | HTTP | Code | Meaning | | - | - | - | | 401 | `missing_credentials` | No `Authorization: Bearer` header | | 401 | `invalid_credentials` | Key invalid or revoked | | 403 | `forbidden_scope` | Key lacks required scope | | 403 | `forbidden_entitlement` | Your organization needs **Inform + Operate** (or a higher tier) for this endpoint | | 404 | `not_found` | Resource not found (no cross-tenant leakage) | | 429 | `rate_limited` / `quota_exceeded` | Throttled | | 503 | `service_unavailable` | Identity validation unavailable (fail closed) | Include `request_id` when contacting support. For pagination on list endpoints, see [Pagination](/developers/pagination). # Developers Source: https://help.nops.io/developers/index Programmatic access to nOps with the Public REST API # nOps Public API The nOps Public API (`api.nops.io`) provides programmatic access to cost data, cost allocation, budgets, reports, recommendations, scheduled question runs, scheduled prompts, and notifications. ## Base URL `https://api.nops.io/v1` Use the **API Reference** pages in the sidebar to explore and test endpoints interactively. Download the spec: [openapi.json](/openapi.json) (also at `/openapi.json` on [help.nops.io](https://help.nops.io)). For local preview, run `npm run dev` from `public-docs` (not plain `npx mintlify dev`) so `/openapi.json` is served with your latest generated spec. This starts a proxy on `localhost:3001` (override with `DOCS_DEV_PORT`) that serves the spec at `/openapi.json` and forwards everything else to the underlying Mintlify dev server. If you are contributing to nOps and change a Public API route, regenerate the spec from the `clara` app directory before previewing docs: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} npm run generate:public-api-openapi ``` ## Requirements The Public API is included with **nOps Inform + Operate**, the same plans that power Explorer, Budgets, Reports, and Ask Clara in the app. You will also need: * An **API key** with the permissions required for each endpoint * Keys are created in **Settings → Security → API Keys** ## Quick start ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -sS \ -H "Authorization: Bearer YOUR_API_KEY" \ https://api.nops.io/v1/recommendations ``` See [Authentication](/developers/authentication), [Rate limits](/developers/rate-limits), and [Errors](/developers/errors) for details. # Pagination Source: https://help.nops.io/developers/pagination How list endpoints paginate results with cursors # Pagination All list endpoints return a consistent envelope: an array of results in `data` and a `pagination` object describing how to fetch the next page. ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "data": [ { "id": "..." } ], "pagination": { "limit": 50, "has_more": true, "next_cursor": "eyJvZmZzZXQiOjUwfQ" } } ``` ## Parameters | Query param | Description | | - | - | | `limit` | Maximum number of items to return. Between `1` and `200`. Defaults to `50`. | | `cursor` | Opaque cursor from the previous response's `pagination.next_cursor`. Omit for the first page. | ## Pagination object | Field | Description | | - | - | | `limit` | The page size applied to this response. | | `has_more` | `true` when more results are available. | | `next_cursor` | Pass this as `cursor` to fetch the next page, or `null` when you have reached the end. | ## Iterating all pages Keep requesting with the returned `next_cursor` until `has_more` is `false` (equivalently, until `next_cursor` is `null`). ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} # First page curl -H "Authorization: Bearer $NOPS_API_KEY" \ "https://api.nops.io/v1/reports?limit=50" # Next page: pass the cursor from the previous response curl -H "Authorization: Bearer $NOPS_API_KEY" \ "https://api.nops.io/v1/reports?limit=50&cursor=eyJvZmZzZXQiOjUwfQ" ``` ```javascript theme={"theme":{"light":"github-light","dark":"github-dark"}} async function fetchAll(path) { const results = []; let cursor = null; do { const url = new URL(`https://api.nops.io${path}`); url.searchParams.set('limit', '200'); if (cursor) url.searchParams.set('cursor', cursor); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.NOPS_API_KEY}` }, }); const body = await res.json(); results.push(...body.data); cursor = body.pagination.next_cursor; } while (cursor); return results; } ``` ## Notes * Treat `next_cursor` as opaque: do not parse or construct it yourself. Its encoding may change without notice. * Some list endpoints include an extra `meta` object alongside `data` and `pagination` (for example, `scope_counts` on reports). `data` and `pagination` are always present on list responses. # Rate limits Source: https://help.nops.io/developers/rate-limits Public API rate limiting and write quotas # Rate limits The Public API applies multiple protection layers: 1. **Pre-auth IP limit:** invalid-key spraying is throttled before key validation. 2. **Per-key limit:** authenticated requests are limited per API key. 3. **Write quotas:** email sends and scheduled-prompt runs have daily caps. When limited, the API returns `429` with a standard error envelope. ## Write quotas | Operation | Default daily limit (per org + key) | | - | - | | Scheduled prompt `run` | 50 | | Notification `schedule` | 100 | ## Idempotency `POST` and `PATCH` write endpoints require an `Idempotency-Key` header. Keys are scoped per organization and API key so replays cannot collide across tenants. # Seat tracking Source: https://help.nops.io/developers/seat-tracking Manage AI seat spend, limits, and automation through the public API. The seat tracking API lets you manage AI seat spend and limits for your team. It supports Claude Enterprise and Cursor, with controls for spend limits, limit requests, automation policies, and analytics. All seat tracking endpoints are available under `/v1/seat-tracking`. ## Project-keyed model Seat tracking is organized around **projects**. Each project is backed by a budget and groups together: * Enabled providers (Claude Enterprise, Cursor) * Per-user seat spend and limits * Group allocation and targets * Limit requests and reviewer routing * Automation policies and rebalance runs * Spend history and projections A project ID looks like `aisp_xxxxxxxx`. Use the project ID to call all other seat tracking endpoints. You can list projects with `GET /v1/seat-tracking/projects` and create one with `POST /v1/seat-tracking/projects`. ## Scopes Seat tracking endpoints require one of two new API key scopes: | Scope | Access | | - | - | | `seat-tracking:read` | Read projects, seats, limits, requests, automation, and analytics. | | `seat-tracking:write` | Create or update projects, limits, requests, automation, and reviewer/notify settings. | Write endpoints that change real provider state also require an `Idempotency-Key` header. ## Legacy budget-nested aliases The original endpoints under `/v1/budgets/{id}/ai-seat-tracking` are still supported but deprecated. They now accept either `budgets:*` or `seat-tracking:*` scopes. Prefer the project-keyed endpoints for new integrations. ## User-specific usage endpoints The internal dashboard routes `my-usage` and `my-usage-history` resolve the target user from the signed-in session. API keys and MCP callers use a synthesized service user, so the public API exposes explicit user paths instead: * `GET /v1/seat-tracking/projects/{projectId}/seats/{userId}/usage` * `GET /v1/seat-tracking/projects/{projectId}/seats/{userId}/usage-history` Replace `{userId}` with the nOps user ID of the seat you want to inspect. ## Writes that hit real provider APIs Some endpoints call the Claude Enterprise or Cursor admin APIs directly. Those writes are gated by an `mcpAccess: 'none'` flag and are not reachable through the MCP envelope, even with `mcp:write`: * `PATCH /v1/seat-tracking/projects/{projectId}/seats/limits` * `PATCH /v1/seat-tracking/projects/{projectId}/seats/limits/bulk` * `POST /v1/seat-tracking/projects/{projectId}/automation/run` * `POST /v1/seat-tracking/projects/{projectId}/automation/runs/{runId}/approve` * `POST /v1/seat-tracking/projects/{projectId}/automation/runs/{runId}/undo` A limit write only reaches the provider when that seat is writable. Claude Enterprise seats always are. A Cursor seat is writable when both of these hold: * It came from a Cursor **Enterprise** team you connected with limit management enabled. A Cursor **Teams**-plan connection has no per-user limits to write. * It appears in exactly one connected Cursor team. A person in two teams has their spend summed for reporting, but nOps will not guess which team's limit to change. A write against a read-only seat fails with an explanatory error rather than being silently skipped, so you can tell a refused write from an applied one. Claude Enterprise addresses seats by provider user ID; Cursor addresses them by email, because the Cursor Admin API joins members to spend on email. ## Rate limits `POST /v1/seat-tracking/projects/{projectId}/automation/run` is limited to a daily quota per organization (default 50). Other write endpoints follow the standard public API rate limits. ## Next steps * Browse the **API Reference** pages in the [Developers](/developers) tab for request/response schemas and examples. * See [Authentication](/developers/authentication) for how to pass your API key. * See [Pagination](/developers/pagination) for how to iterate list responses. For the product behavior behind these endpoints, see the AI guides: * [AI](/ai/introduction): what the AI area covers, and the plan and role requirements * [Set up AI seat tracking](/ai/setup): connect providers and create a project * [Wallets](/ai/wallets): allocation groups, group sync, and approvers * [Budgets](/ai/budgets): group and per-seat planning targets * [Requests](/ai/requests): the limit-request queue, decisions, and temporary approvals * [Automated Rebalance](/ai/automated-rebalance): autonomy states, approval modes, and run history # Versioning & changelog Source: https://help.nops.io/developers/versioning How the nOps Public API is versioned and what has changed # Versioning The nOps Public API is versioned in the URL path. The current version is `v1` (for example, `https://api.nops.io/v1/reports`). We consider the following changes **backward compatible**, and may ship them within `v1` without notice: * Adding new endpoints, resources, or optional request parameters * Adding new fields to existing responses * Adding new values to enums or new error `code` strings * Changing the ordering of results (unless documented otherwise) Breaking changes (removing fields, renaming fields, changing types, or altering authentication) will be introduced under a new version path. > [!TIP] > > Write integrations defensively: ignore unknown response fields rather than > failing on them. ## Changelog ### 2026-07: Standard list envelope & cursor pagination * All list endpoints now return a consistent `{ data, pagination }` envelope. `data` is an array of resources and `pagination` contains `limit`, `has_more`, and `next_cursor`. See [Pagination](/developers/pagination). * List endpoints accept `limit` (1–200, default 50) and `cursor` query parameters. The previous `page`/`pageSize` parameters are no longer used. * Endpoint-specific extras (for example, `scope_counts` on reports and `schedules_by_source` on scheduled notifications) moved into a `meta` object. ### Earlier * Added Cost Allocation endpoints (showbacks, rules, previews, and summaries). * Interactive API Reference published. ## Reserved * `Commitments` endpoints are reserved and return `501` until they are generally available. # Google Cloud Platform - Commitment Management Setup Source: https://help.nops.io/gcp/commitment-management-setup Configure nOps to manage GCP Committed Use Discounts (CUDs) on your behalf, including Resource-based and Spend-based commitments. ## FAQs > **What is GCP Commitment Management?** > > GCP Commitment Management enables nOps to autonomously purchase, manage, and optimize Committed Use Discounts (CUDs) on your behalf. This includes both Resource-based CUDs (project-level) and Spend-based (Flex) CUDs (billing account-level). > **What's the difference between Resource-based and Spend-based CUDs?** > > * **Resource-based CUDs**: Purchased at the project level for specific machine families. Requires CUD sharing to be enabled to apply discounts across projects. > * **Spend-based (Flex) CUDs**: Purchased at the billing account level and automatically apply to all eligible usage across all projects. > **Do I need to enable CUD sharing?** > > Yes, for Resource-based CUDs. CUD sharing is **disabled by default** in GCP and must be enabled before nOps can share purchased commitments across your projects. > **Why are there two access paths (Automation Agent and nOps Support)?** > > * **Automation Agent**: A service account used by nOps for autonomous purchasing, quota management, and self-healing operations. > * **nOps Support**: A group email provided by nOps for console access, manual overrides, dashboards, and verification. > **Do I need Inform to view Commitment Inventory?** > > No. [Commitment Inventory](/optimize/commitment-inventory) is included on every nOps plan when your GCP integration is **active**. Inform is only required to **email** or **schedule** inventory reports. This CM setup is for purchasing and deeper CUD inventory reads, not for opening the Inventory page itself. *** ## Before You Start **You will need these 2 values:** | Value | Where to find it | | - | - | | nOps Service Account email | [nOps Settings → Cloud Provider Integrations](https://clara.nops.io/settings) | | nOps Support email | nOps UI (format: `{your-client-id}-gcp-console@nops.io`) | > [!NOTE] > > **Prerequisites:** Before configuring Commitment Management, ensure you have completed: > > * [GCP Integration Prerequisites](/gcp/prerequisites): Billing export setup > * [GCP Integration Setup](/gcp/integration-setup): Link billing data to nOps, Domain Restricted Sharing when required, and service account permissions > > You will need the **nOps Service Account email** from your existing integration. You can find it in [nOps Settings → Cloud Provider Integrations](https://clara.nops.io/settings). > [!TIP] > > **Prefer infrastructure as code?** After completing [Step 1 (Enable CUD Sharing)](#step-1-enable-cud-sharing) and [Step 2 (Create a Dedicated CUD Project)](#step-2-create-a-dedicated-cud-project), you can use our open-source Terraform module instead of the console steps in Steps 3–7. See [Terraform setup](#terraform-setup-alternative-to-console). *** ## What You're Setting Up nOps uses two identities to manage commitments on your behalf: | Identity | What it does | | - | - | | **Automation Agent** (Service Account) | Autonomous purchasing, quota fixing, self-healing | | **nOps Support** (nOps Email) | Dashboard access, manual overrides, support tickets | Both identities need roles at three scopes: Organization, Billing Account, and Project. This guide walks through each scope exactly once, granting roles for both identities at each step. *** ## Step 1: Enable CUD Sharing CUD sharing is off by default. This must be enabled for resource-based CUD discounts to apply across projects in your billing account. > [!WARNING] > > **Cannot be undone from Console.** Once enabled, only Cloud Billing Support can revert it. The reverted setting takes effect at the start of the following month. > [!WARNING] > > **Spend-based CUDs** automatically apply across all projects without this step. This is only needed for resource-based CUDs. > [!NOTE] > > **Required permission:** Billing Account Administrator (includes `billing.subscriptions.update`) **1. Open CUD Analysis** Go to **Billing** in the GCP Console, select your billing account, and then choose **CUD analysis** on the left sidebar. **2. Open CUD Scope Settings** Click the 3 dots next to **Purchase CUDS** → **CUD scope & settings**. **3. Select CUD Scope and Settings** In "Resource-based CUD scope", ensure it says **billing account** and save. **4. Confirm and Enable** In the confirmation dialog, type `Enable` and click **Enable billing account scope**. > [!NOTE] > > **Propagation:** Can take up to 24 hours. If unchanged after 24 hours, contact Cloud Billing Support. *** ## Step 2: Create a Dedicated CUD Project nOps purchases all resource-based commitments from a single dedicated project. With CUD sharing enabled (Step 1), discounts automatically apply across all projects in the billing account. **1. Create the Dedicated Project** Go to **IAM & Admin at the org level** → **Go to "Manage Resources"** **2. Enter Project Details** Enter the following details:
  • **Project name:** `nops-cud-purchases` (or your preferred name)
  • **Organization:** Select your organization
  • **Location:** Select the appropriate folder or organization root
**3. Create the Project** Click **Create** to create the project. **4. Link Project to Billing Account** Ensure you pick your billing account you want cud purchases in. It should align with the billing account you selected for this integration. > [!NOTE] > > **Save the Project ID.** You'll need it for Step 3 and Step 6. *** ## Step 3: Enable Required APIs **1. Navigate to APIs & Services** Go to **APIs & Services** → **Library** **2. Select Project** Select the **`nops-cud-purchases`** project from the top dropdown **3. Enable Required APIs** Click **Enable** for each of the following APIs: | API | Service ID | Purpose | | - | - | - | | Compute Engine API | `compute.googleapis.com` | Purchase resource-based CUDs | | Cloud Commerce Consumer Procurement API | `cloudcommerceconsumerprocurement.googleapis.com` | Purchase spend-based (Flex) CUDs | | Cloud Asset API | `cloudasset.googleapis.com` | Asset inventory and export | | Cloud Quotas API | `cloudquotas.googleapis.com` | Auto-fix quotas before purchasing | | Service Usage API | `serviceusage.googleapis.com` | Service quota management | | Recommender API | `recommender.googleapis.com` | CUD recommendations and savings analysis | ## Step 4: Create the Custom Role (Organization Level) Below are the permissions you will grant to the nOps Custom Role | Permission | Description | | - | - | | compute.commitments.create | Create compute commitments | | compute.commitments.get | Get compute commitments | | compute.commitments.list | List compute commitments | | compute.commitments.update | Update compute commitments | | compute.commitments.updateReservations | Update compute reservations | | compute.regionOperations.get | Get compute region operations | | compute.reservations.list | List reservations (attach to Local SSD / GPU commitments) | | compute.reservations.get | Get a reservation (attach to Local SSD / GPU commitments) | | compute.reservations.create | Attach existing reservations at commitment creation | | serviceusage.quotas.get | Get service usage quotas | | serviceusage.quotas.update | Update service usage quotas | | serviceusage.services.get | Get service usage services | | serviceusage.services.list | List service usage services | | serviceusage.services.use | Use services (required for Procurement API billing attribution) | | cloudquotas.quotas.get | Get cloud quotas | | cloudquotas.quotas.update | Update cloud quotas | | cloudasset.assets.exportResource | Export cloud asset resources | | monitoring.timeSeries.list | List monitoring time series | **1. Navigate to Roles** Go to **IAM & Admin** → **Roles** **2. Select Organization** Select your **Organization** from the top dropdown **3. Create Role** Click **+ Create Role** on the top menu bar **4. Set Role Details** Set:
  • **Title:** `nOps Resource Manager`
  • **Description:** `Least-privilege role for nOps to manage Compute Commitments, Quotas, and Service Usage`
  • **ID:** `nOpsResourceManager`
  • **Role launch stage:** General Availability
**5. Add Permissions** Click **Add Permissions** → **Import** Click the **Enter property name or value** text box and paste in the first permission in the list above Select the **Checkbox** next to the permission and click **Add** Click the **blue X** next to the permission name you pasted in the **Enter property name or value** text box to remove the filter Repeat for each of the permissions in the list above **6. Create the Role** When you have finished adding all permissions, click **Create** to create the role. *** ## Step 5: Organization IAM (Grant Roles to Both Identities) While you're still at the Organization level in IAM: **1. Navigate to IAM** Go to **IAM & Admin** → **IAM** **2. Confirm Organization** Confirm your **Organization** is selected in the top dropdown ### Grant access to the Automation Agent (Service Account) **1. Grant access to the Automation Agent (Service Account)** Click **+ Grant Access** **2. Enter nOps Service Account email** Enter the nOps Service Account email in **New principals** **3. Add roles** Add roles:
  • **Cloud Asset Viewer** (`roles/cloudasset.viewer`)
  • **Browser** (`roles/browser`)
  • **Recommender Viewer** (`roles/recommender.viewer`)
  • **Cloud SQL Viewer** (`roles/cloudsql.viewer`)
  • **Cloud Run Viewer** (`roles/run.viewer`)
  • **Compute Recommender Viewer** (`roles/recommender.computeViewer`)
  • *(Paid support plan only)* **Cloud Support Tech Support Editor** (`roles/cloudsupport.techSupportEditor`)
**4. Save** Click **Save** ### Grant access to nOps Support **1. Grant access to nOps Support** Click **+ Grant Access** **2. Enter nOps Support email** Enter the nOps Support email in **New principals** **3. Add roles** Add roles:
  • **Browser** (`roles/browser`)
  • **Compute Viewer** (`roles/compute.viewer`)
  • *(Paid support plan only)* **Cloud Support Tech Support Editor** (`roles/cloudsupport.techSupportEditor`)
**4. Save** Click **Save** > [!WARNING] > > **No paid support plan?** Skip the `techSupportEditor` role for both identities. You can still contact Cloud Billing Support for CUD-related issues at no cost. > > To check your plan: **Support** → **Overview** → look for "Your current Customer Care service." *** ## Step 6: Project IAM (Grant Roles to Both Identities) **1. Navigate to IAM** Go to **IAM & Admin** → **IAM** **2. Select Project** Select the **`nops-cud-purchases`** project from the top dropdown ### Grant access to the Automation Agent (Service Account) **1. Grant access to the Automation Agent (Service Account)** Click **+ Grant Access** **2. Enter nOps Service Account email** Enter the nOps Service Account email in **New principals** **3. Add roles** Add roles:
  • **Compute Viewer** (`roles/compute.viewer`)
  • **nOps Resource Manager** (the custom role from Step 3)
**4. Save** Click **Save** ### Grant access to nOps Support **1. Grant access to nOps Support** Click **+ Grant Access** **2. Enter nOps Support email** Enter the nOps Support email in **New principals** **3. Add roles** Add roles:
  • **Compute Viewer** (`roles/compute.viewer`)
**4. Save** Click **Save** *** ## Step 7: Billing Account IAM (Grant Roles to Both Identities) **1. Navigate to Billing Account Management** Go to **Billing** → select your billing account → **Account Management** **2. Show info panel** Click **Show info panel** in the top-right corner ### Grant access to the Automation Agent (Service Account) **1. Grant access to the Automation Agent (Service Account)** Click **+ Add Principal** **2. Enter nOps Service Account email** Enter the nOps Service Account email in **New principals** **3. Add roles** Add roles:
  • **Billing Account Viewer** (`roles/billing.viewer`)
  • **Consumer Procurement Order Admin** (`roles/consumerprocurement.orderAdmin`)
  • **Recommender Billing Account CUD Admin** (`roles/recommender.billingAccountCudAdmin`)
**4. Save** Click **Save** ### Grant access to nOps Support **1. Grant access to nOps Support** Click **+ Add Principal** **2. Enter nOps Support email** Enter the nOps Support email in **New principals** **3. Add roles** Add roles:
  • **Billing Account Viewer** (`roles/billing.viewer`)
  • **Recommender Billing Account CUD Viewer** (`roles/recommender.billingAccountCudViewer`)
**4. Save** Click **Save** *** ## Terraform Setup (Alternative to Console) If you manage GCP with **Terraform** or **OpenTofu**, you can provision everything in Steps 3–7 (the required APIs, the nOps Resource Manager custom role, and the organization-, project-, and billing account-level IAM bindings for both identities) using the official nOps module. Use this path **instead of** the manual console instructions in [Step 3](#step-3-enable-required-apis) through [Step 7](#step-7-billing-account-iam-grant-roles-to-both-identities). **Repository:** [nops-io/terraform-gcp-nops-commitment-management](https://github.com/nops-io/terraform-gcp-nops-commitment-management) Complete these steps first. They cannot be done with the module: 1. [Step 1: Enable CUD Sharing](#step-1-enable-cud-sharing): a billing account setting that must be changed in the Console 2. [Step 2: Create a Dedicated CUD Project](#step-2-create-a-dedicated-cud-project): the module configures an **existing** CUD purchase project; note the Project ID for the module input Then configure the module inputs with your organization ID, billing account ID, CUD purchase project ID, and the **nOps Service Account email** and **nOps Support email** from nOps. Follow the README in the repository for the full list of variables, the `examples/basic` layout, and how to run `terraform apply` or `tofu apply`. > [!NOTE] > > The repository README is the source of truth for Terraform inputs and optional settings (such as the Cloud Support Tech Support Editor role for paid support plans). If anything conflicts with this guide, follow the module documentation for Terraform-specific behavior. *** ## Related Guides > **[Prerequisites](/gcp/prerequisites)** > > Configure billing exports and prepare your GCP environment. > **[Integration Setup](/gcp/integration-setup)** > > Link GCP billing data and grant service account permissions. > **[Permissions and Resources - Savings Analysis](/gcp/permissions-and-resources-sa)** > > Overview of all permissions and resources needed for Savings Analysis. > **[Permissions and Resources - Commitment Management](/gcp/permissions-and-resources-cm)** > > Overview of all permissions and resources needed for Commitment Management. # Google Cloud Platform - Integration Setup Source: https://help.nops.io/gcp/integration-setup Configure Domain Restricted Sharing when required, link your GCP billing data to nOps, and grant the required service account permissions for cost visibility and optimization. ## FAQs > **What if I don't see my billing data in BigQuery?** > > * Ensure that **Billing Export** is enabled for the correct project. > * Check if the **dataset and table names** match what was configured in nOps. > * Wait **up to 48 hours** for the first full dataset to appear. > **Can I use customer-managed encryption keys?** > > No, Google Cloud only supports **Google-managed encryption** for billing data exports. > **How often is billing data updated on nOps?** > > Billing data is refreshed **daily**, but there might be a 48-hour delay for full updates. > **How long does it take for the Pricing and Detailed Resource tables to be available?** > > The tables under the **Detailed Usage Cost** and **Pricing** exports may take up to 48 hours to be created. > **Do all exports need to be in the same location?** > > **Yes.** The **Detailed Usage Cost** and **Pricing** exports **must** be configured to use the same location (US or EU) and preferably the same project. Using different locations will cause integration issues with nOps. > **Why do I need to grant permissions at three different levels (Organization, Billing Account, Project)?** > > Each level provides different types of access: > > * **Organization-level role** (Compute Viewer) allows nOps to list resource-based commitment objects across your organization. > * **Billing Account-level role** is required to access billing metadata, currency information, and CUD recommendations at billing scope. This cannot be granted at the project level. > * **Project-level roles** provide access to the BigQuery dataset containing your cost export data. > > Granting roles only at one level will result in incomplete data or integration failures. > > **Note:** Additional organization-level roles for full resource analysis (Cloud Asset Viewer, Cloud SQL Viewer, Cloud Run Viewer, Compute Recommender Viewer) are configured during the [Commitment Management setup](/gcp/commitment-management-setup), keeping the initial onboarding minimal. *** ## Overview > [!NOTE] > > Before proceeding, ensure you have completed the [GCP Integration Prerequisites](/gcp/prerequisites) including: > > * Checking if billing exports are already enabled > * Configuring GCP billing exports (if not already enabled) > > If your organization uses **Domain Restricted Sharing**, review [Domain Restricted Sharing](#1-domain-restricted-sharing) below before granting IAM roles to the nOps service account. > [!TIP] > > **Prefer infrastructure as code?** After you create the GCP integration in nOps and copy the **nOps service account email**, you can use our open-source Terraform module instead of the console steps under [Finding Your BigQuery Dataset IDs](#finding-your-bigquery-dataset-ids), [Section 3](#3-grant-service-account-permissions-in-gcp), and [Section 4](#4-enable-required-apis). See [Terraform setup](#terraform-setup-alternative-to-console). *** ## 1. Domain Restricted Sharing > [!NOTE] > > The nOps GCP integration wizard includes a Domain Restricted Sharing step that you must review before proceeding. If your organization has DRS enabled, you need to add the nOps Customer ID to your allowed domains before granting any IAM roles. If DRS is not enabled, you can confirm and continue without any changes. If your GCP organization has **Domain Restricted Sharing** enabled (via the `iam.allowedPolicyMemberDomains` constraint), you will encounter an error when trying to grant IAM roles to the nOps service account: ``` ERROR: One or more users named in the policy do not belong to a permitted customer. ``` This security policy restricts which external identities can be granted IAM roles in your organization. To allow the nOps service account, you need to add the **nOps Google Workspace Customer ID** to your organization's allowed domains list. > [!NOTE] > > To modify organization policies, you need the **Organization Policy Administrator** (`roles/orgpolicy.policyAdmin`) IAM role on the organization. Contact your GCP administrator if you don't have this role. ### Checking and Configuring Domain Restricted Sharing During GCP onboarding, the integration wizard shows the **Domain Restricted Sharing** section in Step 1 so you can confirm whether DRS applies and act on it before granting permissions. **To check whether DRS is enabled in your organization:** **1. Open the GCP Integration Wizard** Go to [nOps Settings → Cloud Provider Integrations](https://clara.nops.io/settings#cloud) and click the **Google Cloud Platform** card. **2. Review the Domain Restricted Sharing section** In Step 1 of the wizard, the **Domain Restricted Sharing** section displays the **nOps Customer ID** with a copy button. Check whether your GCP organization has the `iam.allowedPolicyMemberDomains` policy enabled before proceeding. **If DRS is enabled**, add the nOps Customer ID to your allowed domains: **1. Go to Organization Policies** Navigate to **IAM & Admin → Organization Policies** in the [Google Cloud Console](https://console.cloud.google.com/iam-admin/orgPolicies). **2. Select Organization** Select your **Organization** from the project/organization selector at the top. **3. Find the Domain Restricted Sharing Policy** Search for and select the policy **Domain restricted sharing** (`iam.allowedPolicyMemberDomains`). **4. Manage Policy** Click **Manage Policy**. **5. Add Value** Under **Policy values**, click **Add value**. **6. Enter nOps Customer ID** Enter the nOps Customer ID (copy it from the GCP integration wizard in nOps). **7. Save** Click **Save**. **If DRS is not enabled**, no changes are needed. Continue with the next section to link your billing data to nOps. *** ## 2. Link GCP Billing Data to nOps Once billing exports are configured in GCP, connect them to nOps using the integration wizard. **1. Open Cloud Provider Integrations** Log in to **nOps** and go to [**Settings → Cloud Provider Integrations**](https://clara.nops.io/settings). Scroll down to the **Add a provider** section and click the **Google Cloud Platform** card. **2. Step 1: Configure Billing Exports and Name Your Integration** The **Connect Google Cloud Platform** dialog opens at **Step 1 of 2**. This step includes two required sections to review before continuing: The wizard displays the nOps Customer ID here. If your GCP organization has the `iam.allowedPolicyMemberDomains` policy enabled, add this Customer ID to your allowed domains now (see [Domain Restricted Sharing](#1-domain-restricted-sharing)). If DRS is not enabled in your organization, no action is needed. Detailed Usage Cost, Pricing, and Committed Use Discounts must all be enabled. See [Prerequisites](/gcp/prerequisites) if you have not configured them yet. Enter an **Integration Name** (e.g., "My Organization GCP Integration 1") and click **Next**. **3. Step 2: Enter Billing Account ID and Dataset IDs** On **Step 2 of 2**, enter the following: Format: `XXXXXX-XXXXXX-XXXXXX` (e.g., `0115B9-C18400-A979DC`) Format: `project.dataset.table` or `project.dataset` Format: `project.dataset.table` or `project.dataset` Format: `project.dataset.table` or `project.dataset` Format: `project.dataset.table` or `project.dataset`. Leave this blank if you have not enabled the FOCUS billing export. Use the **How to find** links next to each field for guidance on locating these values. **4. Create the Integration** Click **Create Integration**. nOps will provision a **service account** for your GCP integration. Copy the **service account email**. You will need it in the next sections to grant permissions. > [!TIP] > > If the Detailed Usage Cost and Pricing exports share the same BigQuery dataset, you can use the same Dataset ID for both fields. > [!NOTE] > > FOCUS is an open standard that presents your cost and usage data in a common format across cloud providers. It is optional in nOps. Unlike the other exports, Google creates and names the FOCUS dataset for you: it is called `gcp_billing_immutable__` (with dashes in your billing account ID replaced by underscores) and lives in the project you chose when you turned the export on. You can add it later from **Settings → Cloud Provider Integrations** if you enable the export after connecting. ### Finding Your Billing Account IDs **1. Navigate to Billing** Go to **Billing** in the [GCP Console](https://console.cloud.google.com/billing). From the billing accounts list, click on the billing account name. **2. Copy Billing Account ID** Copy the Billing Account ID from the URL. The format is `XXXXXX-XXXXXX-XXXXXX` (e.g., `0115B9-C18400-A979DC`). ### Finding Your BigQuery Dataset IDs **1. Navigate to Billing Export** Go to **Billing** in the [GCP Console](https://console.cloud.google.com/billing). From the billing accounts list, click on the billing account name. Select **Billing Export** from the left-hand menu. Each enabled export lists its dataset here. If you turned on the FOCUS export, its dataset is the Google-managed `gcp_billing_immutable__`. **2. Open Dataset in BigQuery** Click on the **Dataset name** link for the first export (e.g., Detailed Usage Cost). This will open BigQuery with that dataset selected. **3. Manage Permissions** In BigQuery, click on the **three vertical dots** next to the dataset name in the left panel. Hover over **Share** and select **Manage permissions**. **4. Grant BigQuery Data Viewer Role** 1. In the permissions panel, click **Add Principal**. 2. In the **New principals** field, enter the nOps service account email. 3. In the **Select a role** dropdown, choose **BigQuery Data Viewer** (`roles/bigquery.dataViewer`). 4. Click **Save**. 5. Repeat for each distinct export dataset, including the FOCUS dataset (`gcp_billing_immutable__`) if you enabled that export. *** ## 3. Grant Service Account Permissions in GCP Once the nOps service account email is generated, grant it the required permissions **in the Google Cloud Console**, unless you are using [Terraform setup](#terraform-setup-alternative-to-console). Permissions must be granted at three different levels: **Organization**, **Billing Account**, and **Project**. > [!WARNING] > > The nOps service account requires permissions at multiple levels. Granting roles only at the project level will not provide sufficient access for full cost visibility and recommendations. > [!NOTE] > > If your GCP organization has Domain Restricted Sharing enabled, you must add the nOps Customer ID to your allowed domains **before** granting any of the permissions below, or the role assignments will fail. The nOps Customer ID is shown in Step 1 of the integration wizard. See [Domain Restricted Sharing](#1-domain-restricted-sharing) above for detailed instructions. *** ### A. Organization-Level Roles (Savings Analysis) For the initial savings analysis setup, three organization-level roles are required. Additional roles for full resource analysis are configured later during [Commitment Management setup](/gcp/commitment-management-setup). **Required Roles:** | Role | ID | Purpose | | - | - | - | | Compute Viewer | `roles/compute.viewer` | List resource-based commitment objects | | Recommender Viewer | `roles/recommender.viewer` | Read cost recommendations at project/org scope | | Browser | `roles/browser` | Enumerate projects and folders | **1. Navigate to Organization IAM** Go to **IAM & Admin → IAM** in the [Google Cloud Console](https://console.cloud.google.com/iam-admin/iam). **2. Switch to Organization** At the top of the page, use the project/organization selector to switch to your **Organization** (not a specific project). **3. Grant Access to nOps Service Account** Click **+ Grant Access**. In the **New principals** field, enter the nOps service account email (obtained from the integration setup). Add the following roles: * **Compute Viewer** (`roles/compute.viewer`) * **Recommender Viewer** (`roles/recommender.viewer`) * **Browser** (`roles/browser`) Click **Save**. *** ### B. Billing Account-Level Role This role is required for currency and billing metadata validation. It must be granted directly on the Billing Account. **Required Role:** **Billing Account Viewer** (`roles/billing.viewer`) > [!NOTE] > > Permissions granted in the standard Project IAM page do **not** propagate to the Billing Account. You must grant this role via the Billing console or gcloud CLI. **1. Navigate to Billing Account Management** Go to **Billing** in the [Google Cloud Console](https://console.cloud.google.com/billing). From the billing accounts list, click on the billing account name that you configured the exports for. Click **Account Management** in the left-hand menu. **2. Open the Info Panel** On the Account Management page, click **Show info panel** in the top-right corner (if the panel is not already visible). This will open a side panel titled with your billing account name. **3. Grant Billing Account Viewer Role** In the info panel on the right, click **+ Add Principal**. In the **New principals** field, enter the nOps service account email. Select the role: **Billing Account Viewer** (`roles/billing.viewer`). Click **Save**. *** ### C. Dataset-Level Roles (Cost Export Datasets) These roles are required for reading BigQuery billing data and must be granted on **each dataset** that contains your cost export data: * **Detailed Usage Cost** dataset * **Pricing** dataset * **Committed Use Discounts** dataset * **FOCUS** dataset: only if you entered a FOCUS Dataset ID **Required Role:** **BigQuery Data Viewer** (`roles/bigquery.dataViewer`) > [!NOTE] > > If you configured all exports to use the **same dataset**, you only need to grant the permissions **once** on that shared dataset. **1. Navigate to Billing Export** Go to **Billing** in the [GCP Console](https://console.cloud.google.com/billing). From the billing accounts list, click on the billing account name. Select **Billing Export** from the left-hand menu. **2. Open Dataset in BigQuery** Click on the **Dataset name** link for the first export (e.g., Detailed Usage Cost). This will open BigQuery with that dataset selected. **3. Manage Permissions** In BigQuery, click on the **three vertical dots** next to the dataset name in the left panel. Hover over **Share** and select **Manage permissions**. **4. Grant BigQuery Data Viewer Role** 1. In the permissions panel, click **Add Principal**. 2. In the **New principals** field, enter the nOps service account email. 3. In the **Select a role** dropdown, choose **BigQuery Data Viewer** (`roles/bigquery.dataViewer`). 4. Click **Save**. **5. Repeat for Other Datasets (if different)** If your Pricing, Committed Use Discounts, or FOCUS exports use **different datasets**, go back to the Billing Export page and repeat Steps 2-4 for each additional export dataset. The FOCUS dataset is always separate, because Google creates it for you. *** ### D. Project-Level Service Usage Role The **Service Usage Consumer** role must be granted on the project that hosts your billing exports. **Required Role:** **Service Usage Consumer** (`roles/serviceusage.serviceUsageConsumer`) **1. Navigate to IAM** Go to **IAM & Admin → IAM** in the [Google Cloud Console](https://console.cloud.google.com/iam-admin/iam). **2. Select Project** Select the **project that hosts your billing exports** (where your BigQuery billing export dataset is located). **3. Grant Service Usage Consumer Role** Click **+ Grant Access**. In the **New principals** field, enter the nOps service account email. Select the role: **Service Usage Consumer** (`roles/serviceusage.serviceUsageConsumer`). Click **Save**. *** ### E. Project-Level BigQuery Resource Viewer Role (Optional) > [!NOTE] > > This role is **only required** if your organization uses **flat-rate or reservation-based BigQuery pricing**. Most customers use on-demand pricing and can **skip this section**. > > **How to check:** Go to **BigQuery → Administration → Reservations** in the GCP Console. If you see reservations or capacity commitments configured, you need this role. The **BigQuery Resource Viewer** role allows nOps to read BigQuery reservation and slot information for capacity planning and cost optimization of flat-rate BigQuery workloads. **Role:** **BigQuery Resource Viewer** (`roles/bigquery.resourceViewer`) **1. Navigate to IAM** Go to **IAM & Admin → IAM** in the [Google Cloud Console](https://console.cloud.google.com/iam-admin/iam). **2. Select Project** Select the **project** that contains your BigQuery billing export dataset. **3. Grant BigQuery Resource Viewer Role** Click **+ Grant Access**. In the **New principals** field, enter the nOps service account email. Select the role: **BigQuery Resource Viewer** (`roles/bigquery.resourceViewer`). Click **Save**. *** ## 4. Enable Required APIs Enable the following APIs **in the Google Cloud Console** to allow nOps to collect cost and usage data for savings analysis, unless you are using [Terraform setup](#terraform-setup-alternative-to-console), which can enable them for you. **APIs only need to be enabled in the project that hosts your billing exports**, not across all projects. **Required APIs (Savings Analysis):** | API | Service ID | Purpose | | - | - | - | | Cloud Billing API | `cloudbilling.googleapis.com` | Billing account access and cost data | | Recommender API | `recommender.googleapis.com` | Cost optimization recommendations | > [!NOTE] > > **Additional APIs** for full resource analysis (Cloud Asset API, Cloud Quotas API, Compute Engine API) are enabled during [Commitment Management setup](/gcp/commitment-management-setup). **Optional APIs:** | API | Service ID | When Required | | - | - | - | | BigQuery Reservation API | `bigqueryreservation.googleapis.com` | Only if using flat-rate/reservation BigQuery pricing | **1. Navigate to APIs & Services** Go to **APIs & Services → Library** in the [Google Cloud Console](https://console.cloud.google.com/apis/library). **2. Select Project** Select the **project that hosts your billing exports** from the top dropdown menu. **3. Enable Required APIs** Click **Enable** for each of the following APIs: * **Cloud Billing API** (`cloudbilling.googleapis.com`) * **Recommender API** (`recommender.googleapis.com`) > [!NOTE] > > **Optional:** Only enable the **BigQuery Reservation API** if you use flat-rate or reservation-based BigQuery pricing. Most customers use on-demand pricing and can skip this. *** ## Terraform Setup (Alternative to Console) If you manage GCP with **Terraform** or **OpenTofu**, you can provision the organization-, billing-, project-, and BigQuery dataset-level IAM bindings for the nOps service account, and enable the required APIs on your billing export project, using the official nOps module. Use this path **instead of** the manual console instructions under [Finding Your BigQuery Dataset IDs](#finding-your-bigquery-dataset-ids) (BigQuery Data Viewer), [Section 3](#3-grant-service-account-permissions-in-gcp), and [Section 4](#4-enable-required-apis). **Repository:** [nops-io/terraform-gcp-nops-integration](https://github.com/nops-io/terraform-gcp-nops-integration) Complete the same prerequisites and nOps-side steps first: 1. [GCP Integration Prerequisites](/gcp/prerequisites) (including billing exports) 2. [Domain Restricted Sharing](#1-domain-restricted-sharing), if it applies to your organization 3. [Section 2](#2-link-gcp-billing-data-to-nops): create the integration in nOps, enter your billing export details, and copy the **nOps service account email**. The module uses this as an input Follow the README in the repository for variables (for example organization ID, service account email, and billing account / dataset configuration), the `examples/basic` layout, and how to run `terraform apply` or `tofu apply`. > [!NOTE] > > The repository README is the source of truth for Terraform inputs and optional settings. If anything conflicts with this guide, follow the module documentation for Terraform-specific behavior. *** ## Next Steps Once the basic integration is configured, you can optionally enable Commitment Management for automated CUD purchasing: > **[GCP Commitment Management Setup](/gcp/commitment-management-setup)** > > Configure nOps to manage GCP Committed Use Discounts (CUDs) on your behalf, including Resource-based and Spend-based commitments. > **[Prerequisites](/gcp/prerequisites)** > > Configure billing exports and prepare your GCP environment. > **[Commitment Management Setup](/gcp/commitment-management-setup)** > > Configure automated CUD purchasing and nOps support team access. > **[Permissions and Resources - Savings Analysis](/gcp/permissions-and-resources-sa)** > > Overview of all permissions and resources needed for Savings Analysis. > **[Permissions and Resources - Commitment Management](/gcp/permissions-and-resources-cm)** > > Overview of all permissions and resources needed for Commitment Management. # Google Cloud Platform - Permissions & Resources - Commitment Management Source: https://help.nops.io/gcp/permissions-and-resources-cm Complete reference of all permissions nOps requires and all resources created or needed in your GCP environment to run commitment management. ## Overview nOps offers two integration tiers, each requiring different levels of access: 1. **[Savings Analysis](/gcp/integration-setup)** -- Read-only cost visibility, resource inventory, and optimization recommendations 2. **[Commitment Management](/gcp/commitment-management-setup)** -- Automated purchasing and management of GCP Committed Use Discounts (CUDs), via both an Automation Agent (service account) and the nOps Operations Team *** ## Permissions Commitment Management requires elevated permissions beyond Savings Analysis, split into two access paths: * **Automation Agent (Service Account)** -- For autonomous purchasing and quota management * **nOps Support Team** -- For GCP Console access, dashboards, and manual overrides ### Automation Agent (Service Account) #### Organization-Level Roles | Role | Role ID | Purpose | | - | - | - | | Browser | `roles/browser` | Browse organization hierarchy | | Cloud Asset Viewer | `roles/cloudasset.viewer` | Enumerate assets across services | | Recommender Viewer | `roles/recommender.viewer` | Read cost recommendations at project/org scope | | Cloud SQL Viewer | `roles/cloudsql.viewer` | Read Cloud SQL instances | | Cloud Run Viewer | `roles/run.viewer` | Read Cloud Run services | | Compute Recommender Viewer | `roles/recommender.computeViewer` | View CUD/SUD recommendations | | Cloud Support Tech Support Editor | `roles/cloudsupport.techSupportEditor` | Create support tickets (paid support plans only) | #### Billing Account Roles | Role | Role ID | Purpose | | - | - | - | | Billing Account Viewer | `roles/billing.viewer` | View spend data | | Consumer Procurement Order Admin | `roles/consumerprocurement.orderAdmin` | Purchase spend-based (Flex) CUDs | | Recommender Billing Account CUD Admin | `roles/recommender.billingAccountCudAdmin` | Access CUD recommendations | #### Project-Level Roles (CUD Project) | Role | Role ID | Purpose | | - | - | - | | Compute Viewer | `roles/compute.viewer` | View VMs for coverage analysis | | nOps Resource Manager | Custom role (see below) | Purchase and manage resource-based CUDs | ### nOps Support Team #### Organization-Level Roles | Role | Role ID | Purpose | | - | - | - | | Browser | `roles/browser` | See organization and list projects in GCP Console | | Compute Viewer | `roles/compute.viewer` | View VMs and compute resources | | Cloud Support Tech Support Editor | `roles/cloudsupport.techSupportEditor` | Create support tickets (paid support plans only) | #### Billing Account Roles | Role | Role ID | Purpose | | - | - | - | | Billing Account Viewer | `roles/billing.viewer` | View billing dashboard | | Recommender Billing Account CUD Viewer | `roles/recommender.billingAccountCudViewer` | View CUD recommendations | #### Project-Level Roles (CUD Project) | Role | Role ID | Purpose | | - | - | - | | Compute Viewer | `roles/compute.viewer` | Populate Machine Family and Region dropdowns | ### Custom Role: nOps Resource Manager Created at the **organization level**, granted at the **CUD project level**. * **Title:** nOps Resource Manager * **ID:** `nOpsResourceManager` **Included Permissions:** | Category | Permission | | - | - | | Compute Lifecycle | `compute.commitments.create` | | Compute Lifecycle | `compute.commitments.update` | | Compute Lifecycle | `compute.commitments.updateReservations` | | Compute Lifecycle | `compute.commitments.get` | | Compute Lifecycle | `compute.commitments.list` | | Compute Lifecycle | `compute.regionOperations.get` | | Reservations | `compute.reservations.list` | | Reservations | `compute.reservations.get` | | Reservations | `compute.reservations.create` | | Quota Management | `serviceusage.quotas.get` | | Quota Management | `serviceusage.quotas.update` | | Quota Management | `serviceusage.services.get` | | Quota Management | `serviceusage.services.list` | | Quota Management | `serviceusage.services.use` | | Quota Management | `cloudquotas.quotas.get` | | Quota Management | `cloudquotas.quotas.update` | | Asset Export | `cloudasset.assets.exportResource` | | Monitoring | `monitoring.timeSeries.list` | ## Resources You Must Create | Resource | Details | | - | - | | **Dedicated GCP Project** (e.g., `nops-cud-purchases`) | Must be linked to your billing account. With CUD sharing enabled, discounts apply across all projects. | | **Custom IAM Role** (`nOpsResourceManager`) | Created at the organization level, granted at the CUD project level. See permission list above. | *** ## Required APIs Enabled on the **dedicated CUD project**. | API | Service ID | | - | - | | Compute Engine API | `compute.googleapis.com` | | Cloud Commerce Consumer Procurement API | `cloudcommerceconsumerprocurement.googleapis.com` | | Cloud Asset API | `cloudasset.googleapis.com` | | Cloud Quotas API | `cloudquotas.googleapis.com` | | Service Usage API | `serviceusage.googleapis.com` | | Recommender API | `recommender.googleapis.com` | *** ## CUD Sharing Requirement For Commitment Management with resource-based CUDs, **CUD sharing must be enabled** on your billing account. CUD sharing is disabled by default in GCP. > [!WARNING] > > After you enable CUD sharing, **you cannot disable it yourself**. Cloud Billing Support must perform this action. > [!NOTE] > > Spend-based (Flex) CUDs automatically apply across all projects without requiring CUD sharing. *** ## Related Guides > **[Prerequisites](/gcp/prerequisites)** > > Configure billing exports and prepare your GCP environment. > **[Integration Setup](/gcp/integration-setup)** > > Link GCP billing data and grant service account permissions. > **[Commitment Management Setup](/gcp/commitment-management-setup)** > > Configure automated CUD purchasing and nOps operations team access. > **[Permissions and Resources - Savings Analysis](/gcp/permissions-and-resources-sa)** > > Overview of all permissions and resources needed for Savings Analysis. # Google Cloud Platform - Permissions & Resources - Savings Analysis Source: https://help.nops.io/gcp/permissions-and-resources-sa Complete reference of all permissions nOps requires and all resources created or needed in your GCP environment to run a savings analysis. > [!NOTE] > > Setup takes approximately **20 minutes** to complete. ## Overview nOps offers two integration tiers, each requiring different levels of access: 1. **[Savings Analysis](/gcp/integration-setup)** -- Read-only cost visibility, resource inventory, and optimization recommendations 2. **[Commitment Management](/gcp/commitment-management-setup)** -- Automated purchasing and management of GCP Committed Use Discounts (CUDs), via both an Automation Agent (service account) and the nOps Operations Team *** ## Permissions All roles below are granted to the nOps service account. ### Organization-Level Roles | Role | Role ID | Purpose | | - | - | - | | Browser | `roles/browser` | Enumerate projects and folders | | Recommender Viewer | `roles/recommender.viewer` | Read cost optimization recommendations | | Compute Viewer | `roles/compute.viewer` | Read Compute Engine data | ### Billing Account Roles | Role | Role ID | Purpose | | - | - | - | | Billing Account Viewer | `roles/billing.viewer` | Access billing metadata and currency validation | ### Dataset-Level Roles Granted on **each BigQuery dataset** containing billing export data, including the FOCUS dataset if you configured one. | Role | Role ID | Purpose | | - | - | - | | BigQuery Data Viewer | `roles/bigquery.dataViewer` | Read billing export tables | ### Project-Level Roles Granted on the project hosting your billing export datasets. | Role | Role ID | Required | Purpose | | - | - | - | - | | Service Usage Consumer | `roles/serviceusage.serviceUsageConsumer` | Yes | Run BigQuery jobs against billing data | | BigQuery Resource Viewer | `roles/bigquery.resourceViewer` | Only if using flat-rate/reservation BigQuery pricing | Read BigQuery reservation and slot information | *** ## Resources Created by nOps nOps creates a **per-client service account** (`nops-billing-sa-{clientId}@nops-billing-export.iam.gserviceaccount.com`) when you set up the integration. This service account lives in the nOps GCP project -- no infrastructure resources are created in your environment. *** ## Resources You Must Create | Resource | Details | | - | - | | **BigQuery Dataset -- Detailed Usage Cost** | Location must be US or EU | | **BigQuery Dataset -- Pricing** | Must use the same project and location as Detailed Usage Cost | | **BigQuery Dataset -- Committed Use Discounts** | Must use the same project and location as above | | **BigQuery Dataset -- FOCUS** (optional) | Created and named by Google when you enable the FOCUS export: `gcp_billing_immutable__` | > [!TIP] > > The Detailed Usage Cost and Pricing exports can share the same BigQuery dataset. The FOCUS dataset is always separate, because Google creates it for you. *** ## Required APIs Enabled on the **project that hosts your billing exports**. | API | Service ID | | - | - | | Cloud Billing API | `cloudbilling.googleapis.com` | | Recommender API | `recommender.googleapis.com` | **Optional:** | API | Service ID | When Required | | - | - | - | | BigQuery Reservation API | `bigqueryreservation.googleapis.com` | Only if using flat-rate/reservation BigQuery pricing | *** ## Domain Restricted Sharing If your GCP organization has **Domain Restricted Sharing** enabled, you must add the nOps Google Workspace Customer ID to your allowed domains list before granting IAM roles to the nOps service account. The nOps Customer ID is available in the GCP integration wizard at [Settings > Cloud Provider Integrations](https://clara.nops.io/settings). > [!NOTE] > > If your organization does not have Domain Restricted Sharing enabled, this does not apply. See [Integration Setup](/gcp/integration-setup#1-domain-restricted-sharing) for detailed instructions. *** ## Related Guides > **[Prerequisites](/gcp/prerequisites)** > > Configure billing exports and prepare your GCP environment. > **[Integration Setup](/gcp/integration-setup)** > > Link GCP billing data and grant service account permissions. > **[Commitment Management Setup](/gcp/commitment-management-setup)** > > Configure automated CUD purchasing and nOps operations team access. > **[Permissions and Resources - Commitment Management](/gcp/permissions-and-resources-cm)** > > Overview of all permissions and resources needed for Commitment Management. # Google Cloud Platform - Prerequisites Source: https://help.nops.io/gcp/prerequisites Set up billing exports and prepare your GCP environment for nOps onboarding. ## FAQs > **Why should I enable GCP Billing Exports?** > > Enabling billing exports allows you to store and analyze cost and usage data using BigQuery. This helps with tracking expenses, optimizing spending, and integrating with other cost management tools like nOps. > **Can I export billing data to multiple projects?** > > Billing data must be linked to a single BigQuery dataset per billing account. However, you can share access across multiple projects for visibility and analysis. > **Do I need to use the same location for both Pricing and Detailed Usage Cost exports?** > > Yes, both pricing and resource exports **must** be configured to use the same location (US or EU) and preferably the same dataset. Using different locations or datasets will cause integration issues with nOps. *** ## Overview Integrate your **Google Cloud Billing** data with the nOps platform for comprehensive cost tracking and analysis. This integration allows you to visualize and manage GCP spending directly within the nOps platform. > [!WARNING] > > **Currency Support:** nOps currently supports only **USD currency** for billing export data. Ensure your GCP billing account is configured to use USD currency for proper integration with the nOps platform. *** ## Administrative Prerequisites To perform this setup, the person executing the steps needs high-level privileges. If you don't have these, you'll need to coordinate with your **IAM or Cloud Governance team**. * **Organization Administrator**: Required to grant permissions at the Organization level. * **Billing Account Administrator**: Required to access the Billing Console and grant the Billing Account Viewer role. * **Project Owner**: Required to enable APIs and manage project-level IAM. * **BigQuery Admin**: Required to manage permissions on the specific datasets (Detailed Usage, Pricing, CUD, and FOCUS if enabled). * **Organization Policy Administrator**: Required only if your organization uses Domain Restricted Sharing and you need to add the nOps Customer ID to allowed domains (see [Integration Setup](/gcp/integration-setup#1-domain-restricted-sharing)) *** ## 1. Check If Billing Exports Are Already Enabled Before proceeding with the setup, check if your GCP billing exports are already configured: **1. Navigate to Billing Export** Go to the **Billing** section in the [GCP Console](https://console.cloud.google.com/billing). Select your billing account from the list. Click **Billing Export** from the left-hand menu. **2. Verify Export Status** If billing exports are already enabled, you'll see **Project name** and **Dataset name** fields populated for each export type. > [!NOTE] > > **Already Enabled?** If your billing exports are already configured with Project name and Dataset name populated for all three export types, you can skip the configuration steps below and proceed directly to [GCP Integration Setup](/gcp/integration-setup). Note the FOCUS dataset name too if that export is enabled. nOps has an optional field for it. If the exports are **not enabled** (showing as empty or disabled), continue with the configuration steps below. *** ## 2. Configure GCP Billing Exports You must enable three specific exports: **Detailed Usage Cost**, **Pricing**, and **Committed Use Discounts**. You can create the BigQuery dataset directly within the first export configuration. You can also enable the **FOCUS usage cost** export on the same page. It is optional in nOps, but it gives you cost data in the FinOps Open Cost and Usage Specification format, which is consistent across cloud providers. Google creates and names this dataset for you as `gcp_billing_immutable__` in the project you select, so it does not follow the shared-dataset guidance below. ### Select or Create a GCP Project A **Google Cloud project** is required to store billing data. If managing multiple billing accounts, configure the export for each account separately. > [!NOTE] > > For help setting up the Cloud Billing account, refer to the [Google Cloud Billing documentation](https://cloud.google.com/billing/docs). ### Enable Cloud Billing Exports to BigQuery **1. Navigate to Billing Export** Go to the **Billing** section in the [GCP Console](https://console.cloud.google.com/billing) and select **Billing Export** from the left-hand menu. **2. Configure Detailed Usage Cost Export** Click **Edit Settings** under **Detailed Usage Cost**. * Select your **Project**. * Create a **New Dataset** (e.g., `gcp_billing_exports`) or select an existing one. * Choose a location (**US** or **EU**) and click **Save**. **3. Configure Pricing Export** Click **Edit Settings** under **Pricing**. * Select the **same Project and Dataset** as above. * Click **Save**. **4. Configure Committed Use Discounts Export** Click **Edit Settings** under **Committed Use Discounts**. * Select the **same Project**. * Enter a dataset name (e.g., `cudsExportDataset`) and select the **same location** (Multi-region US or EU). * Click **Save**. **5. Configure FOCUS Export (optional)** Click **Edit Settings** under **FOCUS usage cost**. * Select the **same Project** and the **same location** (Multi-region US or EU). * Click **Save**. Google creates the dataset and table for you. You do not name them. > [!WARNING] > > **Billing Data Backfill Behavior:** When enabling Cloud Billing export to BigQuery for the first time and selecting a multi-region dataset location (EU or US), the export includes billing data **retroactively from the start of the previous month**. This historical data backfill provides immediate access to recent billing information for analysis. > > **Important**: This retroactive data population occurs **only once** during the initial setup. If the export is disabled and later re-enabled, or if the dataset is changed, the backfill will **not occur again**. Billing data will only be available from the date of re-enablement or dataset change onward. ### Important Configuration Details > [!WARNING] > > **Location Consistency:** All three exports **must** use the same location (US or EU) and preferably the same project. Using different locations will cause integration issues. * **CUD Export Status**: After creating the Committed Use Discounts export, it may initially appear as **Disabled**. Simply **refresh the page**, and it should show as **Active**. * **Table Creation**: Each export creates a separate BigQuery table with its own unique **Table ID**. These tables may take up to **48 hours** to be created. *** ## Next Steps Once your billing exports are configured and the BigQuery tables have been created (allow up to 48 hours), you're ready to connect GCP to nOps. > [!TIP] > > **Ready to connect?** Go to [nOps Settings → Cloud Provider Integrations](https://clara.nops.io/settings) and click the **Google Cloud Platform** card to start the integration wizard. For a detailed walkthrough, see the guide below. > **[Integration Setup](/gcp/integration-setup)** > > Configure Domain Restricted Sharing when required, link GCP billing data, and grant service account permissions. > **[Commitment Management Setup](/gcp/commitment-management-setup)** > > Overview of all permissions and resources needed for Savings Analysis and Commitment Management. > **[Permissions and Resources - Savings Analysis](/gcp/permissions-and-resources-sa)** > > Overview of all permissions and resources needed for Savings Analysis. > **[Permissions and Resources - Commitment Management](/gcp/permissions-and-resources-cm)** > > Overview of all permissions and resources needed for Commitment Management. # Welcome to nOps Source: https://help.nops.io/index nOps is the AI-powered cloud cost optimization platform. Explore guides, connect your cloud accounts, and get the most out of every dollar you spend in the cloud. > [!NOTE] > > New to nOps? Connect your first cloud account with an [AWS](/aws/integration-setup), [GCP](/gcp/integration-setup), or [Azure](/azure/integration-setup) onboarding guide, or start from [Integrations](/platform/integrations) for an overview. Then explore [Canvas](/clara/canvas), [Ask Clara](/clara/clara-chat), and the rest of the platform. ## Connect your cloud accounts > **[AWS](/aws/integration-setup)** > > Onboard your payer account so nOps can analyze spend, recommendations, and commitments. > **[Google Cloud](/gcp/integration-setup)** > > Connect via a service account with BigQuery access to your billing export datasets. > **[Microsoft Azure](/azure/integration-setup)** > > Connect via admin consent and a service principal with cost management and FOCUS export access. > **[All integrations](/platform/integrations)** > > Cloud providers, third-party SaaS tools, and commitment management setup in one place. ## Explore the platform > **[Canvas](/clara/canvas)** > > Build interactive dashboards with drag-and-drop widgets, AI-generated charts, and real-time data sources. > **[Ask Clara](/clara/clara-chat)** > > Chat with Clara about your cloud and AI spend, review your history, and schedule recurring questions. > **[Home page](/platform/home)** > > Choose where nOps opens when you sign in, and set a default landing page for your team. > **[Users and roles](/platform/users)** > > Invite team members, assign built-in or custom roles, and manage permissions across your organization. > **[Inform](/inform/introduction)** > > Explorer, Reports, and dashboards for cloud cost visibility: filters, saved views, and scheduled emails. > **[Commitment Inventory](/optimize/commitment-inventory)** > > View AWS, GCP, and Azure commitments and AWS utilization, included on every plan when your integrations are active. # Explorer Source: https://help.nops.io/inform/explorer Analyze cloud spend with charts, heat maps, filters, and breakdowns across dimensions. **Explorer** is the cornerstone of nOps Inform. It helps your team move from raw billing data to actionable insight so you can optimize costs, improve allocation, and make faster decisions. Explorer supports AWS and multi-cloud environments with flexible filters and granularity for both finance and engineering stakeholders. > **[Reports](/inform/reports)** > > Save views and schedule email delivery. > **[Explorer Dashboard](/inform/explorer-dashboard)** > > Combine saved reports into live dashboards. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Inform → Explorer**, or go to [clara.nops.io/explorer](https://clara.nops.io/explorer). 3. Use the filter panel to narrow your view. Results update as you change filters. 4. Save your view as a report, or open **Manage Reports** to load a saved report. ## Key features ### Filters Use the left **Filters** panel to shape what you see: * **Date range:** presets such as 7D, 30D, MTD, and YTD, or a custom range. * **Cost type:** Unblended, Amortized, Blended, List, and discounted variants (Discounted Unblended, Discounted Amortized, Discounted List). * **Usage chart:** Hide, Usage, or Normalized Usage to overlay usage trends. To see a usage overlay, select exactly one Cost Unit dimension. * **Group by:** dimensions organized by category: * Billing & Cost * Product & Services * Resource & Usage * Tags * Compute * Storage * Kubernetes — **Cluster Name** requires Split Cost Allocation Data and the AWS-generated cost allocation tag **`aws:eks:cluster-name`** (see [AWS integration setup](/aws/integration-setup#why-is-cluster-name-missing-in-kubernetes-explorer)) Click into any dimension to open its filter panel. From there you can: * **Include** or **exclude** specific values. * Use **Contain** or **Doesn't contain** to match values by substring. * For **Tags** and **Cost Allocation Tags**, choose a tag key and combine multiple keys with **AND** or **OR**. The **Selected Filters** panel on the right lists every active filter so you can review or remove them individually, or use **Clear All** to reset everything at once. Some advanced key-value filters (like Labels) may show as coming soon depending on your workspace. ### Spend summary Summary cards give you a quick read on spend: * **Yesterday's total spend:** compared to the day before. * **Month to date spend:** compared to the same period last month. * **Total spend:** for the selected date range, compared to the previous interval. Granularity affects which cards appear: | Granularity | Cards shown | | - | - | | Hourly or Daily | Yesterday, MTD, and Total | | Weekly or Monthly | MTD and Total | | Quarterly or custom ranges | Total only | If your billing data hasn't fully processed for a period yet, a card may show a "data pending" state instead of an incomplete \$0 total. ### History chart and table * Spend is shown as a bar chart; when Usage Chart is enabled, usage is overlaid as a dashed line on the same chart. * Change **Granularity** to Hourly, Daily, Weekly, Monthly, or Quarterly. * Use the chart's **Show 10 / 20 / 30 / 50 / all** control to change how many series appear before the remainder rolls up into an **Other spend** series. Use the legend to search series, or enable/disable individual series. * The **Cost Explorer Table** below gives a detailed breakdown by your selected dimension, with sorting, a name search, and server-side pagination. * When you group by Tags or Cost Allocation Tags, the table shows each tag key as an expandable row so you can drill into its values. * Use **Download CSV** on the table to export the current breakdown. ### Heat map Switch from the time-series history chart to a **heat map** when you want to compare spend across two dimensions at once, for example which services drive cost in which accounts, or how regions break down by environment tag. * Click the **grid** icon above the chart to open the heat map. The chart area shows spend as colored cells: darker cells mean higher spend for that X/Y pair. * Click **History** to return to the bar chart. * Click **Axes** (while the heat map is open) to choose the **X axis** and **Y axis** dimensions. The two axes must be different. * When you first enable the heat map, the **X axis** defaults to your current **Group by** dimension and the **Y axis** defaults to **Account name**. Change either axis anytime with **Axes**. * The heat map uses your selected **cost type**, **date range**, and **filters**. It shows the top spend combinations (up to 50 pairs) for the period you have selected. * Hover a cell to see the exact spend for that combination. * **Tag dimensions**: you can use a specific tag key (for example, `Environment`) as an axis. The generic Tags category column is not available as an axis. Pick a tag key instead. * The heat map is **not available** while a **budget overlay** is active. Switch back to **Default View** first, then open the heat map. Saved reports remember whether the heat map was enabled and which axes you chose. [Explorer Dashboard](/inform/explorer-dashboard) widgets, and scheduled emails use that saved view when the heat map is part of the report. ### Budget view If your organization uses [Budgets](/operate/budgets), you can overlay one directly on Explorer: * Open **View By** and pick a budget from the list. * Explorer applies that budget's filters and adds a target line to the chart, plus a **Budget Targets** table below it so you can compare actual spend against your plan without leaving Explorer. * Switch back to **Default View** at any time to remove the overlay. ### Saved reports From Explorer you can: * Open **Manage Reports** to search and load Private, Shared, or **nOps Global** reports. * **Save report** to store your current filters, date range, chart settings, and heat map layout (when enabled). * **Set it as your home page** so nOps opens on that report when you sign in. See [Home page](/platform/home). * **Email Explorer report** to send now or on a recurring schedule (daily, weekly, or monthly), with an optional **Include Clara AI analysis** summary for recipients. * **Create budget** directly from a saved report to start a new [Budget](/operate/budgets) using that report's dimensions. Report links use this format: `https://clara.nops.io/explorer?report={id}` For full report management, see [Reports](/inform/reports). ### Data freshness Explorer shows a **Data updated** label near the top of the page so you always know how current the numbers are. ## How Explorer compares to AWS Cost Explorer AWS Cost Explorer covers basics well. **nOps Explorer** adds: * **Richer dimensions:** group and filter across billing, product, resource, tag, and Kubernetes dimensions in one place. * **More granularity:** hourly views and flexible custom date ranges. * **Saved reports and sharing:** save views, share URLs, and email reports with PDF attachments. * **Budget overlays:** compare actual spend against a budget's target line without switching tools. * **Heat maps:** compare spend across two dimensions in one view (for example, service × account or region × tag). * **Team workflows:** private, shared, and nOps Global report libraries, plus optional Clara summaries in scheduled emails. ## Examples **Analyze costs by tag** 1. Open **Group by** and choose a tag dimension (for example, Environment). 2. Add tag filters in the Filters panel if needed. 3. Review the chart and table for spend by tag value. **Track usage trends** 1. Set **Usage chart** to Usage or Normalized Usage. 2. Pick a granularity that matches your question (hourly for intraday peaks, monthly for trends). 3. Group by the dimension that matters most (service, account, region, and so on). **Focus on a project window** 1. Choose a custom **Date range** for the project timeline. 2. Save the view as a **Private** or **Shared** report for repeat access. **Check spend against a budget** 1. Open **View By** and select a budget. 2. Compare the target line on the chart against actual spend, and use the **Budget Targets** table for period-by-period detail. **Spot high-spend combinations across two dimensions** 1. Set your **date range**, **cost type**, and any filters you need. 2. Click the **grid** icon above the chart to open the heat map. 3. Click **Axes** and pick the two dimensions you want to compare (for example, **Service** on the X axis and **Region** on the Y axis). 4. Hover cells to read exact spend, then **Save report** if you want your team to reopen the same heat map view. ## FAQs > **How does granularity affect the spend summary and chart?** > > Granularity controls which summary cards appear and how the history chart is bucketed. Hourly and daily views show Yesterday, MTD, and Total spend. Weekly and monthly views show MTD and Total only. Quarterly granularity and custom date ranges show Total spend only. > **What filters are available?** > > You can filter by date range, cost type, usage chart mode, and dimensions across billing, product, resource, tag, compute, storage, and Kubernetes categories. Each dimension supports include/exclude values, and most support Contain / Doesn't contain text matching. Filters apply as you change them. Use **Clear All** to reset. > **How do I share a report with my team?** > > Save the view as a **Shared** report, copy the report link from Explorer or the Reports page, or use **Email Explorer report** to send a one-time or scheduled email with a chart preview and PDF attachment. > **What are Private, Shared, and nOps Global reports?** > > **Private** reports are visible only to you. **Shared** reports are visible to everyone in your organization. **nOps Global** reports are pre-built templates from nOps that you can open or duplicate to customize. > **Can I compare spend against a budget in Explorer?** > > Yes. Use **View By** to pick a budget. Explorer applies that budget's filters, adds a target line to the chart, and shows a **Budget Targets** table. See [Budgets](/operate/budgets) for how to set one up. > **What is the Explorer heat map?** > > The heat map is an alternate chart view that shows spend across two dimensions at once. Each cell is one X/Y combination; color intensity reflects spend for your selected date range and filters. Use the **grid** icon to switch from the history chart, **Axes** to change dimensions, and **History** to switch back. It is saved with reports and appears in emails and dashboard widgets when enabled on the report. > **Why can't I open the heat map?** > > The heat map is disabled while a **budget overlay** is active. Open **View By** and choose **Default View** to remove the budget overlay, then click the **grid** icon again. > **How long before I see data in Explorer?** > > Data is typically available within 24 to 48 hours after your cloud integration is active. Spend reflects roughly a 24-hour delay aligned with Cost and Usage Report (CUR) processing. > **Why is Cluster Name unavailable under Kubernetes?** > > **Cluster Name** depends on the AWS-generated cost allocation tag **`aws:eks:cluster-name`** (and Split Cost Allocation Data on your Legacy CUR). If that tag is inactive or missing from the CUR, Explorer reports that Cluster Name isn't available for this account. Full prerequisite steps are in [AWS integration setup](/aws/integration-setup#why-is-cluster-name-missing-in-kubernetes-explorer). ## Related * [Home page](/platform/home): choose where nOps opens when you sign in * [Reports](/inform/reports): browse and manage all saved reports * [Explorer Dashboard](/inform/explorer-dashboard): multi-report dashboards for your team * [Budgets](/operate/budgets): set spend targets from Explorer reports and track them over time # Explorer Dashboard Source: https://help.nops.io/inform/explorer-dashboard Custom dashboards built from saved Explorer reports. **Explorer Dashboard** gives your team a flexible place to view, monitor, and analyze key cost metrics. Combine saved [Explorer reports](/inform/reports) into one live dashboard your team can revisit anytime, without rebuilding filters from scratch each week. > [!NOTE] > > In the sidebar this feature appears as **Dashboards** under Inform. You can also set any dashboard as your [home page](/platform/home#change-your-home-page), so nOps opens on it when you sign in. > **[Reports](/inform/reports)** > > Save the reports you want on a dashboard. > **[Explorer](/inform/explorer)** > > Open a linked report for full analysis. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. Open **Inform → Explorer Dashboard** (sidebar label: **Dashboards**), or go to [clara.nops.io/explorer/dashboard](https://clara.nops.io/explorer/dashboard). 3. Click **Create dashboard**, name it, and choose **Private** or **Shared**. 4. Open the dashboard and click **Add Widget** to attach saved Explorer reports. ## Dashboard list ### Tabs | Tab | Description | | - | - | | **All** | Every dashboard you can access | | **Private** | Dashboards only you can see | | **Shared** | Dashboards visible to your entire organization | | **Global** | Curated dashboards available to all nOps customers | ### Actions on the list From the dashboard list menu you can: * **Copy URL:** share a direct link to the dashboard * **Edit:** change name or visibility * **Clone:** duplicate a dashboard (optionally constrain the copy to a Cost Allocation showback and values) * **Delete:** permanently remove a dashboard Each dashboard card also shows a **category** badge alongside its visibility, so you can scan the list for the type of dashboard you're looking for. Use **Search dashboards** to filter by name. ## Create a dashboard 1. Click **Create dashboard**. 2. Enter a descriptive **name**. 3. Choose visibility: * **Private:** personal use or experiments before sharing * **Shared:** visible to everyone in your organization * **Global:** available to all nOps customers (when your role allows) 4. Save, then open the dashboard to add widgets. ## Add widgets 1. Open a dashboard and click **Add Widget**. 2. Pick a saved Explorer report from **Private**, **Shared**, or **Global** tabs (same libraries as [Reports](/inform/reports)). 3. Confirm the selection. Each widget shows the report's chart and summary cards. 4. Add multiple widgets to compare different views side by side. If you have no saved reports yet, create one in [Explorer](/inform/explorer) first. A dashboard with no widgets yet shows *You have not selected any report yet*, with a **Select Report** button if you have edit access. ## Work with widgets Each widget displays: * Summary cards (Yesterday, MTD, Total, based on the report's settings) * History chart or **heat map** for the linked report (whichever view was saved on the report) * The report name as the widget title ### Widget actions When you can edit the dashboard: | Action | What it does | | - | - | | **Open in Explorer** | Click the widget title to open the linked report at `/explorer?report={id}` | | **Edit** | Change the widget name, date range, granularity, cost type, chart view, and overlay toggles | | **View parameters** | Inspect the effective filters and timing for this widget | | **Replace report** | Swap the linked Explorer report without removing the widget | | **Refresh** | Reload this widget's data | | **Delete** | Remove the widget from the dashboard | | **Drag handle** | Reorder widgets by dragging | Anyone who can view the dashboard can open **View parameters** and **Refresh**. Drag-and-drop reordering is available when you have edit access. > [!NOTE] > > Widget **Edit** saves overrides on the dashboard widget only. The underlying Explorer report is unchanged. End dates in the future append a **forecast** (dashed bars) beyond yesterday’s last complete day. To point a widget at a different report, use **Replace report**. Each dashboard can hold up to **50** widgets. ## Share with your team * Create a **Shared** dashboard so everyone in your organization sees the same layout. * Use **Copy URL** on the dashboard list to send a direct link. * Combine with [scheduled report emails](/inform/reports#email-and-schedules) when stakeholders prefer inbox delivery over visiting a dashboard. ## Empty states | Tab | Message | | - | - | | **All** | *Combine saved Explorer reports into a live dashboard your team can revisit anytime.* | | **Private** | *Create a private dashboard to experiment before sharing with your team.* | | **Shared** | *Shared dashboards are visible to everyone in your organization.* | | **Global** | *Global dashboards can be published for all nOps customers.* | ## FAQs > **What types of dashboards are available?** > > **Private** dashboards are only for you. **Shared** dashboards are visible to your whole organization. **Global** dashboards are pre-built or published templates for all nOps customers. > **How do I add widgets?** > > Open a dashboard, click **Add Widget**, and select a saved Explorer report. You can add as many widgets as you need, then drag to reorder. > **Can I rearrange widgets?** > > Yes. Use the drag handle on each widget header to reorder the layout when you have edit access. > **What can I do from a widget?** > > Open the report in Explorer, edit the widget's name and view settings, refresh data, or delete the widget from the dashboard. To point a widget at a different report without losing its position on the dashboard, use **Replace report**. > **How do I share a dashboard?** > > Set visibility to **Shared** when creating or editing the dashboard, and use **Copy URL** to share the link with teammates. ## Related * [Reports](/inform/reports): manage saved reports used as widgets * [Explorer](/inform/explorer): deep-dive analysis for any linked report * [Home page](/platform/home): choose where nOps opens when you sign in # Insights Source: https://help.nops.io/inform/insights Cost optimization recommendations and cost anomaly detection in one place. **Insights** is where nOps surfaces cost-saving opportunities and unexpected spend changes across your cloud infrastructure. It has two tabs: **Recommendations** for ongoing optimization opportunities, and **Anomalies** for cost spikes and drops that need a closer look. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Inform → Insights**, or go to [clara.nops.io/insights](https://clara.nops.io/insights). 3. Use the tabs at the top to switch between **Recommendations** and **Anomalies**. > [!NOTE] > > The **Recommendations** page moved to **Insights**. Links and bookmarks to `/recommendations` redirect here automatically, with the Recommendations tab selected. ## Recommendations tab Recommendations helps you find and act on cost-saving opportunities across your cloud infrastructure. nOps continuously analyzes your resource usage and configurations, then surfaces actionable recommendations with estimated savings, an implementation effort level, and AI-generated guidance on how to implement each one. ### Summary cards Three cards give you an at-a-glance view of your optimization program: * **Savings Summary:** potential **Annual savings** and **Monthly savings** across all active recommendations. * **Recommendations by effort:** active recommendations grouped by implementation effort (Low, Medium, High). * **Savings achieved:** realized savings from recommendations you've already implemented, shown as current **Monthly savings** and cumulative **Saved to date**. ### Clara Insights **Clara Insights** is an AI-powered carousel at the top of the tab that automatically analyzes your recommendation data and highlights the most impactful opportunities. For example, *"You have 12 high-impact Compute recommendations worth \$5,000/month in potential savings."* * Click any insight card to instantly filter the list to matching recommendations. Click it again to remove the filter. * Use the refresh action to regenerate insights from your latest recommendation data. ### Savings History The **Savings History** chart visualizes your recommendation activity and savings over time: * Switch between **Spend** and **Count** modes to see savings amounts or recommendation counts. * Choose a time range: **Last 7 days**, **Last 30 days**, **Last 90 days**, **Last 6 months**, **Last year**, or **All time**. * Hover any point for details, including savings achieved when a recommendation was resolved. ### Recommendations list * Toggle between **Grouped** (by recommendation type) and **Flat** views. * **Search recommendations** to filter by name or resource. * Use **Filters** to narrow by **Account**, **Region**, **Effort**, **Category**, **Action**, or **Service**. * **Download CSV** to export the currently displayed rows. * Click any row to open its details. ### Recommendation details Opening a recommendation shows three tabs: * **Overview:** Monthly Savings, implementation effort, age since detection, and a **Clara Summary** explaining the opportunity in plain language. * **How to Implement:** step-by-step guidance from Clara, plus **Console & CLI** quick actions with direct links and copyable commands. * **Technical Details:** resource details and other considerations relevant to implementation. If a console link is available, use **View in AWS** to jump directly to the resource. ### Saved views and email schedules * Use **Manage Reports** to save your current filters as a view (**Private**, **Shared**, or **All**), so you and your team can return to the same slice of recommendations. * Send a saved view now, or schedule a recurring email digest, from the Recommendations tab on the [Reports](/inform/reports) page. ### Effort levels Every recommendation is scored **Low**, **Medium**, or **High** effort based on factors like whether it requires engineering validation, a resource restart, operating system or application configuration changes, or code changes. Lower effort generally means fewer coordination steps and less risk of disruption. ### Recommendation types nOps generates recommendations across a range of optimization categories, including: * **Rightsizing:** resize underutilized EC2 instances, RDS instances, or Lambda functions. * **Idle resources:** stop idle RDS instances, scale in underused Auto Scaling Groups, or remove unused Elastic Load Balancers. * **Storage:** upgrade EBS volumes (for example, GP2 to GP3), delete unused EBS volumes, enable S3 Intelligent-Tiering, or clean up old EC2 and RDS snapshots. * **Graviton migration:** move EC2 instances, RDS databases, or Auto Scaling Groups to AWS Graviton for better price-performance. * **Modernization:** upgrade EC2 instances to newer generations, switch Aurora to IO-Optimized, or move from third-party AI models to AWS Bedrock. Recommendations are refreshed regularly, so new opportunities appear as your usage patterns and cloud provider pricing change. ## Anomalies tab Anomalies helps you spot unexpected cost spikes and drops as soon as they happen, and drill into what caused them, so surprises don't wait until the end of the month to surface. ### Summary cards * **Anomalies:** the total number of anomalies in the selected date range. Click this card to clear the high severity filter and show every anomaly. * **Total impact:** the aggregate excess (or reduced) spend across all anomalies in the window. * **High severity:** the count of **Critical** or **High** severity anomalies. Click to filter the table down to just those. ### Filters * **Date range:** **Last 7 days**, **Last 30 days**, **Last 90 days** (default), or **All time**. * **High severity:** toggle from the summary card to show only Critical/High severity anomalies. ### Anomalies table Each row shows: * **Source:** which detector found the anomaly. * **Severity:** **Critical**, **High**, **Medium**, or **Low**, based on how unusual the spend pattern is. * **Start** / **End** / **Duration:** when the anomaly began, ended, and how many days it lasted. * **Cost impact:** the estimated excess spend (or savings, shown as a decrease) caused by the anomaly. * **Impact %:** how much the anomaly changed spend relative to the expected baseline. * **Trend:** a sparkline showing the spend pattern around the anomaly. * **Service:** the affected AWS service, plus a short plain-language summary of the anomaly. * **Root causes:** click to expand and see the specific accounts, regions, and usage types driving the anomaly. ### Root cause details Expanding a row's root causes shows a ranked list of contributors, each with: * The account, region, and usage type or charge type responsible. * A contribution bar showing that cause's share of the total impact. * The dollar impact of that specific cause. * An **Explorer** button that opens [Explorer](/inform/explorer) pre-filtered to that anomaly's date range, service, and root cause, so you can dig deeper into the underlying usage. ### Send and schedule anomaly reports Use **Manage reports** to deliver the current anomaly view to your team: * **Send now:** deliver immediately to email addresses, Slack channels, or Microsoft Teams channels. * **Schedule:** set up a recurring digest (daily, weekly, or monthly) so your team gets anomaly updates automatically. * Both options carry over the selected **date range** and **high severity** filter, and let you customize the subject and add a note. ## FAQs > **Who has access to Insights?** > > Insights is available to any organization with the Recommendations feature enabled on their account. > **What happened to the Recommendations page?** > > Recommendations moved into Insights as a tab, alongside the new Anomalies tab. The sidebar item is now called **Insights**, and old `/recommendations` links redirect automatically. > **How is Savings Achieved calculated?** > > Savings Achieved tracks the estimated monthly savings from recommendations marked as resolved. As you implement recommendations, the system accumulates their estimated monthly savings into your realized totals over time. > **How accurate are the estimated savings?** > > Estimates are based on your current usage patterns and cloud provider pricing. Actual savings may vary with changes in usage, price changes, or implementation specifics. > **Can I share recommendations or anomaly reports with my team?** > > Yes. For recommendations, save a filtered view from **Manage Reports**, download the current list as a **CSV**, or set up a recurring email schedule from the [Reports](/inform/reports) page. For anomalies, use **Manage reports** on the Anomalies tab to send or schedule a digest to email, Slack, or Teams. > **How do I prioritize which recommendations to implement first?** > > Use **Clara Insights** to quickly spot the highest-impact opportunities, or sort your priorities by savings potential and effort level using the Filters panel. > **How often are recommendations and anomalies updated?** > > Both refresh regularly to reflect the latest data from your cloud environment, so you always see current optimization opportunities and recent spend changes. ## Related * [Reports](/inform/reports): saved recommendation views and email schedules * [Home page](/platform/home): choose where nOps opens when you sign in * [Explorer](/inform/explorer): analyze the cost impact of a recommendation or anomaly root cause in more detail # Inform Source: https://help.nops.io/inform/introduction Real-time cloud cost visibility for finance and engineering teams. # nOps Inform nOps Inform gives you real-time visibility into costs and usage across teams, applications, and business units, without spreadsheets or manual exports. Get answers quickly, reduce billing surprises, and manage cloud spend with confidence. ## What Inform includes * **Integrations:** Connect AWS, Azure, GCP, Kubernetes, and more. nOps normalizes billing data into a unified view. * **[Explorer](/inform/explorer):** Find exactly what you need with rich filters and dimensions built for finance and engineering. Surface hidden costs before they grow, including **heat maps** that compare spend across two dimensions at once. * **[Reports](/inform/reports):** Save Explorer views, share them with your team, and schedule email delivery with chart previews and PDF attachments. * **[Explorer Dashboard](/inform/explorer-dashboard):** Combine saved reports into dashboards your team can revisit anytime. * **[Insights](/inform/insights):** AI-assisted cost-saving recommendations and cost anomaly detection, with estimated savings, effort levels, root-cause detail, and step-by-step implementation guidance. * **[MAP Manager](/inform/map-manager):** Track and tag resources for your AWS Migration Acceleration Program (MAP) contracts so you capture every credit you're owed. * **[Home page](/platform/home):** Choose where nOps opens when you sign in, such as Anomalies or a saved Explorer dashboard. Once you're ready to set spend targets, see **[Budgets](/operate/budgets)** under Operate. Budgets are built directly from your Explorer reports. Cost Allocation and shared-cost rules are also part of the broader Inform platform. Spend on AI tools like Claude, Cursor, and ChatGPT has its own area in the sidebar under **AI**, with per-seat tracking, allocation, budgets, and limit requests. See **[AI](/ai/introduction)**. ## Who Inform helps ### FinOps practitioners * **Granular cost tracking:** Drill into detailed data for optimization decisions. * **Organized reporting:** Use saved reports and dashboards for trend analysis and stakeholder updates. * **Single view:** See spend across clouds and connected services in one place. ### Engineers and managers * **Operational decisions:** Use actionable spend data to improve workflows and resource use. * **Team visibility:** Share reports and dashboards so each group sees relevant costs. * **Faster answers:** Start from [Explorer](https://clara.nops.io/explorer) or ask Clara in Canvas without exporting to spreadsheets. ## Get started 1. Sign in at [clara.nops.io/dashboard](https://clara.nops.io/dashboard). 2. Confirm your integrations under **Settings → Account Status**, and fix any that need attention. 3. Open **[Explorer](https://clara.nops.io/explorer)** to analyze spend by service, account, tag, or other dimensions. 4. **Save a report** when you have a view worth keeping. 5. Build an **[Explorer Dashboard](https://clara.nops.io/explorer/dashboard)** from saved reports, then [set it as your home page](/platform/home#change-your-home-page). ## Feature guide | Feature | Sidebar location | Best for | | - | - | - | | [Home page](/platform/home) | Home (top of sidebar) | Opening nOps on the page you check most | | [Explorer](/inform/explorer) | Inform → Explorer | Ad-hoc analysis, filters, charts, and tables | | [Insights](/inform/insights) | Inform → Insights | Finding and tracking cost-saving opportunities, and reviewing cost anomalies | | [MAP Manager](/inform/map-manager) | Inform → MAP Manager (AWS integration required) | Tagging and tracking AWS MAP migration credits | | [Reports](/inform/reports) | Inform → Reports | Managing saved views, recommendation schedules, and budget alerts | | [Explorer Dashboard](/inform/explorer-dashboard) | Inform → Dashboards | Team-facing multi-report layouts | | [Budgets](/operate/budgets) | Operate → Budgets | Setting and tracking spend targets from Explorer reports | ## Typical workflows **Daily standup** Start on your [home page](/platform/home) → open **Explorer** if something looks off → share a **Report** link with your team. **Monthly business review** Build an [Explorer Dashboard](/inform/explorer-dashboard) with your standard reports → set [scheduled emails](/inform/reports#email-and-schedules) for finance stakeholders. **Investigate a spike** Open [Explorer](/inform/explorer) → narrow date range → group by service or account → save as a **Private** report while you investigate → **Share** when ready. **Optimize and set guardrails** Check [Insights](/inform/insights) for savings opportunities and cost anomalies → implement or override each recommendation → create a [Budget](/operate/budgets) from your key Explorer reports → add email alerts so you know before you go over. ## FAQs > **How do I get started with Inform?** > > Log in at clara.nops.io, connect your cloud accounts in Settings, then open Explorer from the Inform section of the sidebar. Data usually appears within 24 to 48 hours after integration is active. > **What reports can I create?** > > Any Explorer view can become a report: cost trends, usage breakdowns by tag or service, and custom date ranges. Use nOps Global templates as starting points and duplicate them for your org. > **How long before I see data in Explorer?** > > Typically 24 to 48 hours after your integration is active. Spend reflects roughly a 24-hour delay aligned with Cost and Usage Report processing. > **What is the difference between Reports and Explorer Dashboard?** > > **Reports** are individual saved Explorer views. **Explorer Dashboard** displays multiple reports as widgets on one page for ongoing monitoring. > **Can I choose which page nOps opens when I sign in?** > > Yes. Use the cog next to **Home** in the sidebar to pick a page, saved report, cost allocation, or Explorer dashboard. Admins can also set a default for the whole organization. See [Home page](/platform/home). > **How do Insights and Budgets relate to Explorer?** > > Insights surfaces optimization recommendations and cost anomalies independently of Explorer. Budgets, on the other hand, are built directly from an Explorer report, so a budget always shares that report's filters and dimensions. ## Next steps > **[Explorer](/inform/explorer)** > > Analyze spend with filters and group-by dimensions. > **[Insights](/inform/insights)** > > Find and track cost-saving opportunities and cost anomalies. > **[AI](/ai/introduction)** > > Track AI seat spend, allocation, budgets, and limit requests. > **[MAP Manager](/inform/map-manager)** > > Tag and track AWS MAP migration credits. > **[Reports](/inform/reports)** > > Save views and schedule email delivery. > **[Explorer Dashboard](/inform/explorer-dashboard)** > > Build team dashboards from saved reports. > **[Budgets](/operate/budgets)** > > Set spend targets and get alerted on overruns. > **[Home page](/platform/home)** > > Choose where nOps opens when you sign in. Need help? Use **Help & Support** in the sidebar to chat with support, email [support@nops.io](mailto:support@nops.io), or browse this documentation. # MAP Manager Source: https://help.nops.io/inform/map-manager Track and tag AWS Migration Acceleration Program (MAP) resources to maximize your credits. **MAP Manager** helps you track and tag resources for your [AWS Migration Acceleration Program (MAP)](https://www.nops.io/aws-map/) contracts. Getting AWS MAP credits depends on tagging migrated resources correctly and as early as possible. MAP Manager centralizes that tracking and tagging so you don't lose out on earned benefits. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. Connect an **active AWS integration** in Settings if you have not already. MAP Manager appears in the sidebar only when AWS is connected. 3. In the sidebar, open **Inform → MAP Manager**, or go to [clara.nops.io/map-manager](https://clara.nops.io/map-manager). 4. Click **Create MAP Project** to register a MAP migration contract, or open an existing project to track and tag its resources. ## Key features ### AWS MAP Projects Summary The landing page shows: * **MAP Tagged Spend** and **Benefits Realized** summary cards. * **Current MAP Status:** a bar chart comparing tagged vs. untagged resource spend. * **List of MAP Contracts:** every MAP project you've created, with actions to open, edit, or delete. ### Creating a MAP project Click **Create MAP Project** and fill in: | Field | Notes | | - | - | | **MAP ID** | Your AWS MAP contract's project ID. | | **MAP Name** | A name meaningful to your team. | | **Start Date** / **End Date** | Per your MAP contract terms. Credit Period End Date is calculated automatically. | | **Max Credit** | Your contract's maximum credit cap. | | **Target Spending** | Your contract's target spending amount. | | **Credit %** (Standard MAP) | Your discount percentage for standard MAP resources. | | **Tag Key / Tag Value** | The exact tag value string from your AWS contract, used to identify migrated resources. | | **Windows optimization** | Yes/No, if your contract includes this incentive. | | **MAP Optimizations** | Additional entity types your contract covers (for example, Commercial DB\&A or Private Equity), each with its own Credit % and tag settings. | | **Filter Selection** | Optionally scope the project to specific AWS accounts, regions, or AWS services. Leave blank to include all. | Creating a project only registers what to track. It doesn't tag any resources for you. ### Project detail Opening a project shows: * **View By:** switch between **Standard** and any additional entity types enabled for the project (for example, Windows Optimization). * **MAP Tracker:** a table of your incentive credits over the migration period. * **Current QTD Tagging Status:** a bar chart of tagged vs. untagged resource spend for the current quarter. * **List of Resources:** every resource tied to the project, grouped by AWS service. ### Tagging resources To tag untagged resources for MAP credit: 1. In **List of Resources**, use the **Tagged / Untagged** toggle to view untagged resources, and filter by account or region if needed. 2. Expand a service to see individual resources, and select the ones you want to tag. 3. Click **Add Migration Tag**, then **Tag Now** for the account/region group you want to tag. 4. Confirm **Yes, tag resources**. This opens **AWS Systems Manager** in a new browser tab (or multiple tabs for large batches) with the tag key, value, and resource ARN pre-filled. Tagging happens in AWS, not automatically in nOps. You'll need access to the account and permission to use Systems Manager to complete the tag. Once tagged in AWS, it takes about a day for nOps to reflect the change. Use **Download CSV** to export the current list of resources (tagged or untagged) for offline review. ## FAQs > **Does creating a MAP project automatically tag resources?** > > No. Creating a project only registers what to track. You tag resources yourself from the project's **List of Resources**, which redirects you to AWS Systems Manager to apply the tag. > **Why don't the numbers in nOps match AWS?** > > Check that your map-migrated tag key is set as an active Cost Allocation Tag, confirm the tagging dates line up, and use Explorer's tag filters to verify the tag was actually applied. > **What permissions do I need to tag resources?** > > You need access to the AWS account the resources reside in, plus permission to use AWS Systems Manager to tag them. Ask your AWS admin if you're missing access. > **How long after tagging in AWS does nOps update?** > > Typically about a day after you tag a resource in AWS, the change is reflected in MAP Manager. ## Related * [Explorer](/inform/explorer): verify tag application with the tag filters and Group by * [Home page](/platform/home): choose where nOps opens when you sign in # Reports Source: https://help.nops.io/inform/reports Browse, manage, and schedule saved Explorer reports, recommendation schedules, and budget alerts. The **Reports** page is your central hub for everything you've saved and scheduled across nOps: Explorer reports, recommendation report schedules, and budget alerts. Each source keeps its own tab so you can manage it without leaving the page. > **[Explorer](/inform/explorer)** > > Create and refine reports from your current analysis. > **[Explorer Dashboard](/inform/explorer-dashboard)** > > Add saved reports as dashboard widgets. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. Open **Inform → Reports**, or go to [clara.nops.io/reports](https://clara.nops.io/reports). 3. Choose a source tab at the top: **Explorer**, **Recommendations**, **Budgets**, **Inventory**, or **Commitment Analysis** (when available). 4. Within the Explorer tab, browse scope tabs **All**, **Private**, **Shared**, or **Global** (nOps Global templates). Click a report name to open it in Explorer, or use **Create Report** to start from a blank view. ## Source tabs | Tab | What it shows | Header action | | - | - | - | | **Explorer** | Saved Explorer reports across your organization | **Create Report** → opens Explorer | | **Recommendations** | Saved recommendation views and their email schedules | **Open Recommendations** | | **Budgets** | Budget threshold alerts across all your budgets | **Open Budgets** | | **Inventory** | Scheduled emails for [Commitment Inventory](/optimize/commitment-inventory) filter views | **Open Inventory** | | **Commitment Analysis** | Scheduled emails for the Commitment Management overview (when enabled for your org) | **Open Commitment Management** | | **Business Unit Economics** | Scheduled emails for your saved [Business Unit Economics](/operate/business-unit-economics) unit models | **Open Business Unit Economics** | The Budgets tab only appears if you have access to Budgets. The Inventory and Commitment Analysis tabs appear for users who can access Commitment Inventory or Commitment Management, respectively. The Business Unit Economics tab appears if you have access to that feature. Viewing Inventory itself does not require Inform; scheduling inventory emails from Inventory or managing those schedules here does. ### Explorer tab | Scope | Who can see it | Best for | | - | - | - | | **All** | Everyone in your org (combined list) | Finding any report quickly | | **Private** | Only you | Personal analysis and drafts | | **Shared** | Everyone in your organization | Team standards and collaboration | | **Global** | All nOps customers (curated templates) | Starting from proven report setups | The list shows **Report name**, **Created by**, **View type** (Cost, or Cost & Usage), **Date range**, **Granularity** (Hourly through Quarterly), **Scheduling** (email schedule summary, if configured), and **Actions**. Use the search box to filter by name. Each tab shows **25 reports per page**. Row actions (icon buttons): **Copy link**, **Clone**, **Create budget**, **Edit**, **Delete**, plus the scheduling cell to manage email delivery. ### Recommendations tab Shows your saved recommendation views (**All**, **Private**, **Shared** scope tabs; there's no Global tab here) alongside their email schedules, grouped together. Search by report or schedule name. Open a saved view to jump back into the Recommendations tab of [Insights](/inform/insights) with its filters applied, or delete a view you no longer need. ### Budgets tab Lists every budget alert across your organization in one place. No need to open each budget individually. Columns include the **budget**, its linked **Explorer report**, the **alert rule** (threshold type and value), **recipients**, and **status** (never triggered, or last triggered date). Use **Open Budgets** to manage a budget's alerts directly, or see [Budgets](/operate/budgets) for how alerts work. ## Create a custom report 1. Open [Explorer](https://clara.nops.io/explorer) and set filters, date range, group-by, cost type, and granularity. 2. Optionally switch to the **heat map** view and configure **Axes** if you want the saved report to open in that layout. 3. Click **Save report** (or use **Manage Reports → Create new**). 4. Enter a name and choose **Private** or **Shared**. 5. Optionally enable **nOps Global** if your role allows publishing templates for all nOps customers. To customize a global template, open it from the **Global** tab and use **Clone**. ## Open and edit a report * Click the report name to open it in Explorer at `https://clara.nops.io/explorer?report={id}`. * Adjust filters in Explorer, then overwrite the existing report or save it as a new one. * Use **Edit** on the Reports page to rename or change visibility, date range, or granularity. To change filters or group-by, open the report in Explorer. ## Email and schedules From Explorer or the Reports list, open the scheduling cell or click the mail icon to send or schedule the current report: * **Send now:** delivers immediately with a chart preview and PDF attachment. If the report was saved with the **heat map** enabled, the email shows the heat map instead of the history chart. * **Schedule:** daily, weekly, or monthly delivery in your chosen timezone. * **Subject** and optional **Message** for recipients. * **Include Clara AI analysis:** Clara adds a short summary of shifts and anomalies when the email is sent. * **Recipients:** search and select multiple organization members, or type an email address manually to add it to the list. Add or remove as many recipients as you need before sending or saving a schedule. Recipients must be members of your organization with a Clara account, and they must already have access to the report (for example, a **Private** report can only be sent to its creator). You can't send Explorer report emails to outside addresses that aren't part of your organization. Recommendation report schedules work the same way from the Recommendations tab. **Inventory** schedules mirror the filters saved from [Commitment Inventory](/optimize/commitment-inventory). Open Inventory to send or schedule, then manage recurring deliveries from the **Inventory** tab here. Budget alerts are threshold-triggered notifications rather than scheduled digests. See [Budgets](/operate/budgets) for the difference between a budget's email alerts and its email report digest. ## Manage reports | Action | When to use it | | - | - | | **Copy link** | Copy the report's URL to share directly with a teammate who has access | | **Clone** | Copy a report, especially a Global template you want to customize | | **Create budget** | Start a new [Budget](/operate/budgets) using this report's dimensions | | **Edit** | Change name, visibility, date range, or granularity | | **Delete** | Remove a report you no longer need | > [!TIP] > > To open nOps on a saved report when you sign in, set it as your [home page](/platform/home#change-your-home-page). ## Pre-built nOps Global reports Global reports ship with predefined filters for common scenarios. Examples include: | Report | Practical use | Typical period | Granularity | Group by | | - | - | - | - | - | | RDS Purchase Type Coverage | RDS costs by purchase type | Last 30 days | Hourly | Purchase Type | | CloudWatch Breakdown | CloudWatch service costs | Last 30 days | Daily | Product Services Subtype | | AWS Marketplace | Marketplace spend | Year to date | Monthly | Cost Entity Name | | OpenSearch Purchase Type | OpenSearch by purchase type | Last 30 days | Hourly | Purchase Type | | Compute Purchase Type | RI, SP, On-Demand, Spot mix | Last 30 days | Hourly | Purchase Type | | Public IPv4 | Public IPv4 usage costs | Year to date | Daily | Product Service | | NAT Gateway - Data | NAT data transfer costs | Last 30 days | Hourly | Region Name | | NAT Gateway - Hours | NAT operational costs | Last 30 days | Daily | Region Name | | Data Transfer Service | Data transfer spend | Last 30 days | Daily | Product Services | | S3 Breakdown | S3 usage costs | Last 30 days | Daily | Product Services Subtype | | Data Transfer Operation | Operational transfer costs | Last 30 days | Daily | Operation | | Extended Support Services | Extended support charges | Last 30 days | Daily | Product Services | Open any Global report, then clone and adjust filters for your organization. ## Empty states If you have no reports yet: * **Explorer → All:** *Create a report in Explorer to save your filters, date range, and chart settings for quick access.* * **Explorer → Private:** *Save an Explorer view as a private report to keep it visible only to you.* * **Explorer → Shared:** *Shared reports are visible to everyone in your organization.* * **Explorer → Global:** *Global reports are curated templates available to all nOps customers.* * **Recommendations:** *Save a view from Recommendations, or set up an email schedule, to see it here.* * **Budgets:** *Set up an alert on a budget to see it listed here.* * **Business Unit Economics:** *Open Business Unit Economics and use Manage Reports to send or schedule unit economics reports.* ## FAQs > **How can Group by help me find trends?** > > Group by segments costs by dimensions such as Purchase Type, Region, or Product Services Subtype. For example, grouping Compute spend by Purchase Type shows how much comes from On-Demand, Reserved, Savings Plans, or Spot, surfacing optimization opportunities. > **How do shared and private reports differ?** > > Shared reports appear for everyone in your organization. Private reports stay with you unless you clone them as Shared or share a direct link with someone who has access. > **What role does granularity play?** > > Granularity sets the time bucket in the chart and table. Hourly helps with intraday peaks; daily and weekly balance detail and readability; monthly and quarterly highlight longer trends. > **Which global reports help with data transfer costs?** > > Look at **NAT Gateway - Data**, **Public IPv4**, and **Data Transfer Service** to see which regions, operations, or services drive transfer spend. > **What's the difference between the Recommendations tab and the Budgets tab here?** > > The **Recommendations** tab manages saved recommendation views and their scheduled emails. The **Budgets** tab is a read-only, org-wide list of budget threshold alerts. Open **Budgets** to create or edit an alert. > **Can I open nOps on one of my reports?** > > Yes. Use the cog next to **Home** in the sidebar and choose a saved report under **Explorer**. See [Home page](/platform/home). ## Related * [Explorer](/inform/explorer): build and refine report views * [Insights](/inform/insights): cost optimization recommendations and cost anomaly detection * [Budgets](/operate/budgets): spend targets and alerts * [Explorer Dashboard](/inform/explorer-dashboard): display reports on a shared dashboard * [Home page](/platform/home): choose where nOps opens when you sign in # Amazon Bedrock Source: https://help.nops.io/integrations/amazon-bedrock Connect Bedrock Model Invocation Logs to nOps Inform ## Overview nOps reads **Amazon Bedrock Model Invocation Logs** from AWS (via S3 large data delivery) to show AI model usage and cost in Inform. In nOps you provide the **S3 bucket** (and optional **prefix**) for each Bedrock log destination. You can connect **multiple** S3 destinations when Bedrock logs are split across buckets or prefixes. This step stores references only. It does not deploy CloudFormation in your account. Complete AWS-side logging and IAM setup first, then connect in nOps. ## Prerequisites * An AWS account with Amazon Bedrock enabled * Permission to enable **Model invocation logging** in Bedrock and configure S3 delivery * An existing **nOps AWS cloud integration** in the account that receives Bedrock logs (see [AWS integration setup](/aws/integration-setup)) * Permission to update the `nOpsBucketPolicy` on your `nops-integration-role` IAM role for S3 read access * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Step 1: Enable Model Invocation Logs in Bedrock 1. Sign in to the [AWS Management Console](https://console.aws.amazon.com) and open [Amazon Bedrock](https://console.aws.amazon.com/bedrock/) in the target region. 2. Go to **Settings** under **Configure and learn**. 3. Enable **Model invocation logging** and choose which data types to log. > [!WARNING] > > Message content can be sensitive. Disable **Text** in logging options if you do not want message bodies in logs. 4. Configure **S3 location:** bucket and prefix (for example `s3://your-bucket/bedrock/`). 5. Use an IAM role that allows Bedrock to write to that bucket and **Save settings**. 6. Optionally invoke a model once and confirm objects appear under the prefix. > [!NOTE] > > Logs capture usage from enablement forward only, not historical usage before logging was turned on. ## Step 2: Grant nOps S3 read access During AWS onboarding, nOps creates a cross-account role named **`nops-integration-role`** (or **`nops-integration-role-`**) with a customer-managed **`nOpsBucketPolicy`** for S3 access. Update that policy in the account that holds the Bedrock log bucket to allow read access to your prefix, for example: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::YOUR_BUCKET", "Condition": { "StringLike": { "s3:prefix": ["YOUR_PREFIX/*"] } } } ``` ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "Effect": "Allow", "Action": ["s3:GetObject"], "Resource": "arn:aws:s3:::YOUR_BUCKET/YOUR_PREFIX/*" } ``` Replace `YOUR_BUCKET` and `YOUR_PREFIX` with your Bedrock log destination. Use the payer or child account where the role and bucket live, consistent with your existing AWS integration. See [AWS Permissions & Resources](/aws/permissions-and-resources) for the full `nOpsBucketPolicy` reference. > [!NOTE] > > nOps does not train on Model Invocation Log content and does not expose message bodies in the product. ## Connect in nOps ### Where to open Amazon Bedrock * **To connect for the first time:** go to **Settings → Integrations** and click the **Amazon Bedrock** card. * **To manage existing connections:** open the same card or use **Settings → Account Status → Connected apps** and click the **Amazon Bedrock** chip. ### Connect steps 1. Click the **Amazon Bedrock** card or chip. 2. Click **Add integration**. 3. Enter the **S3 bucket** (and optional **prefix**) using one of these formats: * `my-bucket` * `s3://my-bucket` * `s3://my-bucket/prefix` 4. Click **Add**. Repeat steps 2–4 for each additional S3 destination. nOps stores these references without a live API check. Ensure AWS logging and IAM access are correct before connecting. > [!NOTE] > > New Amazon Bedrock integrations accept **S3 destinations only**. If you previously connected a legacy CloudWatch log group, you can still edit that value on the existing integration, but new connections must use S3. ## Manage your connections Administrators can **add**, **edit**, **re-validate**, or **remove** individual Bedrock integrations from the Amazon Bedrock modal. If data does not appear, fix Bedrock logging or S3/IAM permissions in AWS first, then update the stored S3 bucket or prefix path if the destination changed. ## Troubleshooting * **No data after 24–48 hours:** confirm Bedrock is writing to the S3 prefix, the nOps IAM role can `s3:GetObject` on that prefix, and the prefix in nOps matches exactly. * **Wrong account:** Bedrock logs, the S3 bucket, and the `nops-integration-role` must align with your nOps AWS integration account. * **Sensitive data:** exclude text logging in Bedrock if policy requires it. * **Invalid bucket format:** use a valid bucket name or `s3://` URI as shown above. Paths like `my-bucket/prefix` without the `s3://` prefix are not accepted unless the value is a bare bucket name. ## Security Model invocation logs may contain sensitive prompts and responses. Restrict S3 bucket policies and logging options to your compliance requirements. # Anthropic (Platform) Source: https://help.nops.io/integrations/anthropic Connect Anthropic Console Admin API credentials to nOps Inform ## Overview nOps uses your **Anthropic Admin API key** and an **API key name** to bring Claude Platform (Console) usage and billing into Inform. Credentials are stored securely, validated before save, and are not shown again after you connect. > [!NOTE] > > This integration is for **Claude Platform / Console** (programmatic API usage) only. If your organization uses **Claude Enterprise** (claude.ai seats), see [Claude.ai (Enterprise)](/integrations/claude-enterprise) instead. The two credential types are **not** interchangeable. A Console Admin key is rejected by the Enterprise endpoints, and an Enterprise Analytics key cannot call the Console Admin API. ## Prerequisites * Anthropic account with permission to create **Admin API keys** * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create an Anthropic Admin API key 1. Sign in to the [Anthropic Console](https://console.anthropic.com). 2. Open [Admin API keys](https://console.anthropic.com/settings/admin-keys). 3. Click **Create new Admin Key**. 4. Enter a descriptive name (for example `nOps Integration`). 5. Copy the Admin API key immediately. It is typically shown only once. > [!WARNING] > > Do not share the Admin API key or expose it in public repositories. Generate a new key and reconnect if it is compromised. ## Connect in nOps ### Where to open Anthropic (Platform) * **To connect for the first time:** go to **Settings → Integrations** and click the **Anthropic (Platform)** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Anthropic (Platform)** chip to re-validate or disconnect. ### Connect steps 1. Click the **Anthropic (Platform)** card or chip. 2. Enter an **API key name** and paste the **Admin API key**. 3. Click **Connect**. nOps validates the key with Anthropic before storing it. ## Manage your connection Administrators can **Re-validate** or **Disconnect** from the connected modal. **Action required** means validation failed. Confirm the key is still active in Anthropic and reconnect if needed. ## Troubleshooting * **Invalid key:** confirm you used an **Admin API key**, not a standard API key. * **No data:** allow up to **24 hours** after connect; confirm billing activity in Anthropic. * **Multiple accounts:** repeat connect with a unique **API key name** per Anthropic organization. ## Security Follow your organization's key rotation policy. Update nOps before rotating keys in Anthropic to avoid sync gaps. # Atlassian Source: https://help.nops.io/integrations/atlassian Connect Atlassian organization API key to nOps ## Overview nOps uses an **unscoped Atlassian organization Admin API key** (plus an **API key name** and optional **expiration date**) to track usage and user activity in Inform. The key is stored securely, validated before save, and is not shown again after you connect. ## Prerequisites * **Organization Admin** access in Atlassian (`admin.atlassian.com`) * **Centralized User Management** enabled (legacy user management is not supported) * Permission to create **API keys without scopes** * nOps organization **administrator** access > [!WARNING] > > This integration requires **Organization Admin** permissions. Scoped API keys and limited admin roles will not work. > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect in nOps. **Members** see **Admin Only** on connectable cards. ## Create an Atlassian API key 1. Sign in to [Atlassian Administration](https://admin.atlassian.com) with Organization Admin privileges. 2. Go to **Settings → API keys**. 3. Click **Create API key**. 4. Enter a name (for example `nOps Integration`). 5. Select **API keys without scopes**. Required for organization Admin API endpoints (`/admin/v1/orgs`, user directories, and activity data). 6. Set an expiration date (maximum one year) and create the key. 7. Copy the API key immediately. It is typically shown only once. See [Atlassian Cloud Admin Scopes](https://developer.atlassian.com/cloud/admin/scopes/) for why unscoped keys are required for these endpoints. ## Connect in nOps ### Where to open Atlassian * **To connect for the first time:** go to **Settings → Integrations** and click the **Atlassian** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Atlassian** chip to re-validate or disconnect. ### Connect steps 1. Click the **Atlassian** card or chip. 2. Enter **API key name**, paste the **API key**, and optionally set **Expiration date**. 3. Click **Connect**. nOps validates the key with the Atlassian Admin API before storing it. ## Manage your connection Administrators can **Re-validate** or **Disconnect** from the modal. Atlassian keys expire within one year. Create a new key in Atlassian before expiry and connect again, or update after rotation. ## Troubleshooting * **Invalid key:** confirm the key was created **without scopes** and your account has **Organization Admin** access. * **No data:** allow up to **24 hours**; verify centralized user management and that users have activity in Jira, Confluence, or other Atlassian products. * **Incomplete data:** ensure the admin has access to all products you expect to track. ## Security Do not share the API key or store it in public repositories. Rotate before the expiration date you set in Atlassian or in nOps. ## Reference * [Manage an organization with the admin APIs](https://support.atlassian.com/organization-administration/docs/manage-an-organization-with-the-admin-apis/) # Claude.ai (Enterprise) Source: https://help.nops.io/integrations/claude-enterprise Connect Claude Enterprise (claude.ai) Analytics API credentials to nOps Inform ## Overview nOps uses an **Analytics API key** created in **claude.ai** to bring Claude Enterprise usage and adoption data into Inform, and (when the key has the right scopes) per-user spend and seat limits into the **AI** area. Credentials are stored securely, validated before save, and are not shown again after you connect. > [!NOTE] > > This integration is for **Claude Enterprise** (claude.ai seats) only. If your organization uses > **Claude Platform / Console** (programmatic API usage), see [Anthropic > (Platform)](/integrations/anthropic) instead. The two credential types are **not** > interchangeable. An Analytics key cannot call the Console Admin API, and a Console Admin key is > rejected by the Enterprise endpoints. ## Prerequisites * Claude Enterprise organization with a member who can create an Analytics API key in claude.ai * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin > Only** on connectable cards. ## API key scopes Create one Analytics API key in **claude.ai → Organization settings → API** and grant the scopes your team needs. nOps uses the [Claude Enterprise Admin API](https://docs.anthropic.com/en/api/admin) for seat tracking and limit changes in the AI area. | Scope | Used for | Required? | | - | - | - | | **`read:analytics`** | Inform: usage and adoption visibility | **Yes** (minimum to connect) | | **`read:members`** | AI: match nOps users to Claude members by email | Required for [AI seat tracking](/ai/introduction) | | **`read:spend_limits`** | AI: per-user spend and effective seat limits | Required for AI seat tracking | | **`write:spend_limits`** | AI: set or clear per-user spend limit overrides from nOps | Optional (read-only limits if omitted) | | **`read:rbac_groups`** | Cost Allocation: **Sync from Claude** imports Claude groups and their members | Required for group sync (Admin key path) | > [!NOTE] > > **Read-only seat tracking:** grant `read:analytics`, `read:members`, and `read:spend_limits`. > **Let nOps change seat limits:** also grant `write:spend_limits`. **Sync groups from Claude:** also grant `read:rbac_groups`. You can add scopes later and **Re-validate** in nOps without > reconnecting from scratch. > [!WARNING] > > **`read:spend_limits` is not optional for seat tracking.** nOps builds the seat roster from `GET > /v1/organizations/spend_limits/effective`. Without this scope that call is rejected and no seats > are ingested, so no default allocation group is created, the setup stalls at **Cost Allocation** > with `0 seats`, and the **Budget** tab stays locked because it needs at least one allocation > group. Adding the scope and re-running setup resolves all of these together. ### Group sync scopes (Sync from Claude) The **Sync from Claude** button on the Cost Allocation tab reads your Claude groups so seats can be grouped the same way in nOps. nOps accepts either credential path and tries both: | Key type | Scopes required | Anthropic endpoints | | - | - | - | | **Admin API key** | **`read:rbac_groups`** | `/v1/organizations/rbac_groups`, `/v1/organizations/rbac_groups/{id}/members` | | **Compliance Access Key** | **`read:compliance_org_data`** and **`read:compliance_user_data`** | `/v1/compliance/groups`, `/v1/compliance/groups/{id}/members` | > [!NOTE] > > Anthropic grants **`read:rbac_groups`** only on a key created for **all linked organizations** in > the enterprise. A key scoped to a single organization cannot sync groups even when the scope is > checked. Recreate the key at the enterprise level, or use a Compliance Access Key instead. Group sync is optional and does not affect seat tracking. If you skip it, create allocation groups manually with **Add group** on the Cost Allocation tab. ### Where each feature appears in nOps | Feature | Location | | - | - | | Usage and adoption | Inform cost and analytics workflows | | Per-user AI spend and limits | The **AI** area, on a [seat tracking project](/ai/introduction) | | Inline limit edits | The seat table's **Seat limit** column (requires `write:spend_limits`) | ## Create a Claude.ai Analytics API key Claude **Enterprise** organizations do not appear in the Anthropic Console and have no Admin API keys. Their usage and adoption data comes from the **Claude Enterprise Analytics API**, which uses an **Analytics API key** created in claude.ai. 1. Sign in to [claude.ai](https://claude.ai). 2. Open **Organization settings → API**. 3. Enable public API access and **create an Analytics API key**. 4. Select scopes: * **`read:analytics`:** always required. * **`read:members`** and **`read:spend_limits`:** add these for [AI seat tracking](/ai/introduction). * **`write:spend_limits`:** add this only if you want to adjust per-user limits from nOps. * **`read:rbac_groups`:** add this to use **Sync from Claude** on the Cost Allocation tab. Create the key for **all linked organizations** in the enterprise, or Anthropic will not grant the scope. 5. Copy the key immediately and store it securely. > [!WARNING] > > Do not share the Analytics API key or expose it in public repositories. Generate a new key and > reconnect if it is compromised. ## Connect in nOps ### Where to open Claude.ai (Enterprise) * **To connect for the first time:** go to **Settings → Integrations** and click the **Claude.ai (Enterprise)** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Claude.ai (Enterprise)** chip to re-validate or disconnect. ### Connect steps 1. Click the **Claude.ai (Enterprise)** card or chip. 2. Enter an **API key name** and paste the **Analytics API key** (`sk-ant-api01-…`). 3. Click **Connect**. nOps validates the key against the Claude Enterprise Analytics API before storing it. ## Manage your connection Administrators can **Re-validate** or **Disconnect** from the connected modal. **Action required** means validation failed. Confirm the key is still active in claude.ai and reconnect if needed. ## Troubleshooting * **Invalid key:** confirm you used an **Analytics API key** created in claude.ai, not a Console Admin API key from [Anthropic (Platform)](/integrations/anthropic). * **Missing scope / permission errors:** recreate the key in claude.ai with the scopes from [API key scopes](#api-key-scopes). For seat spend and limits, include **`read:members`** and **`read:spend_limits`**. To change limits from nOps, include **`write:spend_limits`**. * **Seat tracking works but limit edits fail:** the key likely lacks **`write:spend_limits`**. Add that scope in claude.ai and **Re-validate** in nOps. * **`0 seats` on the Cost Allocation tab, and the Budget tab is locked:** the key is missing **`read:spend_limits`**, which is where the seat roster comes from. Cost allocation and budgets keep working from cloud spend; per-seat limits, seat tracking, and limit automation do not. Add the scope and **Re-validate.** nOps re-checks on the next load and the notice clears itself. To unblock the Budget tab before the key is fixed, click **Add group** on the Cost Allocation tab and create one group manually. * **Which scopes am I missing?** nOps checks each scope when you connect or re-validate a key, and again whenever a feature uses one. A notice at the top of the **AI** area names every scope your key was refused and what each one turns off. Features that do not need Claude, including cost allocation and budgets, stay available. * **"Unable to sync Claude groups with the stored key":** the key satisfies neither group-sync path. Use an Admin key with **`read:rbac_groups`** created for all linked organizations, or a Compliance Access Key with **`read:compliance_org_data`** and **`read:compliance_user_data`**. See [Group sync scopes](#group-sync-scopes-sync-from-claude). This affects only **Sync from Claude.** Seat tracking and limit edits keep working. * **Usage detail is unavailable when drilling into a seat:** limits and projections come from the provider, so they need **`read:spend_limits`**. Spend and forecast figures come from cost allocation and stay accurate regardless. * **Rate limited:** Anthropic caps Admin API requests (for example, spend limit calls) at **60 requests per minute** organization-wide. Wait a moment and retry; nOps surfaces the rate-limit response in the seat table. * **No data:** allow up to **24 hours** after connect for usage data to populate in Inform. Seat rows appear once you [create a seat tracking project](/ai/setup) with Claude Enterprise enabled. * **No account found for a seat:** nOps matches users by **email**. Confirm the nOps user email matches the Claude member email. * **Multiple organizations:** repeat connect with a unique **API key name** per Claude Enterprise organization. ## Security Follow your organization's key rotation policy. Update nOps before rotating keys in claude.ai to avoid sync gaps. ## Related * [AI](/ai/introduction): track per-seat Claude spend, limits, and requests * [Set up AI seat tracking](/ai/setup): create a seat tracking project after connecting Claude * [Anthropic (Platform)](/integrations/anthropic): separate integration for Claude Console / API usage (not claude.ai Enterprise seats) # Cloudflare Source: https://help.nops.io/integrations/cloudflare Connect a Cloudflare API token to nOps for product cost and usage visibility ## Overview nOps uses your **Cloudflare account ID** and an API token to pull product usage and contracted cost into Inform, plus zone and account usage when the token includes the analytics permissions below. The token is stored securely, validated before save, and is not shown again after you connect. Cloudflare's billable usage API covers **self-serve accounts only**. Enterprise contracts are not included yet. Connecting an Enterprise account will not produce cost data in Inform. Usage is updated **daily**. Cost appears in Inform after that sync, which can take up to **24 hours**. ## Prerequisites * A **self-serve** Cloudflare account * An API token with **Billing Read** and the [analytics permissions](#token-permissions) below * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin > Only** on connectable cards. ## Create a Cloudflare API token 1. Sign in to the [Cloudflare dashboard](https://dash.cloudflare.com). 2. Open **My Profile → API Tokens → Create Token**. 3. Choose **Create Custom Token**. 4. Add every permission in [Token permissions](#token-permissions). Include the optional rows only if you want R2 bucket or Images stats. 5. Under **Account Resources**, include the account you want nOps to read. 6. Under **Zone Resources**, include the zones you want nOps to read (or all zones). Zone permissions do nothing until a zone is included. 7. Create the token and copy it immediately. It is typically shown only once. 8. Copy your **Account ID**. It is the 32-character value in the dashboard URL (`https://dash.cloudflare.com//...`) or on the account home page. > [!WARNING] > > The token **must** include **Account → Billing → Read**. A token without that permission cannot > read billable usage, and nOps will not store it. Add the other required permissions so nOps can > see zones, requests, and account usage. ## Token permissions Create a custom token and add these permissions. ### Required | Type | Permission | Access | What nOps can see | | - | - | - | - | | Account | Billing | Read | Product usage and contracted cost (self-serve accounts) | | Account | Account Analytics | Read | Account-level usage analytics, such as R2 storage and operations | | Zone | Zone | Read | The list of zones in your account | | Zone | Analytics | Read | Requests and bandwidth per zone | ### Optional | Type | Permission | Access | What nOps can see | | - | - | - | - | | Account | Workers R2 Storage | Read | Your R2 bucket list, so nOps can attribute R2 usage. Cloudflare's read permission also allows reading stored objects; nOps only lists buckets. | | Account | Cloudflare Images (may be listed as "Images") | Read | Images storage stats (image count against your allowance). This permission can also list stored images. | ## Connect in nOps ### Where to open Cloudflare * **To connect for the first time:** go to **Settings → Integrations** (`/settings/integrations` or **View all**) and click the **Cloudflare** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Cloudflare** chip to re-validate or disconnect. ### Connect steps 1. Click the **Cloudflare** card or chip. 2. Paste your **Account ID** and **API token**, then click **Connect**. nOps checks the account ID and token against Cloudflare's billable usage API before storing them. On success, the catalog shows **Integrated** or Connected apps shows **Connected**. ## What nOps brings back After the daily sync, Inform can show: * Product name (`ServiceName` and `ServiceFamilyName`) * Charge period * Quantity * Contracted cost (`ContractedCost`) * Zone, when Cloudflare includes one (`ZoneId` / `ZoneName`) > [!NOTE] > > This API does not cover **Enterprise** contracts. If your Cloudflare account is Enterprise, the > connection will not produce cost rows in Inform. ## Manage your connection Administrators can **Re-validate** stored credentials or **Disconnect** from the same modal. **Action required** means the token was revoked or no longer has Billing Read. Fix the token in Cloudflare, then re-validate or connect again. ## Troubleshooting * **Invalid token:** confirm there are no typos and that the token is still active in Cloudflare. * **Missing Billing Read:** edit the token (or create a new one) so it includes **Account → Billing → Read**, then connect again. * **Missing zones, requests, or account usage:** add **Account Analytics**, **Zone**, and **Zone → Analytics**, and include those zones under **Zone Resources**. Add **Workers R2 Storage** or **Cloudflare Images** only if you want bucket or image stats. Then **Re-validate**. * **Wrong account ID:** use the 32-character ID from the dashboard URL or account home. It must match the account the token can read. * **No data yet:** allow up to **24 hours** after connect. Usage is refreshed once a day, and a new account may have no billable rows yet. * **Enterprise account:** self-serve usage is the only data this connection can read. Enterprise contracts are not in the billable usage API yet. * **Rate limits:** wait briefly and use **Re-validate**. ## Security Treat the API token like a password. Rotate it on a schedule, and keep the token scoped to the [permissions above](#token-permissions) on the account you want nOps to see. # Cursor Source: https://help.nops.io/integrations/cursor-admin-api Connect one or more Cursor teams to nOps using Team API keys ## Overview nOps connects to Cursor with a **Team API key**, one per Cursor team. The key powers **AI seat tracking** (per-user period-to-date spend and, on Cursor Enterprise, per-user spend limits) once you enable Cursor on a seat tracking project. Keys are validated before they are stored and are never shown again in the nOps UI. If your organization has several Cursor teams, connect each one. nOps reports on all of them together. > [!NOTE] > > A single Team API key covers everything nOps reads for that team: members, daily usage, per-event usage, and spend. It authenticates with HTTP **Basic** auth (the key as the username, no password), so there is no separate secret to supply. > [!WARNING] > > Use a **Team API key**, not an **Organization API key**. The two are different credentials: Organization API keys call `/organizations/*` routes and carry a single scope chosen from a dropdown, and they cannot call the `/teams/*` routes nOps relies on for members, usage, and spend. A Cursor organization is an aggregation layer above teams. Per-user spend limits live on the team, which is why nOps asks for a team key even on Enterprise. ## Prerequisites * A Cursor **Teams** or **Enterprise** plan with admin access to each team you want to connect * Permission to create **Team API keys** in Cursor * nOps organization **administrator** access to connect or manage the integration > [!NOTE] > > **Members** can view integration status on **Account Settings** and **Integrations**, but only **admins** (and owners) can connect, re-validate, or disconnect. Non-admins see an **Admin Only** indicator on the Cursor card. ## What nOps can do, by plan Cursor exposes per-user spend limits only on Enterprise, so what nOps can do depends on the plan of the team you connect. | | Cursor **Teams** | Cursor **Enterprise** | | - | - | - | | Per-user spend | Yes | Yes | | Per-user spend limits | Not available on the plan | Read, and written if you opt in | | Raise a limit by approving a request | No | Yes | | Automated Rebalance | No | Yes | | Key scope needed | Read-only is enough | Read-only to track; **Admin** to change limits | Read-only seats are still tracked, allocated, budgeted, and forecast in nOps. Their limits show as **Not reported** rather than as unlimited, because Cursor does not tell nOps a number. ## Create a Team API key 1. Sign in to [Cursor](https://cursor.com) with an account that has team admin privileges. 2. Open the [Cursor dashboard](https://cursor.com/dashboard) and go to **API Keys**. 3. Create a key for the team you want to connect: * **Read-only** is enough for seat spend tracking. * Choose **Admin** scope only if you want nOps to change per-user spend limits on a Cursor Enterprise team. 4. Copy the key immediately. It starts with `crsr_` and Cursor shows it only once. Repeat this for each Cursor team you plan to connect. > [!WARNING] > > Treat the Team API key like a password. Do not share it in chat, email, or source control. ## Connect in nOps Only nOps administrators can complete these steps. ### Where to open Cursor * **To connect for the first time:** go to **Settings → Integrations** (the main **Account Settings** page shows a preview of available apps; use **View all** to open the full catalog if Cursor is not in the preview) and click the **Cursor** card. * **To manage existing connections:** go to **Account Settings → Account Status → Connected apps** and click the **Cursor** chip. ### Add a team The Cursor modal lists the teams you have already connected and lets you add another. For each team: 1. **Team name:** a label so you can tell your connections apart, for example `Platform team`. One connection per Cursor team. 2. **Cursor plan:** choose **Team** or **Enterprise**. This is what tells nOps whether per-user spend limits exist at all for these seats, so pick the plan this team is actually on. 3. **Organization ID** (Enterprise only): the Cursor organization ID from your Enterprise dashboard, starting with `org_`. This is metadata that ties the connection back to your Cursor org; it is *not* an Organization API key, and nOps still uses the Team API key for all reads and writes. 4. **Manage seat limits from nOps** (Enterprise only): leave this off for read-only tracking. Turn it on to let nOps change per-user spend limits, which requires an **Admin**-scoped Team API key. 5. **Team API key:** paste the `crsr_` key for this team. 6. Click **Connect**. nOps validates the key against Cursor (`GET /teams/members`) before saving it. On success the team appears in the list, the integrations catalog card shows **Integrated**, and the card's connection count reflects how many teams you have connected. ### Add the rest of your teams Repeat **Add a team** for every Cursor team. Each connection stores its own key, plan, and limit-management setting, so a read-only Teams-plan connection can sit alongside an Enterprise connection that nOps writes to. ## Use in AI seat tracking After at least one Cursor team is connected, enable Cursor on a seat tracking project: 1. In the sidebar, open **AI**. 2. Add **Cursor** to the project's providers under **Project settings → Provider sync**. 3. Matched users show period-to-date spend and, where available, seat limits in the seat table. nOps matches seats to nOps users by **email**, because the Cursor Admin API itself joins members to spend on email. Seats whose limit nOps can change render an editable limit; everything else renders read-only, so you never get an editable field that fails on save. Removing Cursor from a project stops its seats from being tracked there. It does not disconnect the org integration. See [Set up AI seat tracking](/ai/setup) for the full workflow. ### Someone who belongs to two connected teams If the same email appears in more than one connected Cursor team, nOps **sums that person's spend** across those teams so reporting and budgets stay complete. Their limit becomes read-only, because nOps cannot tell which team's limit you meant to change. To manage such a seat's limit from nOps, change it in Cursor, or keep the person in a single connected team. ## Manage your connections Administrators can open the Cursor card or chip to work on any connected team: * **Re-validate:** checks the stored key against Cursor again without asking you to re-enter it. * **Edit:** change the label, plan, Organization ID, or limit-management setting. Leave the API key field blank to keep the current key, or paste a new key to rotate it. * **Disconnect:** removes that team's stored key and its connection. Other connected teams are unaffected. If validation fails, for example because a key was revoked in Cursor, the status changes to **Action required**. An administrator should edit that connection with a new key, or use **Re-validate** after fixing the key in Cursor. ## What nOps stores Per connected team, nOps saves the integration status and configuration (the label, plan tier, Organization ID if you supplied one, whether limit management is on, and when the team was connected and last validated) so your team can see whether each connection is active. Each Team API key is stored securely and is never shown again in the nOps UI after you connect. ## Troubleshooting ### Invalid API key * Confirm you copied the full key, starting with `crsr_`, with no leading or trailing spaces. * Ensure it is a **Team API key** from **Cursor dashboard → API Keys**, not an **Organization API key** and not a personal or user key. An Organization API key cannot call the team routes nOps uses and will fail validation. * Verify the Cursor team still has API access enabled. ### Seat limits are read-only when you expected to edit them Work through these in order: * The connection's **Cursor plan** is set to **Team**. Per-user spend limits do not exist on that plan. If the team is actually on Enterprise, edit the connection and correct the plan. * **Manage seat limits from nOps** is off. Edit the connection and turn it on. * The seat's email appears in two connected teams, so it is intentionally read-only. See [Someone who belongs to two connected teams](#someone-who-belongs-to-two-connected-teams). * Cursor refused a limit write. nOps trusts your Enterprise and limit-management settings up front, then records what Cursor actually allows the first time it tries a real write. If Cursor rejects it as unauthorized (most often because the key is Read-only rather than Admin), nOps records that and treats the connection's limits as read-only from then on. Rotate the connection to an **Admin**-scoped Team API key to restore write access. ### Action required * The stored key for that team may have been revoked or expired in Cursor. Create a new Team API key and edit the connection, or use **Re-validate** after updating the key in Cursor. * Only nOps administrators can resolve this status. ### Admin Only on the card * You are signed in as a **member**, not an administrator. Ask an org admin to connect or manage Cursor, or request the administrator role in nOps. ### No account found for a seat * nOps matches nOps users to Cursor members by **email**. Confirm emails match, or show unmatched users in the seat table. * If the person is in a Cursor team you have not connected yet, add that team. ### A seat's limit shows "Not reported" Cursor returned no limit for that seat. This is expected on a Cursor Teams plan, which has no per-user limits. It does not mean the seat is uncapped. ### Rate limited Cursor limits Admin API requests per team. If you see a rate-limit error, wait a minute and try again. Connecting more teams does not consume a single shared budget. Each team's key is rate limited by Cursor separately. ### Still stuck? Contact your nOps administrator or nOps support with the time of the error (not the API key itself). ## Reference * [AI](/ai/introduction): track per-seat Cursor spend, limits, and requests * [Set up AI seat tracking](/ai/setup): create a seat tracking project after connecting Cursor * [Automated Rebalance](/ai/automated-rebalance): unattended limit changes, available for Cursor Enterprise connections with limit management enabled * [Cursor Admin API](https://cursor.com/docs/account/teams/admin-api) * [Cursor Organization API](https://cursor.com/docs/account/organizations/organization-admin-api): the org-level API nOps does *not* use * [Cursor API overview (authentication)](https://cursor.com/docs/api) # Databricks Source: https://help.nops.io/integrations/databricks Export Databricks system-table billing data to S3 for nOps Inform ## Overview nOps reads **Databricks billing data** from `system.billing.usage` and `system.billing.list_prices`, plus compute configuration, utilisation and query metadata used for Databricks recommendations, after you export those system tables to S3. Databricks is an **export-only** Settings integration: you choose an S3 destination in nOps, deploy a prefix-scoped read-only role, then import and schedule a generated notebook in your Databricks workspace. nOps does **not** create or run Databricks jobs, and does **not** collect a workspace URL, SQL warehouse ID, or machine credential. You can connect **one** AWS Databricks export per organization. Azure Databricks export is not available yet. ## Prerequisites * nOps organization **administrator** or **owner** access * Permission to deploy CloudFormation (including IAM roles) in the AWS account that holds the export bucket * Administrative access to a Databricks workspace so you can import a notebook, grant S3 write (for example a Unity Catalog external location), and schedule a daily job * Either permission for CloudFormation to create a new S3 bucket, or an existing bucket in the same AWS account (or separately grant that account access) > [!NOTE] > > Only **admins** and **owners** can connect, view instructions, or disconnect. **Members** see **Admin Only** on connectable cards. ## Connect in nOps ### Where to open Databricks * **To connect for the first time:** go to **Settings → Integrations** and click the **Databricks** card. * **To manage an existing export:** open the same card or use **Settings → Account Status → Connected apps** and click the **Databricks** chip. ### Connect steps 1. Click the **Databricks** card. The AWS tab is the supported path. 2. Choose **New S3 bucket** (CloudFormation creates the bucket and nOps read role) or **Existing S3 bucket** (CloudFormation creates a read role scoped to your prefix). 3. Enter the **S3 bucket name** and a **dedicated prefix** (default `nops/databricks`). Do not reuse a shared prefix. The notebook writes system-table Parquet under that prefix and replaces only its own year/month/table/client path. 4. **Download .py notebook** or **Copy notebook**. nOps fills in the S3 destination, nOps client ID, and organization name. The generated file exports the system tables listed under [What the notebook exports](#what-the-notebook-exports) and is ready to import as a Databricks notebook. 5. Click **Save and open CloudFormation**. Deploy the stack in your AWS account. It creates a prefix-scoped, read-only role that the existing `nops-data-connector` can assume. The stack does not modify an existing bucket policy. 6. After the stack finishes, paste the **deployed role ARN** and click **Save deployed role**. > [!WARNING] > > Use a dedicated prefix. A shared prefix can overwrite other data under that path. ## Import and schedule the notebook in Databricks nOps does not create, run, or manage jobs in your workspace. After you download or copy the notebook in nOps: 1. Log in to your Databricks workspace. 2. Import the generated `.py` file (or create a notebook and paste the copied script). You can name it something like `NopsDatabricksBillingDataUploader`. 3. Grant this workspace permission to **write** to the S3 destination (for example a Unity Catalog external location). The CloudFormation role is for nOps **read** access only. 4. If the job will not run as a metastore admin, grant its run-as user or service principal **read** access to the system tables (see [Grant read access to system tables](#grant-read-access-to-system-tables)). 5. In the notebook toolbar, click **Schedule**. 6. Select a compute cluster and set the frequency to **Every 1 day**. 7. Create the schedule and confirm a run completes. Daily scheduling keeps Inform current. The first sync can take up to **24 hours**. ## What the notebook exports | Table | Required | Used for | | - | - | - | | `system.billing.usage` | Yes | Inform cost and usage | | `system.billing.list_prices` | Yes | Inform pricing | | `system.billing.account_prices`, `system.billing.cloud_infra_cost`, `system.billing.attributed_usage` | No | Negotiated prices and cloud infrastructure cost, where your account has them | | `system.compute.clusters`, `system.compute.warehouses` | No | Auto-termination / auto-stop settings and sizing for recommendations | | `system.compute.node_timeline`, `system.compute.node_types`, `system.compute.instance_pools`, `system.compute.instance_events` | No | Cluster utilisation and node sizing | | `system.compute.warehouse_events` | No | When SQL warehouses start, scale and stop | | `system.query.history` | No | Which clients and users keep SQL warehouses busy. Query text, error messages and query parameters are **not** exported. | Usage, cost, event, timeline and query-history tables are exported for the selected month. Configuration tables (clusters, warehouses, instance pools) contain the latest settings of every object that existed during the month, so a setting that last changed long ago is still included. Price lists and node types are exported in full. Optional tables that are not enabled in your metastore, or that the job principal cannot read, are skipped and the run still succeeds. Recommendations are more precise when they are available. Some system schemas (for example `system.query` or `system.compute`) may need an account admin to enable them first. ### Grant read access to system tables A metastore admin can already read every table. Otherwise, have an admin run the following for the job's run-as user or service principal (least privilege: `USE CATALOG`, `USE SCHEMA`, and `SELECT` on the exported tables only). Grants on tables your account does not have can be skipped. ```sql theme={"theme":{"light":"github-light","dark":"github-dark"}} GRANT USE CATALOG ON CATALOG system TO ``; GRANT USE SCHEMA ON SCHEMA system.billing TO ``; GRANT USE SCHEMA ON SCHEMA system.compute TO ``; GRANT USE SCHEMA ON SCHEMA system.query TO ``; GRANT SELECT ON TABLE system.billing.usage TO ``; GRANT SELECT ON TABLE system.billing.list_prices TO ``; GRANT SELECT ON TABLE system.billing.account_prices TO ``; GRANT SELECT ON TABLE system.billing.cloud_infra_cost TO ``; GRANT SELECT ON TABLE system.billing.attributed_usage TO ``; GRANT SELECT ON TABLE system.compute.clusters TO ``; GRANT SELECT ON TABLE system.compute.warehouses TO ``; GRANT SELECT ON TABLE system.compute.node_types TO ``; GRANT SELECT ON TABLE system.compute.instance_pools TO ``; GRANT SELECT ON TABLE system.compute.node_timeline TO ``; GRANT SELECT ON TABLE system.compute.warehouse_events TO ``; GRANT SELECT ON TABLE system.compute.instance_events TO ``; GRANT SELECT ON TABLE system.query.history TO ``; ``` ### Updating an existing export If your notebook shows a `Script version` earlier than `2026-10-16.1` (or was generated from the legacy nOps app), it exports only part of this list. Download or copy the notebook again from the Databricks card in nOps, replace the contents of your existing scheduled notebook, apply the grants above if needed, and run it once. The S3 destination, role, and schedule do not change. ## Azure Databricks Coming soon. Azure Databricks onboarding will use an Azure-native export storage and identity setup. No AWS CloudFormation step is available for Azure. ## Troubleshooting * **Shared prefix:** use a dedicated prefix such as `nops/databricks`. The notebook overwrites only its own year/month/table/client path under that prefix. * **No data after about 24 hours:** confirm the scheduled notebook job is succeeding, objects exist under the prefix, and the deployed role ARN is saved in nOps. * **Notebook cannot write to S3:** grant Unity Catalog (or equivalent) write access to the export bucket and prefix. The nOps CloudFormation role does not grant Databricks write. * **CloudFormation / role errors:** deploy in the AWS account that owns the bucket; paste the role ARN after the stack completes. Existing buckets must be in that account (or separately grant access). The stack does not update an existing bucket policy. * **Optional tables skipped:** the run output lists skipped tables and the reason. Apply the grants above, or ask an account admin to enable the `system.compute` / `system.query` schemas, then re-run. * **Azure tab:** Azure export is not available yet. Use AWS. ## Security nOps stores only the non-secret AWS destination and cross-account role configuration. The CloudFormation stack creates a prefix-scoped, read-only role trusted by `nops-data-connector` with your external ID. nOps never stores your Databricks workspace URL, warehouse ID, machine credential, or job configuration. The customer-run notebook writes system-table Parquet to your bucket; nOps reads only that prefix. Query text, error messages, and query parameters from `system.query.history` never leave your workspace. # Datadog Source: https://help.nops.io/integrations/datadog Connect Datadog to nOps for unified observability cost visibility ## Overview nOps uses your **Datadog API key**, **App key**, and **site** to pull cost and usage data into Inform. Credentials are stored securely, validated before save, and are not shown again in the nOps UI after you connect. ## Prerequisites * A Datadog account with permission to create or use API and application keys * Datadog **App key** with `usage_read` and `billing_read` scopes enabled * nOps organization **administrator** access to connect or manage the integration > [!NOTE] > > **Members** can view integration status on **Settings** and **Integrations**, but only **admins** and **owners** can connect, re-validate, or disconnect. Non-admins see an **Admin Only** indicator on connectable cards. ## Authentication requirements nOps requires both a **Datadog API key** and **Datadog App key**. The App key must have **`usage_read`** and **`billing_read`** permissions so nOps can retrieve cost and usage data. ## Create Datadog API key 1. Sign in to your [Datadog account](https://app.datadoghq.com). 2. Press **Ctrl+K** (Windows/Linux) or **⌘+K** (Mac) to open the Datadog search bar. 3. Type `/organization-settings/api-keys` and press **Enter**. 4. Click **New Key**, name the key (for example `API key for nOps`), and click **Create API key**. 5. Copy the **API key** value (not the Key ID) and store it securely. ## Create Datadog App key 1. Press **Ctrl+K** (Windows/Linux) or **⌘+K** (Mac) to open the Datadog search bar. 2. Type `/organization-settings/application-keys` and press **Enter**. 3. Click **New Key**, name the key (for example `Application key for nOps`), and click **Create Application key**. 4. Copy the **Application key** value and store it securely. 5. Click **Edit** on the new App key, enable **`usage_read`** and **`billing_read`**, and click **Save**. > [!WARNING] > > Without `usage_read` and `billing_read` on the App key, nOps cannot sync Datadog cost and usage data, even if the key itself is valid. ### If you cannot enable billing scopes Ask your **Datadog organization administrator** to edit the App key under **Organization Settings → Application Keys**, enable **`usage_read`** and **`billing_read`**, and save. Then try **Connect** again in nOps. ## Connect in nOps Only nOps administrators can complete these steps. ### Where to open Datadog * **To connect for the first time:** go to **Settings → Integrations** (open the full catalog via `/settings/integrations` or **View all** from the Settings preview) and click the **Datadog** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Datadog** chip to re-validate or disconnect. ### Connect steps 1. Click the **Datadog** card or chip. 2. Enter your **Datadog API key**, **Datadog App key**, and select your **Datadog site** (for example `datadoghq.com` or `datadoghq.eu`). See [Datadog sites](https://docs.datadoghq.com/getting_started/site/#access-the-datadog-site). 3. Click **Connect**. nOps validates both keys with Datadog before storing them. If validation succeeds, the catalog shows **Integrated** or Connected apps shows **Connected**. ## Manage your connection After Datadog is connected, administrators can open the same card or chip to: * **Re-validate:** nOps checks the stored keys against Datadog again without re-entering them. * **Disconnect:** removes the stored keys and marks the integration as disconnected. If validation fails, the status changes to **Action required**. Update or rotate keys in Datadog, then **Re-validate** or connect again with new keys. ## Troubleshooting ### Invalid credentials * Confirm the API key and App key were copied in full with no extra spaces. * Ensure the **Datadog site** matches the site you use to sign in to Datadog. * If the keys validate but no cost data appears, verify the App key has **`usage_read`** and **`billing_read`** enabled. ### Data not appearing * Allow up to **24 hours** for the initial Inform sync after a successful connect. * Confirm there is billable Datadog usage in the account. ### Admin Only on the card * You are signed in as a **member**. Ask an org admin to connect or manage Datadog. ## Security Treat API and App keys like passwords. Do not share them in chat, email, or source control. Rotate keys in Datadog if they may have been exposed. # Fastly Source: https://help.nops.io/integrations/fastly Connect Fastly API token to nOps for CDN cost visibility ## Overview nOps uses your **Fastly API token** to pull CDN cost and usage into Inform. The token is stored securely, validated before save, and is not shown again after you connect. ## Prerequisites * A Fastly account with permission to create API tokens * A token with **`global:read`** scope (required for billing and usage data) * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create a Fastly API token 1. Sign in to the [Fastly control panel](https://manage.fastly.com). 2. Go to **Account → Personal API tokens** (or **Account → API tokens**). 3. Click **Create Token**. 4. Configure the token: * **Name:** for example `nOps-Cost-Integration` * **Type:** **Automation token** (if available) * **Role:** **Billing** (if prompted) * **Scope:** **Read-only access (`global:read`)** * **Access:** **All Services** for full cost visibility * **Expiration:** per your security policy (rotate before expiry if set) 5. Copy the token immediately. It is typically shown only once. > [!WARNING] > > The token **must** have **`global:read`** for nOps to retrieve billing and usage data. nOps can confirm the token itself is valid without this scope, but cost data will not sync until the token has `global:read`. ## Connect in nOps ### Where to open Fastly * **To connect for the first time:** go to **Settings → Integrations** (`/settings/integrations` or **View all**) and click the **Fastly** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Fastly** chip to re-validate or disconnect. ### Connect steps 1. Click the **Fastly** card or chip. 2. Paste your **API token** and click **Connect**. nOps validates the token with Fastly before storing it. On success, the catalog shows **Integrated** or Connected apps shows **Connected**. ## Manage your connection Administrators can **Re-validate** stored credentials or **Disconnect** from the same modal. **Action required** means the token expired or was revoked. Fix the token in Fastly, then re-validate or connect again. A token that validates but lacks `global:read` stays **Connected** without producing cost data. ## Troubleshooting * **Invalid token:** confirm no typos and that the token is still active in Fastly. A valid token without `global:read` will connect but cost data will not appear. * **No data:** allow up to **24 hours** after connect; confirm billing activity exists in Fastly. * **Rate limits:** wait briefly and use **Re-validate**. ## Security Treat the API token like a password. Rotate on a schedule even if you chose “never expire” in Fastly. # GitHub Source: https://help.nops.io/integrations/github Connect GitHub billing, usage, seats, and engineering activity to nOps ## Overview Connect GitHub to nOps with a **personal access token** and your **organization slug** (and optionally an **enterprise slug** if you report at enterprise level). We validate the token before saving it, store it securely, and never show it again in the UI. We recommend a **fine-grained PAT** owned by your organization: you can grant **read-only** org and repository permissions instead of the broad classic scopes. If you need **enterprise billing** or **consumed licenses**, use a **classic** PAT for that part. GitHub does not support those endpoints on fine-grained tokens. This card is your **cost and usage** integration. It is separate from **GitHub Issues** in Clara’s recommendation workflow (that flow uses WorkOS Pipes and a repository destination). Connecting here does **not** turn on issue creation. After you connect, nOps can ingest: * **Cost and usage:** metered spend by product, SKU, repository, and day (Actions, Codespaces, Packages, storage, Copilot, GHAS, and more). * **Copilot attribution:** premium requests and AI credits by user and model, plus Copilot seat assignments when your token allows it. * **Members and seats:** your organization member roster and paid seat counts. * **Engineering activity:** read-only metadata from pull requests, commits, and Actions runs to enrich anomaly context (no source code or file contents). > [!NOTE] > > Only nOps **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on the integration card. ## Who can create the token? The person who creates the token needs the right role in GitHub: | Connection type | Role on GitHub | | - | - | | **Organization** | Organization **owner** or **billing manager** | | **Enterprise** (classic PAT only) | Enterprise **admin** or **billing manager** | Your org or enterprise should use GitHub’s **enhanced billing platform** (required for the billing usage APIs nOps calls). You also need nOps **Settings → Integrations** admin access to connect the card. ## Choose your token type The connect modal asks you to pick **Fine-grained PAT (recommended)** or **Classic PAT**. The permission checklist in the modal matches the lists below. ### Fine-grained PAT (recommended) Create the token with **Resource owner = your organization** (not your personal account). Grant **read-only** permissions. nOps only sends **GET** requests. **Organization permissions** * **Administration: read:** organization billing usage, premium requests, AI credits * **Members: read:** member roster * **GitHub Copilot Business: read:** Copilot seats *(optional, if you use Copilot)* * **Organization Copilot metrics: read:** Copilot usage metrics *(optional)* **Repository permissions:** set access to **All repositories** (or every repo your engineers use; repos the token cannot see are omitted from activity data) * **Metadata: read:** repository list *(included automatically)* * **Pull requests: read:** PR metadata for activity context * **Contents: read:** commit metadata on the default branch *(not file contents)* * **Actions: read:** workflow run metadata > [!WARNING] > > Do **not** add an **Enterprise slug** in nOps when you use a fine-grained token. Enterprise billing usage and consumed licenses require a **classic** PAT with `read:enterprise`. Use fine-grained for org-level billing and activity, or switch to classic if you need enterprise reporting. > [!TIP] > > Fine-grained tokens are a good fit for a **dedicated service account** with a short expiry and regular rotation. They avoid classic `repo`, which includes **write** access to private repositories. ### Classic PAT Use a classic token when you need **enterprise** billing, when fine-grained org billing is unavailable for your org, or when you prefer the older scope model. **Scopes to select** * **`admin:org`:** **required** for organization billing (`read:org` and `write:org` are **not** enough; GitHub often returns “not found” instead of “forbidden” when billing scope is missing) * **`manage_billing:copilot`:** Copilot seats *(optional)* * **`read:enterprise`:** **required** if you enter an **Enterprise slug** (enterprise billing and consumed licenses) * **`repo`:** private repository activity *(optional for activity data; includes write. Prefer fine-grained for read-only repo access)* > [!WARNING] > > **What nOps does with `admin:org`.** GitHub treats organization billing as org administration. There is no separate “billing-only” classic scope for orgs. nOps uses these credentials only to **read** billing, Copilot, and member endpoints, never to change org settings, teams, or membership. Use a service account, limit scopes to what you need, and rotate on a schedule. ## Create the token in GitHub ### Fine-grained 1. Sign in to [GitHub](https://github.com) as an org owner or billing manager. 2. Go to **Settings → Developer settings → Personal access tokens → Fine-grained tokens**. 3. Click **Generate new token**, set **Resource owner** to your **organization**, and choose **All repositories** (or the repos you need). 4. Add the organization and repository permissions from the list above. 5. Set an expiration, generate the token, and copy it. GitHub shows it **once**. ### Classic 1. Sign in as an org owner, billing manager, or enterprise admin (as needed). 2. Go to **Settings → Developer settings → Personal access tokens → Tokens (classic)**. 3. Click **Generate new token (classic)**, add a note (for example `nOps Inform`), and set an expiration. 4. Select the scopes from the classic list above. 5. Generate and copy the token immediately. For API details, see GitHub’s [billing usage REST API](https://docs.github.com/en/rest/billing/usage) and [Automating usage reporting](https://docs.github.com/en/billing/tutorials/automate-usage-reporting). ## Connect in nOps ### Where to open GitHub * **First-time connect:** **Settings → Integrations**, then the **GitHub** card. * **Manage an existing connection:** **Settings → Account Status → Connected apps**, then the **GitHub** chip. ### Connect steps 1. Open the **GitHub** modal. 2. Choose **Token type** (fine-grained or classic). 3. Paste your token (`github_pat_…` or `ghp_…`). nOps detects the prefix if it does not match your selection and shows a clear error. 4. Enter your **Organization slug** (the URL segment from `github.com/your-org`, not the display name). 5. Optionally enter an **Enterprise slug** (**classic PAT only**). 6. Click **Connect**. nOps calls the GitHub API to confirm the token and billing access before storing credentials. If something is wrong, you’ll see a specific message in the modal (missing scope, wrong slug, enterprise + fine-grained mismatch, and so on). ## Manage your connection From the same modal, admins can **Re-validate** (check the stored token still works), **Update** (new token or slugs), or **Disconnect**. Rotate tokens in GitHub before they expire, then update the connection in nOps. ## Troubleshooting * **Invalid token:** Confirm the token owner has a billing or admin role and the token has not expired. * **Fine-grained + enterprise slug:** Remove the enterprise slug or switch to a classic PAT with `read:enterprise`. * **Token type mismatch:** If you chose Classic but pasted `github_pat_…`, switch the dropdown to Fine-grained (or paste a `ghp_…` classic token). * **Organization not found / validation fails:** Double-check the **slug** from the URL. For classic org billing, add **`admin:org`**. For fine-grained, grant **Administration: read** on a token whose resource owner is the org. The token owner must still be an org owner or billing manager. * **No enterprise data:** Use a **classic** PAT with **`read:enterprise`** and an enterprise billing role. * **No Copilot or member data:** Add Copilot or Members permissions (fine-grained) or `manage_billing:copilot` / member-related classic access. Missing optional permissions skip those datasets but do not block core cost and usage. * **No billing data:** Your org may not be on the enhanced billing platform yet; check GitHub billing settings. * **No data in Inform yet:** Allow up to **24 hours** after the first successful connect for the initial sync. ## Security Treat the token like a password: do not commit it to git or share it in chat. Grant the minimum read permissions you need, use a service account where possible, rotate on a schedule, and disconnect in nOps when you retire a token. ## Reference * [GitHub REST API: Billing usage](https://docs.github.com/en/rest/billing/usage) * [GitHub REST API: Copilot user management (seats)](https://docs.github.com/en/rest/copilot/copilot-user-management) * [GitHub REST API: Enterprise consumed licenses](https://docs.github.com/en/enterprise-cloud@latest/rest/enterprise-admin/license) * [Automating usage reporting with the REST API](https://docs.github.com/en/billing/tutorials/automate-usage-reporting) # GitLab Source: https://help.nops.io/integrations/gitlab Connect GitLab.com subscription, seat, and usage data to nOps ## Overview nOps uses a **GitLab.com access token** (with the `read_api` scope) plus your **top-level group** to pull subscription, seat, and usage-quota data into Inform. The token is stored securely, validated before save, and is not shown again after you connect. This is a **cost and usage integration**. It is separate from **GitLab Issues** in the recommendation workflow, which uses an organization connection and a project destination. Connecting this card does not enable issue creation. This integration targets **GitLab.com SaaS** (`https://gitlab.com`). nOps reads: * **Subscription & plan:** namespace plan tier and billable member count. * **Seats:** billable members (paid seats) and per-member seat usage / last activity. * **Usage quotas:** CI/CD compute minutes and storage (repository, LFS, artifacts, packages, container registry) at the group and project level. > [!NOTE] > > Unlike some vendors, GitLab's API returns **usage quantities and seat counts, not billed dollar amounts**. There is no per-line USD billing feed. nOps derives cost from your plan and reports seats, compute minutes, and storage; dollar figures come from your subscription pricing, not the API. ## What token and access do I need? | Requirement | Value | Why | | - | - | - | | **Token scope** | **`read_api`** (least-privilege) or `api` | Read-only access to all the group, member, seat, and usage-quota endpoints nOps calls. GitLab has no billing-specific scope. | | **Role** | **Owner** on the **top-level group** | Seat / billable-member and usage-quota endpoints require the **Owner** role and work on **top-level groups only**. A Maintainer token returns `403`. | | **Token type** | **Group access token** (recommended) or personal access token from a group Owner | A group access token is scoped to the one group and isn't tied to a person. | > [!WARNING] > > The **`read_api`** scope alone is not enough. The token owner (or the group access token) must have the **Owner** role on the **top-level group**. Seats and usage quotas are not readable at Maintainer level or on subgroups. > [!NOTE] > > GitLab is rolling out **fine-grained personal access tokens**, but the standard, broadly-supported choice for read-only reporting is a **classic** token (personal or group) with `read_api`. > [!NOTE] > > Only nOps **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Cost inputs (collected at connect time) > [!WARNING] > > GitLab has **no public billing API**. Its REST and GraphQL APIs return usage quantities and seat counts only, never dollars (the invoice lives in the Customers Portal / internal CustomersDot API, which a customer token cannot reach). To report **cost**, nOps needs a few pricing inputs from you. Provide them once at connect time; nOps derives cost from your seat count, compute minutes, and storage. The connect form collects the following (stored securely in Secrets Manager alongside your token). Only **price per seat** is important. GitLab bills are roughly seats × price, so that one number drives most of the cost: | Field | Required | Notes | | - | - | - | | **Plan** | auto | Detected from your namespace (`free` / `premium` / `ultimate`); confirm or override. | | **Price per seat** | recommended | Your negotiated price per billable user. This is the main cost driver. | | **Billing term** | recommended | `monthly` or `annual`. Annual prices are normalized to a monthly figure (÷12). | | **Currency** | optional | Defaults to `USD`. | | **Contracted seats** | optional | If your contract fixes a seat count; otherwise nOps uses the live billable-members count. | | **Included compute minutes / overage rate** | optional | Per month. Defaults to the plan allotment; overage is usually \$0. | | **Included storage GB / overage rate** | optional | Overage is usually \$0 within the plan allotment. | | **Invoice total + period** | optional | If supplied, nOps stores it as the actual (EffectiveCost) figure for invoice tie-out. | > [!NOTE] > > Without a **price per seat**, nOps still ingests seats, compute minutes, and storage as **usage** (cost \$0). Add the seat price to turn on dollar reporting. All values can be updated later by re-connecting. ## Create the token ### Group access token (recommended) 1. Sign in to [GitLab.com](https://gitlab.com) as an **Owner** of your top-level group. 2. Go to your group's **Settings → Access tokens**. 3. Create a token: set the **role** to **Owner**, select the **`read_api`** scope, and set an expiration. 4. Create the token and copy it immediately. It is shown only once. ### Personal access token (alternative) 1. Sign in to [GitLab.com](https://gitlab.com) as a user who is an **Owner** of the top-level group. 2. Go to **Edit profile → Access → Personal access tokens**. 3. Select the **`read_api`** scope, set an expiration, and generate the token. 4. Copy the token immediately. It is shown only once. See [GitLab personal access tokens](https://docs.gitlab.com/user/profile/personal_access_tokens/) and [group access tokens](https://docs.gitlab.com/user/group/settings/group_access_tokens/) for details. ## Connect in nOps ### Where to open GitLab * **To connect for the first time:** go to **Settings → Integrations** and click the **GitLab** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **GitLab** chip to re-validate or disconnect. ### Connect steps 1. Click the **GitLab** card or chip. 2. Paste your **access token** (group access token or personal access token). 3. Enter your **top-level group** path (for example `my-company`) or numeric group ID. 4. Click **Connect**. nOps validates the token against the GitLab.com API before storing it, then uses the group to read seats and usage quotas. ## Manage your connection Administrators can **Re-validate** or **Disconnect** from the modal. Rotate the token in GitLab before expiry and reconnect in nOps after rotation. ## Troubleshooting * **Invalid token:** confirm the token has the **`read_api`** scope and has not expired. * **No seat or usage data / 403:** the token needs the **Owner** role on the **top-level group**; a Maintainer token or a subgroup token cannot read seats or usage quotas. * **Wrong group:** use the full top-level namespace path (for example `my-company`) or the numeric group ID; subgroups are not supported for billing/usage. * **No dollar amounts:** expected: GitLab's API returns usage and seat counts, not billed USD. nOps derives cost from your plan. * **No data in Inform:** allow up to **24 hours** after connecting for the first sync. ## Security Do not share the token or store it in public repositories. Prefer a **group access token** with `read_api` scoped to a single top-level group. Rotate before expiration and disconnect in nOps when rotating. ## Reference * [GitLab REST API authentication](https://docs.gitlab.com/api/rest/authentication/) * [Personal access token scopes](https://docs.gitlab.com/user/profile/personal_access_tokens/#personal-access-token-scopes) * [Group access tokens](https://docs.gitlab.com/user/group/settings/group_access_tokens/) * [List billable members of a group](https://docs.gitlab.com/api/group_members/#list-all-billable-group-members) # LiteLLM Source: https://help.nops.io/integrations/litellm Connect a self-hosted LiteLLM gateway to nOps Inform ## Overview nOps connects to your **LiteLLM proxy** with a **read API key** to see models, keys, and spend across the gateway. You can also add an optional **write API key** for future management actions (keys, teams, budgets). Keys are validated before save and are never shown again after you connect. nOps shows only the last four characters of each key. You can connect more than one gateway. Each gateway is a separate connection with its own base URL and keys. ## Prerequisites * A LiteLLM proxy you administer, with the admin UI or the management API enabled * The gateway reachable from the internet over **public HTTPS** (recommended) or HTTP (see [Network requirements](#network-requirements)) * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create the read API key The read key needs to read model info, keys, and spend for the whole gateway. Use a key that belongs to a **`proxy_admin_viewer`** user, so it sees every team but cannot change anything, and limit it to the read routes below. 1. Create a viewer user (skip this if you already have one): ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://litellm.example.com/user/new \ -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{"user_email": "nops@example.com", "user_role": "proxy_admin_viewer"}' ``` 2. Create a key for that user that can call only these read routes: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} curl -X POST https://litellm.example.com/key/generate \ -H "Authorization: Bearer $LITELLM_MASTER_KEY" \ -H "Content-Type: application/json" \ -d '{ "user_id": "", "key_alias": "nops-read", "allowed_routes": [ "/model/info", "/key/info", "/key/list", "/user/daily/activity", "/spend/logs", "/spend/tags", "/global/spend/report", "/team/list", "/team/info", "/user/info" ] }' ``` 3. Copy the `key` value from the response. LiteLLM shows it only once. > [!WARNING] > > Do not use `"key_type": "read_only"` (or `"allowed_routes": ["info_routes"]`). That preset blocks `/user/daily/activity`, which nOps needs to read spend, so spend shows as **Denied**. > [!WARNING] > > Do not use an **LLM API** key (`key_type: llm_api`) or a key scoped to one team. An LLM API key can only call model routes, and a team key shows nOps only that team's usage. nOps warns you after it validates the key. ## Create the write API key (optional) Add a write key only if you want nOps to manage LiteLLM keys, teams, or budgets later. Create it for a **`proxy_admin`** user, or use `"key_type": "management"`. Keep it separate from the read key. To let nOps apply a savings change to a model (see [Savings opportunities](#savings-opportunities)), the write key must also be allowed to call **`/model/*`**. The standard `management_routes` preset does not include `PATCH /model/{id}/update`, which is the route nOps uses to edit a model without disturbing its other settings. For example, when you create the key, send `"allowed_routes": ["management_routes", "/model/*"]`. Without it, nOps can still recommend changes but cannot apply them. When you save a write key, nOps checks which management routes it can call with requests that change nothing: each one targets an id that does not exist (`nops-probe-…`), so LiteLLM answers "not found" instead of making a change. If the key cannot call any management route, nOps does not save it. ## Connect in nOps 1. Go to **Settings → Integrations** and click the **LiteLLM** card. 2. Enter the **Base URL** of the proxy (for example `https://litellm.example.com`). Use the final URL; nOps does not follow redirects. If the URL starts with `http://`, confirm **I understand API keys will be sent unencrypted** to continue. 3. Paste the **Read API key** and, optionally, the **Write API key**. 4. Optionally add a **label** (for example `Production gateway`). 5. Click **Connect**. nOps checks that the gateway is healthy, that each key is accepted, and which routes each key can call. Nothing is saved if a check fails. ## Savings opportunities Open a gateway in **Settings → Integrations → LiteLLM** and click **Savings**. nOps reads the last 14 days of spend through your read key and looks for prompt-caching opportunities: models, such as Claude, that only cache when requests carry cache markers and where little of your prompt traffic is served from the provider's cache. Each recommendation shows: * A **monthly savings range**, not a single number. It is based on your observed cache reads and the model's own cache prices, and assumes only a modest share of the remaining prompt tokens become cache reads. * The **evidence** behind it: prompt tokens, cache-read share, and spend over the period. * **How to apply**: the `cache_control_injection_points` setting to add to that model. > [!NOTE] > > nOps never changes your gateway on its own. Where applying from nOps is enabled for your organization and the gateway has a write key, an **Apply in nOps** button adds the setting for you and a **Roll back** button removes it; otherwise applying the setting is up to you. Either way it affects every team that uses that model, and if your gateway stores models in its database, changes take about a minute to go live. nOps does not overwrite markers you already set. Models that already cache most of their prompts, or that nOps cannot price, are left out. If nothing qualifies, nOps says so and shows your overall cache-read share. ### Model routing For an API key that sends mostly short prompts to a premium model, nOps estimates what you would save by letting a router send the simple requests to a cheaper model of the same family. The estimate is a wide range, because request size stands in for difficulty and nOps never reads your prompts. nOps does not apply routing for you yet. If you set it up yourself, test it on a sample first: on some gateway versions a request that goes through a LiteLLM complexity router ignores the caller's `max_tokens`, so a short answer can come back full length and cost far more than the saving. Send a request with a very small `max_tokens` through the router and confirm the response honors it. ### Prompt compression For keys whose prompts are long (several thousand tokens on average), nOps shows how much input spend per month compression could act on. This is the spend at stake, not a savings estimate: how much a prompt shrinks depends on its content, which nOps does not read. nOps does not apply compression for you. Trial a compression guardrail on one key, then compare cost per request and answer quality before widening it. ### Apply everything recommended When two or more changes can be applied from nOps, **Review and apply all** lists each change and how far it reaches. Each is applied one at a time through the same checks as a single click, so one refusal does not stop the others, and every change can be rolled back on its own. ## Network requirements * The base URL should use **`https://`** with a public hostname. IP addresses, `localhost`, and `.local` / `.internal` hostnames are rejected. * **`http://`** is allowed only after an admin explicitly confirms it, because API keys and responses then travel unencrypted. nOps shows an **Insecure (http)** badge and a warning on the connection. Switch to https when possible. Moving a connection from https to http needs the same confirmation and the keys re-entered. * http does not change the network rules below: private networks are still unreachable over http. * The hostname must resolve only to **public** IP addresses. nOps checks DNS before every request and refuses private, loopback, link-local, and carrier-grade NAT ranges. * Redirects are not followed. If the proxy redirects (for example from `/` to `/ui`, or from `http://` to `https://`), enter the URL that answers directly. * If the gateway only accepts traffic from allowlisted IP addresses, contact nOps support before connecting. ## Manage your connection * **Re-validate** re-runs the checks with the stored keys. A failure shows **Action required**. * **Rotate a key** by entering a new value; leave a key field unchanged to keep the stored key. * **Remove the write key** to go back to read-only access. * **Change the base URL** on a different host only by re-entering the read key (and the write key, or removing it). nOps never sends stored keys to a new host. * **Disconnect** deletes the stored keys. ## Troubleshooting * **Could not reach the gateway:** confirm the base URL is publicly reachable and that `/health/liveliness` returns 200. * **Host is not allowed:** the hostname resolves to a private or reserved address. Expose the proxy on a public address. * **LiteLLM redirected:** enter the final URL the proxy serves, without redirects. A redirect from http to https means you should enter the `https://` URL. * **Confirm insecure http:** the URL starts with `http://`. Use the `https://` URL, or confirm that keys will be sent unencrypted. * **Read key rejected:** confirm the key is active and was copied in full. * **Read key cannot read spend or keys:** the key is missing routes, most often `/user/daily/activity` (spend) or `/key/list` (keys). Add them to the key's `allowed_routes` (`POST /key/update`) or recreate it as described in [Create the read API key](#create-the-read-api-key), for a `proxy_admin_viewer` user. * **Write key cannot call any management routes:** the write key's user is not an admin, or the key's routes exclude management routes. ## Security Treat both keys like passwords. Rotate them in LiteLLM if they may have been exposed, then update them in nOps. # MongoDB Atlas Source: https://help.nops.io/integrations/mongodb-atlas Connect MongoDB Atlas organization API keys to nOps Inform ## Overview nOps uses your MongoDB Atlas **Organization ID** and **organization API keys** to bring Atlas spend into Inform across the projects you grant access to. Keys are stored securely, validated before save, and are not shown again after you connect. ## Prerequisites * MongoDB Atlas **organization administrator** access * API keys with **Organization Billing Viewer** at the org level and **Project Read Only** on each project you monitor * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Step 1: Find your Organization ID The Organization ID is a 24-character identifier for your Atlas organization. 1. Open the [MongoDB Atlas Organizations page](https://cloud.mongodb.com/v2#/preferences/organizations). 2. Select your organization. 3. Click **Settings** in the left menu. 4. Copy the **Organization ID** exactly as shown (organization settings, not project settings). ## Step 2: Create API keys 1. In **Organization Settings**, open **Access Manager → Applications**. 2. Click **Add new → API Key**. 3. Name the key (for example `nOps Integration`). 4. Assign the **Organization Billing Viewer** role. 5. Copy the **Public API key** and **Private API key**. The private key is shown only once. > [!WARNING] > > If your organization uses an **IP access list** for the Atlas Administration API, allow **`52.11.169.55`** so nOps can validate and sync credentials. Without this, connect or re-validate may fail even when keys are correct. ## Step 3: Configure project access Repeat for **each project** you want in Inform: 1. In **Organization Settings**, click **Projects** and select a project. 2. Open **Access Manager → Project Access**. 3. Click **Invite to Project**, select your integration API key, and grant **Project Read Only**. 4. Confirm the invitation. The key needs both **Organization Billing Viewer** (org level) and **Project Read Only** (per project). ## Connect in nOps ### Where to open MongoDB * **To connect for the first time:** go to **Settings → Integrations** and click the **MongoDB** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **MongoDB** chip to re-validate or disconnect. ### Connect steps 1. Click the **MongoDB** card or chip. 2. Enter **Organization ID**, **Public API key**, and **Private API key**. 3. Click **Connect**. nOps validates credentials against the Atlas API before storing them. Validation can fail if the IP access list blocks nOps. Add **`52.11.169.55`** in Atlas if required. ## Manage your connection Administrators can **Re-validate** or **Disconnect** from the modal. **Action required** may mean revoked keys, wrong Organization ID, missing project access, or IP restrictions. ## Troubleshooting * **Validation failed:** check Organization ID, both keys, **Billing Viewer** + **Project Read Only**, and IP allowlist **`52.11.169.55`**. * **Organization ID mismatch:** keys may be valid but not authorized for the Organization ID you entered. * **No billing data:** allow up to **24 hours** after connect; confirm keys are invited to all relevant projects. * **Multiple organizations:** use separate API keys and separate connects per organization. ## Security Treat the private API key like a password. Rotate in Atlas if it may have been exposed. # OpenAI (Platform) Source: https://help.nops.io/integrations/openai Connect OpenAI Platform Admin API credentials to nOps Inform ## Overview nOps uses your **OpenAI Platform Admin API key** and an **API key name** label to bring API usage and billing into Inform. Credentials are stored securely, validated before save, and are not shown again after you connect. > [!NOTE] > > This integration is for the **OpenAI Platform** organization (platform.openai.com): programmatic API usage. If your organization uses **ChatGPT Enterprise** seats, see [ChatGPT (Enterprise)](/integrations/openai-enterprise) instead. The two credential types are **not** interchangeable, and Codex usage on ChatGPT credits does not appear in Platform cost data. ## Prerequisites * OpenAI organization access to create **Admin API keys** * An Admin API key with **read-only** permissions for billing data * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create an OpenAI Admin API key 1. Sign in to the [OpenAI platform](https://platform.openai.com). 2. Open [Admin API keys](https://platform.openai.com/settings/organization/admin-keys). 3. Click **Create new Admin Key**. 4. Enter a descriptive name (for example `nOps Integration`). 5. Select **Read-only** permissions and click **Create admin key**. 6. Copy the Admin API key immediately. It is shown only once. > [!WARNING] > > Do not share the Admin API key or commit it to source control. If lost, create a new key and connect again in nOps. ## Connect in nOps ### Where to open OpenAI (Platform) * **To connect for the first time:** go to **Settings → Integrations** and click the **OpenAI (Platform)** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **OpenAI (Platform)** chip to re-validate or disconnect. ### Connect steps 1. Click the **OpenAI (Platform)** card or chip. 2. Enter an **API key name** (for example `Production OpenAI`) and paste the **Admin API key**. 3. Click **Connect**. nOps validates the Admin API key with OpenAI before storing it. ## Manage your connection Use **Re-validate** to check stored credentials without re-entering them, or **Disconnect** to remove them. **Action required** usually means a revoked, expired, or non-admin key. Create a new Admin API key in OpenAI and connect again. ## Troubleshooting * **Invalid key:** use an **Admin API key** with read-only billing access, not a standard project API key. * **No data:** allow up to **24 hours** for initial sync; confirm billing activity in OpenAI. * **Multiple accounts:** use distinct **API key name** values if you connect more than one OpenAI organization over time. ## Security Rotate Admin API keys on a schedule. Update the integration in nOps before a key expires if you set an expiration in OpenAI. ## Related * [ChatGPT (Enterprise)](/integrations/openai-enterprise): separate integration for ChatGPT workspace seats and credit spend, including Codex on ChatGPT plans # ChatGPT (Enterprise) Source: https://help.nops.io/integrations/openai-enterprise Connect a ChatGPT Enterprise workspace Admin key to nOps Inform ## Overview nOps uses a **workspace Admin key** created in the **Global Admin Console** to bring ChatGPT Enterprise usage and credit spend into Inform. This is the surface where **Codex** usage lands when developers run Codex on a ChatGPT plan (seats and AI credits) rather than an API key. Credentials are stored securely and are not shown again after you connect. > [!NOTE] > > This integration is for **ChatGPT Enterprise workspaces** only. If your organization uses **OpenAI Platform** (programmatic API usage on platform.openai.com), see [OpenAI (Platform)](/integrations/openai) instead. The two credential types are **not** interchangeable. An Admin key cannot be used for model inference, and a Platform Admin API key is rejected by the workspace endpoints. ## Prerequisites * A ChatGPT **Enterprise** workspace eligible for Admin keys * A workspace **admin** or **owner** who can create Admin keys * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create an Admin key 1. Sign in to the **Global Admin Console** at [admin.openai.com](https://admin.openai.com). 2. Open **Credentials → Admin keys**. 3. Select **Create new admin key** and choose the workspace the key should access. 4. Grant **read** access to the features in [Admin key permissions](#admin-key-permissions) below. 5. Copy the key immediately and store it securely. It starts with `sk-admin-`. > [!NOTE] > > One Admin key covers **one workspace**, and Admin keys cannot be used for model inference. ## Admin key permissions Grant these in **Credentials → Admin keys**. OpenAI's console shows toggle names rather than scope strings; the scope column is here for support conversations and for reading refusal messages. | Permission | Scope | Unlocks | Required? | | - | - | - | - | | **Usage limits → Read** | `chatgpt.enterprise.usage_limit.read` | ChatGPT seats, per-seat spend and limits, limit-increase requests | **Yes.** No seats load without it | | **Compliance logging platform → Costs → Read** | `chatgpt.enterprise.compliance_logs_platform.costs.read` | Full ChatGPT spend (Work, ChatGPT, voice, image, and Codex) as hourly per-user rows carrying model, product, surface, client, service tier, reasoning effort, token counts, and per-SKU credits and dollars | **Strongly preferred** cost source | | **Codex analytics API → Read** | `codex.enterprise.analytics.read` | Codex usage per user and model, including model and speed breakdowns and Codex engagement (threads and turns) | Fallback cost source | | **Group Management → Read** | `chatgpt.enterprise.directory.read` | **Sync from ChatGPT** on Cost Allocation: which seats belong to which group | Optional | > [!WARNING] > > **Grant at least one cost source.** Costs and Codex analytics are an either-or: nOps prefers the > Costs logs and reads Codex analytics only when Costs is unavailable. With **both** refused, no > ChatGPT spend is ingested at all. ### Why Costs is preferred over Codex analytics Codex analytics reports Codex activity **only**. Measured against a workspace that had the Costs feed, Codex accounted for roughly **a third of credit spend**, so on the fallback the rest of a workspace's ChatGPT usage never reaches the cost tables. The ChatGPT Enterprise slice in [AI tracking](/ai/tracking) and its model breakdown then show a Codex-only total, which reads as a complete one. Cost allocation, budgets, and forecasting read the same ingested spend, so their ChatGPT totals are incomplete too. Cost logs are the slowest of the ChatGPT feeds: OpenAI publishes them **3–5 hours** behind the reporting hour, where the other log types target under 30 minutes. Recent hours filling in gradually is normal, not a broken connection. > [!WARNING] > > **Costs history starts when you grant it.** OpenAI keeps only **30 days** of cost logs and nOps > cannot backfill, so every week spent on the Codex fallback is non-Codex spend that can never be > recovered. > [!NOTE] > > Two things to check when Costs is refused, because they look identical from the outside, while > the permission is missing, OpenAI answers `400 Invalid event_type` and the `404` that would reveal > a wrong ID never fires: > > * **The permission must be organization-level.** Workspace-level compliance permissions look > similar but return nothing for cost. This is the most common mistake here. > * **The Organization ID must be right.** Costs is the only organization-scoped route, so a wrong > `org-…` value fails even with the permission granted. Group Management is optional and never affects spend. Without it, group names and sizes still load from the usage-limits routes; what is lost is who belongs to each group, so allocation groups have to be built by hand with **Add group** on the Cost Allocation tab. > [!WARNING] > > Do not share the Admin key or commit it to source control. If it is lost or compromised, create a new key and connect again in nOps. ## Find your workspace and organization IDs Both are on [chatgpt.com/admin](https://chatgpt.com/admin): * **Workspace ID:** a UUID such as `123e4567-e89b-12d3-a456-426614174000`. Required. * **Organization ID:** starts with `org-`. Required. Used for cost log ingestion. > [!WARNING] > > These two are easy to mix up. The Workspace ID field rejects `org-…` values. ## Connect in nOps ### Where to open ChatGPT (Enterprise) * **To connect for the first time:** go to **Settings → Integrations** and click the **ChatGPT (Enterprise)** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **ChatGPT (Enterprise)** chip to re-validate or disconnect. ### Connect steps 1. Click the **ChatGPT (Enterprise)** card or chip. 2. Enter a **Key name** and paste the **Admin key**. 3. Enter the **Workspace ID**. 4. Enter the **Organization ID**. 5. Click **Connect**. ## What nOps checks on connect nOps makes **four** read-only calls, one per permission, and records the verdict of each. A missing Organization ID fails before any of them run. | Check | If it fails | | - | - | | **Seat usage limits** | No ChatGPT seats load, and per-seat spend, limits, and limit requests are unavailable. | | **Cost logs** | ChatGPT spend falls back to Codex analytics: a fraction of the real total. See [Why Costs is preferred](#why-costs-is-preferred-over-codex-analytics). | | **Codex usage** | No Codex detail, and no cost source at all if cost logs failed too. | | **Directory groups** | **Sync from ChatGPT** is unavailable; groups must be built by hand on Cost Allocation. | Only the seat and Codex checks decide whether the connection is created. **Either one alone connects**, because either alone is useful. Cost logs and directory groups never block it: the organization-level Costs permission is commonly unavailable on a first attempt, and group sync is optional. > [!WARNING] > > **Connected does not mean complete.** A key that passes both gating checks still connects with no > cost logs, and nothing in the success message says so. Whenever a permission is refused, nOps > names it (and what it turns off) on the connect modal and at the top of the **AI** area, and > marks the integration card as needing attention. Read that list before treating an onboarding as > finished. A check that could not complete (a timeout or a rate limit rather than a refusal) is reported as such, so a transient blip never reads as a missing permission. If both gating checks fail this way, the connection is simply retried, not broken. A partial result still connects, because either half is useful on its own. nOps then shows which permissions were refused, and what each one turns off, on the connect modal and at the top of the **AI** area. Credentials are stored in AWS Secrets Manager, and only the last four characters of the key are retained for support. ## Manage your connection Use **Re-validate** to re-run all four checks against the stored credentials, or **Disconnect** to remove them. **Action required** means the checks stopped passing, usually a revoked key or a permission that was removed. Adding a permission later and re-validating is enough; you do not need to reconnect from scratch. ## Troubleshooting * **"Requires ChatGPT Enterprise":** the workspace is on ChatGPT Business, which does not expose these APIs. No permission change will help; this needs an Enterprise plan. * **"That's a Codex access token":** a token starting `at-` cannot read analytics. Create an Admin key instead. * **"That's a project key":** a key starting `sk-proj-` is a project key. Admin keys start `sk-admin-`. * **"This credential can't access the admin APIs":** the key was rejected by access enforcement. Confirm it is an Admin key from the Global Admin Console. * **Missing scopes:** nOps shows the scope name exactly as OpenAI reports it. Edit the key in **Credentials → Admin keys** and grant that feature, then **Re-validate**. * **"Workspace ID not found for this key's organization":** the Admin key and Workspace ID belong to different organizations. Confirm both on [chatgpt.com/admin](https://chatgpt.com/admin). * **ChatGPT spend looks too low, or only Codex models appear:** the key is on the Codex fallback because **Compliance logging platform → Costs → Read** is missing or the Organization ID is wrong. See [Why Costs is preferred](#why-costs-is-preferred-over-codex-analytics). Grant it promptly: only 30 days of cost logs exist and there is no backfill. * **No ChatGPT spend at all:** both cost sources are refused. Grant **Costs → Read** (preferred) or **Codex analytics API → Read**. * **Sync from ChatGPT does nothing / groups have no members:** the key lacks **Group Management → Read**. Group names and sizes still load without it; membership does not. Seat tracking and spend are unaffected. * **No data:** allow up to **24 hours** after connect for usage data to populate in Inform. Cost logs lag a further **3–5 hours** behind the hour they cover, so the most recent hours are expected to be incomplete. * **Codex usage missing:** Codex on ChatGPT credits appears here, while Codex on a Platform API key appears under [OpenAI (Platform)](/integrations/openai). If your developers use both, connect both integrations. ## Security Follow your organization's key rotation policy. Update nOps before rotating keys in the Global Admin Console to avoid sync gaps. ## Related * [AI](/ai/introduction): track per-seat ChatGPT and Codex spend, limits, and requests * [Set up AI seat tracking](/ai/setup): create a seat tracking project after connecting ChatGPT Enterprise * [OpenAI (Platform)](/integrations/openai): separate integration for platform.openai.com API usage # Snowflake Source: https://help.nops.io/integrations/snowflake Connect Snowflake usage and billing data to nOps Inform using key-pair authentication ## Overview nOps reads **Snowflake usage and billing data** (warehouse credit consumption, query history, and organization-level spend) from Snowflake's `ACCOUNT_USAGE` and `ORGANIZATION_USAGE` system views to show cost and performance in Inform. Snowflake uses **RSA key-pair authentication**: you provide only your **account identifier**, and nOps generates a key pair and gives you the exact SQL commands to run. You can connect **multiple** Snowflake accounts, each with its own generated key pair. > [!WARNING] > > Only create **one** integration from your Snowflake **organization admin account**. The `ORGANIZATION_USAGE` views return identical data across every account in the organization, so connecting more than one account causes duplicate data and inconsistent reporting. ## Prerequisites * `ACCOUNTADMIN` privileges in Snowflake * Access to your Snowflake **organization admin account** (required for `ORGANIZATION_USAGE` views) * Ability to create databases, roles, warehouses, and service users * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, view instructions, or disconnect. **Members** see **Admin Only** on connectable cards. ## Connect in nOps ### Where to open Snowflake * **To connect for the first time:** go to **Settings → Integrations** and click the **Snowflake** card. * **To manage existing connections:** open the same card or use **Settings → Account Status → Connected apps** and click the **Snowflake** chip. ### Connect steps 1. Click the **Snowflake** card. 2. Enter your **account identifier**: just the identifier, not the full URL (for example `ngb14322.us-east-1` from `ngb14322.us-east-1.snowflakecomputing.com`). 3. Click **Generate key pair**. nOps creates a 2048-bit RSA key pair for this connection and shows setup instructions. 4. Copy the generated SQL and run it in a Snowflake worksheet using `ACCOUNTADMIN`. > [!TIP] > > You don't need to look up your account identifier manually. Run this in a Snowflake worksheet to get the exact value: > > ```sql theme={"theme":{"light":"github-light","dark":"github-dark"}} > SELECT > LOWER(CURRENT_ACCOUNT_LOCATOR()) || '.' || > LOWER(REPLACE(REPLACE(CURRENT_REGION(), 'AWS_', ''), '_', '-')) AS account_identifier; > ``` ### Default configuration nOps uses the following defaults for every new Snowflake integration. You only provide the account identifier: | Setting | Default | | - | - | | Database | `nops` | | Schema | `PUBLIC` | | Warehouse | `nops` | | Username | `nops` | ## Run the setup SQL in Snowflake After you generate the key pair, nOps shows SQL split into four steps. Run them in order as `ACCOUNTADMIN` (steps 1–2) and then as the `nops` role (steps 3–4): 1. **Initial setup:** creates the `nops` role, the `nops` warehouse, the `nops` database, and grants `IMPORTED PRIVILEGES` on the `SNOWFLAKE` database so the role can read usage views. 2. **Create the service user:** creates a `SERVICE`-type user, attaches the nOps-generated RSA public key with `ALTER USER ... SET RSA_PUBLIC_KEY=...`, and grants the `nops` role to both the service user and your current user. 3. **Create views:** creates `query_history`, `warehouse_metering_history`, and `usage_in_currency_daily` views in the `nops` database that wrap the underlying `SNOWFLAKE.ACCOUNT_USAGE` and `SNOWFLAKE.ORGANIZATION_USAGE` tables, then grants `SELECT` to the `nops` role. 4. **Verify:** runs a test query as the `nops` role to confirm the setup works. nOps also shows a **Copy all** button to copy every step at once. ### Network configuration (optional) If your Snowflake account restricts access with a network policy, add the nOps IP to your allowlist. `SET ALLOWED_IP_LIST` **replaces** the entire list, so include your existing IPs alongside the nOps address: ```sql theme={"theme":{"light":"github-light","dark":"github-dark"}} ALTER NETWORK POLICY your_policy SET ALLOWED_IP_LIST = ('your.existing.ip.here', '52.11.169.55'); ``` ## Manage your connections Administrators can **view instructions** or **remove** individual Snowflake integrations from the Snowflake modal. Removing an integration deletes the stored RSA private key from AWS Secrets Manager and stops nOps from connecting to that account. nOps does not perform a live connectivity check when you connect. Verify the SQL ran successfully in Snowflake to confirm access. ## Troubleshooting * **Invalid account identifier:** enter only the identifier (for example `ngb14322.us-east-1`), not the full `https://...snowflakecomputing.com` URL. * **`RSA_PUBLIC_KEY` errors:** make sure you copied the full SQL block from step 2 without truncation; the key is a single long base64 string. * **Permission errors while running the SQL:** confirm you're using `ACCOUNTADMIN` for steps 1–2, and that you're logged into the organization admin account. * **No data after setup:** confirm the views in step 3 were created successfully and that the `nops` role has `SELECT` on them. * **Duplicate or inconsistent data across accounts:** you likely connected more than one account in the same organization; keep only the integration created from the org admin account. ## Security Snowflake authentication uses public key cryptography. No password is stored or transmitted. The private key is generated by nOps, stored securely in AWS Secrets Manager, and never shown after key generation completes. Only the public key is placed in your Snowflake account. # Twilio Source: https://help.nops.io/integrations/twilio Connect Twilio API credentials to nOps Inform ## Overview nOps uses your **Twilio Account SID**, **API key ID**, and **API key secret** to import communication service costs into Inform. Credentials are stored securely, validated before save, and are not shown again after you connect. ## Prerequisites * A Twilio account with permission to create API keys * nOps organization **administrator** access > [!NOTE] > > Only **admins** and **owners** can connect, re-validate, or disconnect. **Members** see **Admin Only** on connectable cards. ## Create Twilio API credentials 1. Sign in to the [Twilio Console](https://www.twilio.com/console). 2. Copy your **Account SID** from the dashboard home page. 3. Go to **Account → API keys & tokens** ([API keys](https://console.twilio.com/us1/account/keys-credentials/api-keys)). 4. Click **Create API Key**, name it (for example `nOps Integration`), choose **Standard** key type, and create the key. 5. Copy the **API key SID** and **API key secret** immediately. The secret is shown only once. > [!WARNING] > > If you lose the API key secret, create a new API key in Twilio and connect again in nOps. ## Connect in nOps ### Where to open Twilio * **To connect for the first time:** go to **Settings → Integrations** and click the **Twilio** card. * **To manage an existing connection:** go to **Settings → Account Status → Connected apps** and click the **Twilio** chip to re-validate or disconnect. ### Connect steps 1. Click the **Twilio** card or chip. 2. Enter **Account SID**, **API key ID**, and **API key secret**. 3. Click **Connect**. nOps validates the credentials with Twilio before storing them. ## Manage your connection Use **Re-validate** to test stored credentials or **Disconnect** to remove them. **Action required** indicates invalid or revoked keys. Verify the API key is active in Twilio and reconnect. ## Troubleshooting * **Invalid credentials:** re-check Account SID, API key ID, and secret; standard API keys should access billing data by default. * **No data:** allow up to **24 hours** for initial sync; confirm billable Twilio usage exists. * **Multiple accounts:** connect each Twilio account separately with its own credentials. ## Security Treat API key secrets like passwords. Rotate keys in Twilio if they may have been exposed. # Vercel Source: https://help.nops.io/integrations/vercel Connect Vercel platform billing and AI Gateway usage to nOps Inform ## Overview nOps connects to Vercel over two REST paths and can ingest either or both: * **Platform billing:** all Vercel spend (compute, bandwidth, storage, AI, and more) delivered in the **FOCUS v1.3** open cost standard, per project and per day. * **AI Gateway usage:** per-user, per-model spend and token usage for traffic routed through Vercel AI Gateway. Each path uses its own credential, so you provide only the credentials for the data you want. All credentials are validated before save and are never shown again in the nOps UI after you connect. > [!NOTE] > > The two paths use **different credentials from different places** in the Vercel dashboard: platform billing uses a **Vercel Access Token** (plus your **Team ID**), while AI Gateway uses a separate **AI Gateway API key**. You can connect one or both. ## Prerequisites * A Vercel **team** on a paid plan. AI Gateway usage (`/v1/report`) requires paid **Pro** or **Enterprise**. Hobby and Pro-trial teams cannot use it. Platform billing has no charges to report on a free Hobby team. * Permission to create an **Access Token** and an **AI Gateway API key** for the team. * nOps organization **administrator** access to connect or manage the integration. > [!NOTE] > > **Members** can view integration status on **Account Settings** and **Integrations**, but only **admins** (and owners) can connect, re-validate, or disconnect. Non-admins see an **Admin Only** indicator on the Vercel card. ## Create your Vercel credentials ### 1. Vercel Access Token (platform billing) 1. Sign in to the [Vercel dashboard](https://vercel.com/dashboard). 2. Open **Settings → Tokens** (Account Tokens page). 3. Click **Create**, enter a descriptive name (for example `nOps Integration`). 4. Set **Scope** to the **team** whose billing you want to connect, not your personal account. 5. Choose an expiration (or no expiration for a standing integration) and click **Create Token**. 6. Copy the token immediately. Vercel shows it only once. > [!NOTE] > > The token inherits the role of the account that creates it. To read billing, that account must have one of these team roles: **Owner, Member, Developer, Security, Billing, or Enterprise Viewer**. A read-only role is sufficient. ### 2. Vercel Team ID (platform billing) Open **Team Settings → General** and copy the **Team ID** (format `team_xxxxxxxx`). It is also visible in the dashboard URL while you are inside the team. ### 3. AI Gateway API key (AI Gateway usage) 1. In the Vercel dashboard, open **AI Gateway → API Keys**. 2. Click **Create key** and follow the prompts. 3. Copy the key immediately. The team is inferred from the key, so no Team ID is needed for this path. > [!WARNING] > > Treat both credentials like passwords. Do not share them in chat, email, or source control. Vercel **deactivates a token and any AI Gateway keys when the member who created them leaves the team**, so for a durable integration create them under a dedicated service account rather than a personal login. ## Connect in nOps Only nOps administrators can complete these steps. ### Where to open Vercel * **To connect for the first time:** go to **Settings → Integrations** and click the **Vercel** card (use **View all** if it is not in the preview). * **To manage an existing connection:** go to **Account Settings → Account Status → Connected apps** and click the **Vercel** chip to re-validate or disconnect. ### Connect steps 1. Click the **Vercel** integration card or chip. 2. Choose what to ingest: **Platform billing**, **AI Gateway**, or **Both**. 3. Provide the matching credentials: * Platform billing → paste your **Access Token** and **Team ID**. * AI Gateway → paste your **AI Gateway API key**. 4. Click **Connect**. nOps validates each credential before saving: * **Access Token** → a test call to `GET /v1/billing/charges` for the team (with a recent date range). * **AI Gateway key** → `GET /v1/credits`, then `GET /v1/report`. If validation succeeds, the status shows **Integrated** on the catalog card, or **Connected** in Account Status. ## Manage your connection After Vercel is connected, administrators can open the same card or chip to: * **Re-validate:** nOps re-checks the stored credentials without asking you to re-enter them. * **Disconnect:** removes the stored credentials and marks the integration as disconnected. If validation fails (for example, a token was revoked), the status changes to **Action required**. An administrator should reconnect with new credentials, or use **Re-validate** after fixing them in Vercel. ## What nOps stores nOps saves integration status and configuration (such as which paths are enabled, the Team ID, and when Vercel was connected and last validated) so your team can see whether the integration is active. Your Access Token and AI Gateway key are stored securely and are never shown again in the nOps UI after you connect. ## Troubleshooting ### Invalid token or key * Confirm you copied the full value with no leading or trailing spaces. * For the Access Token, confirm it is **scoped to the team** (not your personal account) and that the creating account has a billing-eligible role. * For AI Gateway, confirm the key was created under **AI Gateway → API Keys**. ### 403 on AI Gateway * The team is on **Hobby** or a **Pro trial**, which cannot use the AI Gateway reporting API. Upgrade to paid **Pro** or **Enterprise**, then reconnect. ### No billing data * Confirm the **Team ID** is correct and matches the token's scope. * A free Hobby team has no billing charges to return. Connect a paid team. * Allow time for the first sync to complete after connecting. ### Action required * A stored credential was revoked, expired, or created by a member who left the team. Create new credentials and connect again, or use **Re-validate** after fixing them in Vercel. ### Admin Only on the card * You are signed in as a **member**, not an administrator. Ask an org admin to connect or manage Vercel. ### Still stuck? Contact your nOps administrator or nOps support with the time of the error (never the token or key itself). ## Reference * [Vercel FOCUS billing charges API](https://vercel.com/docs/rest-api/billing/list-focus-billing-charges) * [Vercel access tokens](https://vercel.com/kb/guide/how-do-i-use-a-vercel-api-access-token) * [AI Gateway authentication](https://vercel.com/docs/ai-gateway/authentication-and-byok/authentication) * [AI Gateway REST API](https://vercel.com/docs/ai-gateway/sdks-and-apis/rest-api) # Budgets Source: https://help.nops.io/operate/budgets Set spend targets from Explorer reports, track actuals by period, and get alerted on overruns. **Budgets** lets you set spend targets tied directly to an Explorer report, track actual spend against those targets period by period, and get notified before you go over. Unlike a standalone budgeting tool, every nOps budget inherits its dimensions and filters from an Explorer report, so what you budget for is always exactly what you're already analyzing. > [!NOTE] > > Budgets requires the **Operate** plan. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Operate → Budgets**, or go to [clara.nops.io/budgets](https://clara.nops.io/budgets). 3. Click **New budget**, choose an Explorer report to base it on, and configure the budget settings. 4. Review the generated budget by period, adjust as needed, and save. Saving a new budget opens its detail page so you can review the plan and configure alerts. ## Key features ### Budgets landing page * Toggle between **Grid** and **List** view (your choice is remembered). * **Portfolio summary** cards show totals across your filtered budgets: **Target (current)**, **Actual (current)**, **Avg % of budget**, and **Over budget** count. This is a summary of your own organization's budgets. For rolling up usage across multiple organizations you administer, see [Portfolio Portal](/portfolio/introduction). * Search by budget name or linked report name. * **Grid** view shows mini trend charts and over-budget badges per budget. Budgets that back AI seat tracking also show an **AI (Seats)** category badge. **List** view lets you expand rows for per-dimension breakdowns (**Budget (current)**, **Actual**, **% of budget**, **Variance**). ### Creating a budget Every budget starts from an Explorer report: 1. Click **New budget** and select the Explorer report to link. The budget inherits that report's dimensions and filters. 2. Fill in **Budget settings**: * **Basics:** Name, Status (Draft or Active), Target type, Budget type. * **Schedule:** Period (Daily, Monthly, Quarterly, Annually), Start date, Number of periods, Lookback periods. * **Baseline:** Starting value (**Previous Month**, **Average Monthly Lookback**, or **Custom**), Growth rate (%), and an optional **Normalization period**. 3. Review the auto-generated **Budget by period** grid, which is live-populated as you create the budget. 4. Optionally configure **Threshold alerts** before saving. **Target type** determines how the budget behaves: | Type | Behavior | | - | - | | **Budget** | Enforceable target. Supports threshold alerts and shows over/under status. | | **Tracking** | Monitor spend against a target without treating it as a hard limit. | **Budget type** determines how budget values are edited: | Type | Behavior | | - | - | | **Bottom Up** | Edit each dimension's target per period; totals roll up automatically. | | **Top Down** | Edit a period's total target; it distributes proportionally across dimensions. | ### Budget by period * Budget values are pre-populated using your **Starting value** and **Growth rate**, based on your Explorer report's spend. * On create, edit individual cells directly or use **Refresh from lookback** to regenerate values from the linked report. * **Download CSV** / **Upload CSV** to make bulk edits offline and re-import them. * Once a budget is saved, a **Budget vs actual** chart tracks real spend against your plan by period. ### Change or refresh the linked report Open a budget and use **Change Report** to link a different Explorer report, or **Update From Report** on the report card to refresh the budget by period using the current lookback data, useful after the underlying report's filters or dimensions change. **Refresh from lookback** in the Budget by period section is available during initial creation; on an existing budget, use **Update From Report** instead. ### Threshold alerts Turn on **Enable alerts**, then configure rules from the budget's **Threshold alerts** section. Use **Manage all alerts** to view, edit, or delete multiple alerts per budget. | Field | What it does | | - | - | | **Threshold type** | **Percent over budget**, **Percent under budget**, or **Amount over budget**. | | **Threshold value** | The percentage or dollar amount that triggers the alert. | | **Minimum spend** | Optional dollar floor. Your threshold is only checked once actual spend reaches this amount, avoiding noisy alerts early in a period. | | **Aggregation** | **Single dimension** or **All dimensions combined**. | | **Alert frequency** | Which period rollovers to evaluate (defaults to the budget's own period). | | **Email recipients** | Organization members who receive the alert. | | **Slack / Teams channels** | Optional connected chat channels for alert delivery. | | **Dimensions to monitor** | Which dimensions the alert applies to; exclude dimensions you do not want monitored. | Alerts are evaluated daily at **12:00 PM Eastern** for **Active** budgets only. Each alert shows **Active** or **Inactive** status; toggle **Alert is active** / **Alert is paused** when editing. Use **Test alert** or **Evaluate now** to preview delivery without waiting for the daily run. ### Share budget report Separate from threshold alerts, use **Share report** to send a digest of a budget's status by email, Slack, or Teams: * Opens the **Share budget report** dialog with **Send now** or **Schedule**. * **Once** or **Recurring** (daily, weekly, monthly), in your timezone. * Add **Email recipients**, optional **Slack / Teams channels**, a **Subject**, and an optional **Message**. ### Budget view in Explorer Open [Explorer](/inform/explorer) and use **View By** to overlay a budget on your chart. This requires the **Inform** tier. Without it, the budget overlay is locked with an upgrade prompt. When enabled, you get: * A target line on the spend chart, labeled with your budget name (for example, **Production Target**). * A **Budget Trend** stacked bar chart below the main chart, titled with your budget name. * A **Budget Targets** table with target vs. actual by dimension, titled with your budget name. Handy for checking spend against a plan without leaving your analysis. ### AI seat tracking AI seat tracking is no longer set up from inside a cloud budget. It now has its own area in the sidebar under **AI**, where a seat tracking project holds your connected providers, seat roster, allocation groups, budgets, limit requests, and automation. Start at [AI](/ai/introduction), or go straight to [Set up AI seat tracking](/ai/setup) to create your first project. A seat tracking project is still backed by a budget, so two things remain visible here: * Budgets that back a project show an **AI (Seats)** category badge on the budgets landing page, in both **Grid** and **List** view. * Older `?tab=ai-seats` links to a budget redirect into the matching section of the AI area, so existing bookmarks keep working. Everything else (choosing providers, the seat table, editing seat limits, and [Automated Rebalance](/ai/automated-rebalance)) lives under **AI**. ### Deleting a budget Only the budget creator or an organization administrator can delete a budget. ## FAQs > **Do I need an Explorer report to create a budget?** > > Yes. Every budget is linked to an Explorer report and inherits its filters and group-by dimensions. Create or choose a report in Explorer first, then start a budget from it (or use **Create budget** directly from the Reports list). > **What's the difference between Budget and Tracking target types?** > > **Budget** targets are enforceable. You can attach alerts and see over/under status. **Tracking** targets are for monitoring spend against a goal without treating it as a hard limit. Both types support threshold alerts in the current product. > **What's the difference between Bottom Up and Top Down planning?** > > **Bottom Up** lets you edit each dimension's target directly, and period totals roll up automatically. **Top Down** lets you set a period's total target, which then distributes across dimensions proportionally. > **How often are budget alerts evaluated?** > > Once per day, at 12:00 PM Eastern, for budgets with **Active** status. If a threshold is crossed, notifications go to the alert's email and chat recipients. > **Can I bulk-edit my budget?** > > Yes. Use **Download CSV** in the Budget by period section to export a template, make your edits offline, and **Upload CSV** to bring them back in. > **How is a threshold alert different from Share report?** > > Alerts are threshold-triggered. They fire only when spend crosses a rule you define. **Share report** sends a scheduled or on-demand digest regardless of whether any threshold was crossed. > **Why can't I overlay a budget in Explorer?** > > Budget overlays in Explorer require the Inform tier. Upgrade to Inform to add target lines, the Budget Trend chart, and the Budget Targets table to your Explorer view. > **Where did AI seat tracking on a budget go?** > > It moved to its own area in the sidebar under **AI**. Providers, the seat roster, seat limits, limit requests, and automated rebalance are all configured on a seat tracking project instead of on a budget. See [AI](/ai/introduction). > **Which Claude Enterprise API scopes do I need for AI seat tracking?** > > At minimum: **`read:analytics`**, plus **`read:members`** and **`read:spend_limits`** for per-seat spend and limits. Add **`write:spend_limits`** only if you want nOps to change per-user Claude limits. See [Claude.ai (Enterprise)](/integrations/claude-enterprise#api-key-scopes). ## Related * [Explorer](/inform/explorer): build the report a budget is based on, and overlay budgets on your charts * [AI](/ai/introduction): track AI seat spend, allocation, budgets, and limit requests * [Automated Rebalance](/ai/automated-rebalance): how nOps earns and keeps the right to change seat limits on its own * [Claude.ai (Enterprise)](/integrations/claude-enterprise): connect Claude Enterprise for usage data and AI seat tracking * [Cursor](/integrations/cursor-admin-api): connect Cursor for AI seat tracking * [Business Unit Economics](/operate/business-unit-economics): track cost per unit from Explorer spend and business metrics * [Reports](/inform/reports): see all budget alerts across your organization in one place * [Home page](/platform/home): choose where nOps opens when you sign in # Business Unit Economics Source: https://help.nops.io/operate/business-unit-economics Tie Explorer spend to business metrics like customers or seats, then track cost per unit over time. **Business Unit Economics** lets you map cloud spend from a **Cost Allocation** report to a business metric (customers, seats, users, or any unit you define) so you can track **cost per unit** by dimension and month. Each saved configuration is called a **model**: one Cost Allocation report, one unit, and the unit counts you enter per dimension. > [!NOTE] > > Business Unit Economics requires the **Operate** plan. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Operate → Business Unit Economics**, or go to [clara.nops.io/business-unit-economics](https://clara.nops.io/business-unit-economics). 3. Click **Create model**, choose a report saved on Explorer's **Cost Allocation** tab, pick or create a **Unit** (e.g. Customers), and set your **Start month** and **Reporting sample month**. 4. Click **Create & calculate**, enter unit counts in the **Units by dimension** table, then **Save & calculate**. You can also start from Explorer with a Cost Allocation report already open. Use **Create model** from the Reports list, or open `/business-unit-economics/new?reportId=...` with a report ID to pre-select a report. > [!NOTE] > > Only shared or global reports saved on the **Cost Allocation** tab (grouped by allocation value, not a raw dimension) are eligible. If your report doesn't show up when creating a model, open [Explorer](/inform/explorer), switch to the **Cost Allocation** tab, group by an allocation value, and save the report there first. ## Key features ### Landing page * **Portfolio snapshot** cards summarize your models at a glance: **Models**, **Tracked spend**, **Units entered**, and **Avg coverage**. * **Models by unit** groups models under each unit name. Each row shows the linked report, cost, units entered, **Cost / unit**, and **Coverage** for the reporting sample month. * The **Units** sidebar lets you create reusable metrics (e.g. Customers, Seats) and attach them when building models. You cannot delete a unit that still has models linked to it. * Search and open any model to edit settings or unit counts. Use **Delete** to remove a model you no longer need. ### Creating a model Every model links one Cost Allocation report to one unit: 1. Click **Create model** and select a report saved on Explorer's **Cost Allocation** tab. Spend rows follow that report's allocation values and filters. 2. In **Settings**, fill in: * **Explorer report:** the Cost Allocation report whose spend drives the model. Use **Change** to pick a different report, or **Open Explorer** to review it. * **Unit:** a reusable metric from the dropdown, or **+ New unit** to create one on the spot. * **Start month:** the first month you want to track unit counts (defaults to the previous calendar month). * **Reporting sample month:** the month used for **Cost**, **Cost / unit**, and summary cards (defaults to the current calendar month). * **Granularity:** currently **Monthly** only. 3. Click **Create & calculate** to save settings and load the units table. You can only save one model per **report + unit** combination. The same unit on different Cost Allocation reports creates separate models. ### Units by dimension table After settings are saved, the **Units by dimension** section shows one row per Explorer dimension value: | Column | What it shows | | - | - | | **Dimension** | The report's grouping value. Rows with no matching dimension appear as **Unallocated**. | | **Cost** | Spend for that dimension in the **reporting sample month**. | | **Cost / unit** | Cost divided by units entered for the reporting sample month. | | Monthly columns | Editable unit-count inputs for each month from your start month through today (labeled **Number of** plus your unit name). | Use **Save & calculate** to persist your counts and refresh cost-per-unit values. **Summary** cards above the table show **Total cost**, total units entered, and **Cost per unit** for the reporting sample month. ### CSV workflow Bulk-edit unit counts offline: * **Template:** download a CSV with **Dimension** and monthly **Units** columns (for example, `July 2026 - Units`) for each month from your start month through today. * **Upload CSV:** import counts by matching the **Dimension** column. Only rows that match existing dimensions are updated. * **Download:** export the full table, including cost and cost-per-unit columns, once the model is saved. ### Manage reports From a saved model, click **Manage Reports** to deliver a summary by email, Slack, or Teams: * **Send now:** deliver immediately. * **Schedule:** once or recurring (daily, weekly, monthly), in your timezone. * Add **Email recipients**, optional **Slack / Teams channels**, a **Subject**, and an optional **Message**. Email deliveries include an HTML summary (total cost, total units, cost per unit) and a CSV attachment. Manage recurring schedules from [Reports](/inform/reports) under the **Business Unit Economics** tab. ### Business Unit Economics view in Explorer Open [Explorer](/inform/explorer) and use the **View By** menu to overlay cost per unit on your chart: * Pick a model to add a **Cost per unit** series for each dimension on the chart. * A side panel shows summary cards and a read-only table for the selected month. * Models appear in the picker as your report name and unit name joined together (for example, **Production spend — Customers**). Budget and Business Unit Economics overlays cannot be active at the same time. ## FAQs > **Do I need an Explorer report to create a model?** > > Yes, and specifically a **Cost Allocation** report. Every model is linked to a shared or global report saved on Explorer's Cost Allocation tab (grouped by allocation value) and inherits its filters and dimensions. Create or choose a Cost Allocation report in Explorer first, then start a model from the Business Unit Economics page or from the Reports list. > **Can I link the same unit to multiple reports?** > > Yes. Each **Cost Allocation report + unit** pair is a separate model. For example, you can track cost per customer on both a production report and a staging report. > **What does Unallocated mean?** > > **Unallocated** appears when grouped spend from your Explorer report does not sum to the account total, typically spend that could not be matched to a dimension value. Enter unit counts for Unallocated if you want cost per unit for that remainder. > **What happens if I change the linked Explorer report?** > > Use **Change** in Settings to link a different report. Spend rows and dimensions will follow the new report's filters and grouping. You may need to re-enter or re-import unit counts for the updated dimensions. > **How is Business Unit Economics different from Budgets?** > > **Budgets** set spend targets and alert you when actuals cross thresholds. **Business Unit Economics** divides spend by business metrics you enter (customers, seats, etc.) to show **cost per unit** over time. Both can overlay on Explorer charts, but only one overlay type can be active at a time. > **How is this different from Cost Allocation?** > > Cost Allocation is where you define showback rules and build the report: grouping spend by allocation values (departments, teams, products, etc.). Business Unit Economics builds on top of a saved Cost Allocation report: it takes that allocated spend and divides it by unit counts you provide (customers, seats, etc.) to show **cost per unit**. You need a Cost Allocation report before you can create a Business Unit Economics model. > **Can I bulk-edit unit counts?** > > Yes. Use **Template** to download a CSV, fill in unit counts offline, and **Upload CSV** to import them. Match rows by the **Dimension** column and use column headers like `July 2026 - Units`. ## Related * [Explorer](/inform/explorer): build the report a model is based on, and overlay cost per unit on your charts * [Budgets](/operate/budgets): set spend targets and threshold alerts from Explorer reports * [Reports](/inform/reports): manage scheduled Business Unit Economics deliveries # Cloud & SaaS Contract Tracker Source: https://help.nops.io/operate/contract-tracker Track commitment burn-down against actual spend from any connected cloud or SaaS integration—PPAs, EDPs, cross-service agreements, and marketplace caps. **Cloud & SaaS Contract Tracker** helps you monitor commitment utilization against real spend. Create contracts for enterprise agreements, PPAs, EDPs, or scoped provider and SaaS spend, then watch burn-down progress over time with forecasts and period-by-period summaries. Spend is pulled from **any integration connected to your organization**—cloud providers (AWS, GCP, Azure) and third-party tools (for example Databricks, Snowflake, and other SaaS billing sources)—using the same dimensions as [Explorer](/inform/explorer). Product services, cost entities, billing entities, and marketplace products all appear in the pickers based on what is flowing into nOps. ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Operate → Cloud & SaaS Contract Tracker**, or go to [clara.nops.io/contract-tracker](https://clara.nops.io/contract-tracker). 3. Click **Add contract** and walk through the three-step setup wizard. 4. After you save, the burn-down chart loads for your new contract. If you already have contracts, the page opens on your most recently updated one. > [!NOTE] > > Contract Tracker requires the **Operate** entitlement and the **Contract Tracker** permission for your role. If you do not see it in the sidebar, ask your organization administrator. ## Key features ### Contract list and switching When you have one or more contracts, use **Manage Contracts** in the page header to: * **Search** by contract name, tracking summary, or dates. * **Switch** the active contract—the chart and summary update for your selection. * **Copy link** to share a direct URL to the current contract (`/contract-tracker/{id}`). * **Create new** to start another contract without leaving the page. Each row shows the contract name, what it tracks, its date range, and total commitment. ### Creating a contract (three-step wizard) Click **Add contract** to open the wizard. #### Step 1 — Track Define what spend counts toward the commitment: * **Contract name** — A display name for cards and charts (for example, *AWS Enterprise Agreement 2026*). * **Track by** — How spend is grouped: | Mode | Use when | | - | - | | **Product service** | The commitment applies to specific product or service lines (for example EC2, S3, Databricks, or Snowflake). | | **Cost entity** | The commitment applies to selected billing cost entities. | | **Cross service** | The commitment spans billing entities, marketplace products, cost entity legal names, and product services in one agreement—useful for multi-provider or enterprise-wide deals. | Select at least one tracked value for your chosen mode. For **Cross service**, pick from: * **Cost entity** (billing entities such as AWS or AWS Marketplace) * **Marketplace entities** (individual AWS Marketplace products) * **Cost entity legal name** * **Product service** > [!NOTE] > > If you select **AWS Marketplace** as a billing entity, individual marketplace product pickers are disabled—the marketplace cap (see Step 2) applies to total AWS Marketplace spend instead. #### Step 2 — Duration Set the contract window and commitment amounts: * **Period** — How commitments are divided: **Monthly**, **Quarterly**, or **Annually**. * **Start date** and **End date** — The full contract term. * **Discount percentage** — For **Cross service** contracts only (for example, your EDP discount). * **Marketplace cap allocation** — Shown when AWS Marketplace is in scope. Set the percentage of each period's commitment that can apply to Marketplace spend before the cap is exhausted (default 50%). * **Commitments** — Enter the dollar commitment for each period in the contract (one row per month, quarter, or year, depending on **Period**). #### Step 3 — Review Confirm name, tracking mode, dates, discount, marketplace cap (if any), tracked values, and per-period commitments. Click **Create contract** to save. ### Burn-down chart The main chart shows how actual spend compares to your commitment over the contract term: * **Stacked bars** — Monthly spend broken out by tracked entity (product service, cost entity, etc.). * **Monthly Target** (dashed line) — The prorated commitment target for each month. * **Remaining commitment** (line) — How much commitment is left at each point in time. * **Forecast** — Future months with projected spend appear with a lighter, dashed bar style so you can see where you are headed before the period ends. The chart header also shows **Actual**, **Commitment**, and **Variance** for a quick read on whether you are ahead or behind. ### Period summary cards Below the chart, summary cards break the contract into commitment periods (months, quarters, or years). Each card shows: * **Actual spend** vs. **target** for that period * **Variance** and **On Track** / **Behind** status * A progress indicator for the period Use these cards to spot which half of a multi-year agreement is running hot or cold. ### Editing, deleting, and sharing * **Edit** — Open **Manage Contracts**, then use the pencil icon on a row you are allowed to change. The same three-step wizard opens with existing values filled in. * **Delete** — Use the trash icon on an allowed row. Deletion is permanent and removes the contract and its burn-down history from your organization. * **Share** — Use **Copy link** in **Manage Contracts** so teammates can open the same contract directly. Only the contract **creator** or an organization **administrator** can edit or delete a contract. Everyone with access can view contracts and copy links. ## FAQs > **What spend does Contract Tracker include?** > > Contract Tracker uses cost and usage from **every integration connected to your organization**—the same unified data and dimensions you see in Explorer. That includes major cloud providers (AWS, GCP, Azure) and third-party SaaS billing sources (for example Databricks and Snowflake) once they are onboarded in [Integrations](/platform/integrations). Depending on how you configure each contract, tracked spend can be scoped by product service, cost entity, billing entity, or marketplace product. It does not replace provider-native commitment consoles; it gives you a unified burn-down against the commitments you define in nOps. > **When should I use Product service vs. Cost entity vs. Cross service?** > > Use **Product service** when the agreement is scoped to specific services or SKUs (cloud or SaaS). Use **Cost entity** when billing entities define the boundary (for example, a payer account or vendor entity). Use **Cross service** for enterprise-wide deals that combine multiple billing entities, marketplace products, legal entities, and services—with optional EDP discount and marketplace cap settings where AWS Marketplace is in scope. > **What is the marketplace cap allocation?** > > For cross-service contracts that include AWS Marketplace, the cap limits how much of each period's commitment can be consumed by Marketplace spend. If you select **AWS Marketplace** as a billing entity, the cap applies to all Marketplace spend—you do not need to pick individual marketplace products. If you pick specific marketplace products instead, you can still set the cap percentage per period. > **How is the forecast calculated?** > > Future months on the chart use projected spend based on your historical burn rate in the contract. Forecast bars are styled differently from actuals so you can distinguish recorded spend from projections. > **Who can create or change contracts?** > > Any user with Contract Tracker access can create contracts and view burn-down data. Only the user who created a contract or an organization administrator can edit or delete it. > **Why does the page open on a specific contract automatically?** > > If you have saved contracts, visiting `/contract-tracker` redirects to your most recently **updated** contract, or the one in the URL. Use **Manage Contracts** to switch, or share a link that includes the contract ID (`/contract-tracker/{id}`). > **Do I need integrations connected first?** > > Yes. Connect the cloud accounts or third-party tools whose spend you want to track via [Integrations](/platform/integrations). Once billing data is flowing into nOps, the same dimensions you use in Explorer appear when you build a contract. If a vendor or service does not show up in the dimension pickers, confirm that integration is active and has recent data in Explorer. ## Related * [Explorer](/inform/explorer) — analyze spend by the same dimensions used in contract tracking * [Budgets](/operate/budgets) — set periodic spend targets and threshold alerts from Explorer reports * [Business Unit Economics](/operate/business-unit-economics) — tie cloud spend to business metrics like customers or seats * [Dashboard](/platform/dashboard) — organization overview and cloud spend summary # Commitment Inventory Source: https://help.nops.io/optimize/commitment-inventory View AWS, GCP, and Azure commitments and AWS utilization in one place. Available on every plan when your cloud integrations are active. **Commitment Inventory** is a multi-cloud read-only view of your active Reserved Instances, Savings Plans, Committed Use Discounts, and Azure Reservations. Filter by provider, review utilization on AWS, and share a filtered link with your team. Viewing is included on every nOps plan. You do not need an Inform subscription to open Inventory or load commitment data. Email delivery and recurring schedules for inventory reports still require **Inform** (see [Email and schedules](#email-and-schedules) below). ## Get started 1. Sign in to [nOps](https://clara.nops.io/dashboard). 2. In the sidebar, open **Optimize → Commitments → Inventory**, or go to [clara.nops.io/commitment-management/inventory](https://clara.nops.io/commitment-management/inventory). 3. Use the **All clouds**, **AWS**, **GCP**, and **Azure** tabs to focus on one provider or see everything together. ## Who can access Inventory | Requirement | Details | | - | - | | **Role** | **Members**, **Admins**, and **Owners** can view Inventory by default. | | **Plan** | Viewing is **free**. No Inform or Operate subscription is required. | | **Integration** | Each cloud tab needs an **active** integration for that provider. If a provider is not connected, its tab stays visible but prompts you to connect from **Settings → Cloud Onboarding**. | > [!NOTE] > > Only **Admins** and **Owners** can add or manage cloud integrations in **Settings**. Members can view Inventory once an integration is active. See [Users and roles](/platform/users). ## Provider tabs and integrations Inventory always shows tabs for **All clouds**, **AWS**, **GCP**, and **Azure**. * **Active integration:** Selecting the tab loads commitments (and AWS utilization when relevant) for that provider. * **No active integration:** Clicking the tab opens a short prompt to connect that provider from Settings instead of switching the table to an empty view. To connect a provider, use **Settings → Cloud Onboarding** or follow the provider guides: > **[AWS](/aws/integration-setup)** > > Savings Analysis onboarding, then optional [Commitment Management](/aws/commitment-management-setup) for full inventory reads and purchasing. > **[Google Cloud](/gcp/integration-setup)** > > Billing export + service account, then optional [Commitment Management](/gcp/commitment-management-setup) for CUD inventory. > **[Microsoft Azure](/azure/integration-setup)** > > Savings Analysis onboarding, then optional [Commitment Management](/azure/commitment-management-setup) for reservation and savings plan inventory. If Inventory cannot read commitments for a scope (for example, missing commitment-management roles on a subscription), nOps surfaces a warning on the page and links to the matching setup guide. Other connected scopes may still load. ## What you see on the page ### Summary cards High-level counts and spend signals across the commitments currently loaded for your filter. ### AWS utilization When **AWS** is in scope and your organization has an active AWS integration, an **AWS utilization** panel shows Reserved Instance and Savings Plan utilization trends from Cost Explorer. ### Commitments table Group and sort commitments by account, project, or subscription. Expand a group for type, region, term, hourly commitment, and dates. Use table filters for status, type, and text search. ### Refresh and share * **Refresh** reloads inventory and utilization for the active provider filter. * **Manage reports** (bookmark menu) copies a link that preserves your current filters so teammates open the same view. ## Email and schedules Sending a one-off inventory email or creating a recurring schedule from Inventory requires **Inform** (`report_delivery` entitlement, the same capability used for Explorer and recommendation report emails). | Action | Plan required | | - | - | | View Inventory and utilization | Any plan (with active integration) | | Copy filtered link | Any plan | | Send now or schedule inventory email | **Inform** (or Operate, which includes Inform) | You can also manage existing **Inventory** email schedules from **Inform → Reports** when you have access to the Reports page. ## Related pages > **[Commitment Management setup](/aws/commitment-management-setup)** > > Optional AWS, GCP, and Azure guides for purchasing and lifecycle operations. Not required just to open Inventory. > **[Integrations](/platform/integrations)** > > Connect cloud accounts and check integration health under **Settings → Account Status**. > **[Reports](/inform/reports)** > > Manage saved Explorer views, recommendation schedules, budget alerts, and inventory email schedules. > **[Users and roles](/platform/users)** > > Invite teammates and understand default access to commitment features. # Home page Source: https://help.nops.io/platform/home Choose where nOps opens when you sign in, and set a default landing page for your team. ## Overview **Home** is the page nOps opens when you sign in. You choose what it is: a page like Anomalies, or a saved report, cost allocation, or dashboard in Explorer. The **Home** item at the top of the sidebar shows the name of the page you picked, and one click takes you back to it. > [!NOTE] > > nOps no longer has a separate organization dashboard. Everything it showed now lives in a dedicated place. See [Where things moved](#where-things-moved). ## What you see by default If neither you nor your admin has picked a home page, nOps opens: * **Anomalies**, if your organization has the Inform plan. * **Explorer**, otherwise. ## Change your home page The quickest way is the cog in the sidebar. You don't need to open Settings. **1. Open the picker** In the sidebar, click the cog next to your **Home** item (**Change home page**). The item is labeled with the page you're on now, such as **Anomalies**. The **Home page** picker opens with the description "Where nOps opens when you sign in." **2. Choose a page** Pick one of the following: * **Pages:** **Anomalies**, **Recommendations**, or **AI Tracking**. A check mark shows your current home page, and a lock means the page needs a plan upgrade. * **Explorer:** **Reports**, **Cost allocation**, or **Dashboards**. Each shows how many you have. Click one to see the list, then pick the report, cost allocation, or dashboard you want. **3. Confirm** Your choice applies right away. The next time you sign in, nOps opens there. Use the search box at the top of the picker (**Search pages, reports, dashboards**) to find one by name. ### Go back to the default When you've picked your own home page, a **Set to default** button appears in the picker. Click it to return to your organization's default (or the built-in default if your admin hasn't set one). > [!TIP] > > Pick the Explorer dashboard your team checks every morning. You'll land on it each time you sign in. See [Explorer dashboards](/inform/explorer-dashboard). ## Set a default for your organization Admins can choose where new users land. This is separate from the cog, which only changes your own home page. 1. Go to **Settings → Organization Settings → Organization Details**. 2. In the **Default landing page** card, click **Change default** and pick a page. 3. To remove it, click **Clear org default**. The card then shows "Built-in default (Anomalies or Explorer)." Members can still pick their own home page. Your default only applies to people who haven't. ## Where things moved | Looking for... | You'll find it in... | | - | - | | Spend and trends | [Explorer](/inform/explorer) | | Integration status for AWS, GCP, and Azure | **Settings → Account Status** | | Chatting with Clara | [Ask Clara](/clara/clara-chat) | | Canvas templates and shared canvases | [Canvas](/clara/canvas) | | Scheduled Clara results | [Ask Clara](/clara/clara-chat#scheduled-questions) | > [!NOTE] > > Old links to `/dashboard` still work. They take you to your home page. ## FAQs > **Can I have a different home page than my teammates?** > > Yes. Your choice is personal. Pick it with the cog next to **Home**, and it only changes where nOps opens for you. > **Why is a page locked in the picker?** > > The page is part of a plan your organization doesn't have yet. Contact your account team to upgrade. *** > **[Ask Clara](/clara/clara-chat)** > > Chat with Clara, review history, and connect MCP clients. > **[Explorer](/inform/explorer)** > > Dig into spend by service, account, tag, and more. # Integrations Source: https://help.nops.io/platform/integrations Connect cloud provider accounts and third-party tools to nOps for cost visibility, commitment management, and usage insights. ## Overview nOps supports two kinds of integrations: * **Cloud providers:** AWS, GCP, and Azure accounts for billing data, recommendations, and commitment management. * **Third-party apps:** developer and SaaS tools (such as Cursor) for usage and billing visibility. Cloud and third-party integrations are managed from **Settings** in the nOps dashboard (`/settings`). *** ## Cloud provider integrations Once connected, nOps pulls billing and usage data from your cloud accounts into the platform, enabling cost visibility on your canvases and powering commitment management features. **Commitment Inventory** ([Optimize → Commitments → Inventory](/optimize/commitment-inventory)) is available on every plan for members, admins, and owners when the relevant cloud integration is **active**. Scheduled inventory emails require **Inform**. nOps supports three cloud providers: > **[AWS](/aws/integration-setup)** > > Onboard your payer account for **savings analysis**. We’ll guide you through linking billing data securely so nOps can analyze spend and recommendations. > **[Google Cloud](/gcp/integration-setup)** > > Connect via a service account with BigQuery access to your billing export datasets. > **[Microsoft Azure](/azure/integration-setup)** > > Connect via admin consent and a service principal with RBAC roles for cost management and FOCUS exports. Use **Settings → Cloud Onboarding** to add a new cloud account. Connected accounts appear under **Settings → Account Status → Cloud accounts**. **Permissions:** Only **Admin** and **Owner** users in your nOps organization can add, remove, or manage cloud integrations (including connecting AWS and using **Manage** on an existing integration). **Members** cannot. See [Users and roles](/platform/users). *** ## Third-party integrations Connect developer tools and SaaS products from **Settings → Integrations** (`/settings/integrations`, or **View all** from the Settings preview). Connected apps also appear under **Settings → Account Status → Connected apps**. **Permissions:** Only **admins** and **owners** can connect, re-validate, or disconnect third-party apps. **Members** can view status but see **Admin Only** on connectable integrations. ### Cost integrations (Inform) These integrations bring third-party spend into Inform for unified cost visibility, attribution, and optimization. > **[Datadog](/integrations/datadog)** > > Retrieve and analyze Datadog cost data for unified expense visibility and resource allocation optimization. > **[MongoDB Atlas](/integrations/mongodb-atlas)** > > Monitor MongoDB Atlas expenses across projects with organization API keys and centralized cost management. > **[Fastly](/integrations/fastly)** > > Bring Fastly CDN cost and usage into Inform for attribution and optimization. > **[Cloudflare](/integrations/cloudflare)** > > Bring Cloudflare product usage and contracted cost into Inform. Self-serve accounts only; cost appears after the daily sync. > **[OpenAI](/integrations/openai)** > > Track OpenAI API usage costs with detailed model usage and spending patterns. > **[Anthropic (Platform)](/integrations/anthropic)** > > Analyze Claude Platform (Console) API usage and billing in Inform with real-time cost insights. > **[Claude.ai (Enterprise)](/integrations/claude-enterprise)** > > Claude Enterprise (claude.ai) usage in Inform and per-user AI seat tracking (with `read:members` and `read:spend_limits`; optional `write:spend_limits` for limit edits). > **[ChatGPT (Enterprise)](/integrations/openai-enterprise)** > > ChatGPT Enterprise and Codex seat spend from a workspace Admin key, for cost visibility and per-user AI seat tracking. > **[Twilio](/integrations/twilio)** > > Monitor Twilio communication costs with visibility across products and usage categories. > **[Amazon Bedrock](/integrations/amazon-bedrock)** > > Track Bedrock AI model usage and costs through Model Invocation Logs. Connect one or more S3 buckets or prefixes for comprehensive AI spend visibility. > **[Databricks](/integrations/databricks)** > > Export Databricks system billing tables to a dedicated S3 prefix. nOps reads usage and list prices; you schedule the notebook in your own workspace. > **[Snowflake](/integrations/snowflake)** > > Bring Snowflake warehouse credit consumption, query history, and organization-level spend into Inform using key-pair authentication. > **[Vercel](/integrations/vercel)** > > Connect Vercel platform billing and AI Gateway usage for unified cost visibility. ### Developer and management tools > **[Cursor](/integrations/cursor-admin-api)** > > Connect your Cursor team with a Team Admin API key for usage visibility and AI seat tracking. > **[Atlassian](/integrations/atlassian)** > > Track Atlassian usage and user activity to identify idle users and optimize license allocation. > **[GitHub](/integrations/github)** > > Connect a GitHub personal access token for organization or enterprise billing, usage, and seat data in Inform. This is separate from GitHub Issues for recommendations. > **[GitLab](/integrations/gitlab)** > > Connect a GitLab.com access token for subscription, seat, and usage-quota data in Inform. This is separate from GitLab Issues for recommendations. ### Issue trackers (Notifications) Connect Jira and Linear from **Settings → Integrations → Notifications** (`/settings/integrations?tab=notifications`) to create issues from nOps recommendations. See [Issue creation from recommendations](/platform/issue-tracker-notifications) for provider capabilities, access categories, and the distinction between issue creation and cost integrations. Email, Slack, and Teams notification delivery are configured separately under **Settings → Notifications** (`/settings/notifications`). For Slack notifications, SSO, and other platform integrations outside this catalog, see the [nOps integrations overview](https://help.nops.io/docs/agents-integrations/integrations) on the help site. *** ## AWS onboarding Follow these guides to connect your AWS payer account for cost and usage visibility. > **[Integration setup](/aws/integration-setup)** > > Savings analysis onboarding: connect billing export and a secure cross-account role in a few steps. > **[Commitment management](/aws/commitment-management-setup)** > > Optional second step after AWS integration: CloudFormation + StackSets roles, then in-product verification. *** ## Google Cloud Platform onboarding Follow these guides to connect your GCP billing data and enable commitment management. > **[Prerequisites](/gcp/prerequisites)** > > Set up billing exports and prepare your GCP environment for nOps. > **[Integration setup](/gcp/integration-setup)** > > Link your GCP billing data to nOps, configure Domain Restricted Sharing when required, and grant service account permissions. > **[Commitment management](/gcp/commitment-management-setup)** > > Configure nOps to manage GCP Committed Use Discounts (CUDs) on your behalf. *** ## Microsoft Azure onboarding Follow these guides to connect your Azure environment and enable cost visibility. > **[Prerequisites](/azure/prerequisites)** > > Understand billing account types, locate your Management Group ID, and prepare your Azure environment for nOps. > **[Integration setup](/azure/integration-setup)** > > Connect your Azure environment to nOps and assign the required RBAC roles for cost visibility. *** > **[Next: Users and roles](/platform/users)** > > Learn how to invite team members, assign roles, and manage permissions. # Issue creation from recommendations Source: https://help.nops.io/platform/issue-tracker-notifications Connect work-management tools to turn nOps recommendations into trackable work. ## Overview nOps can turn selected cost recommendations into work items in the tools your team already uses. Organization administrators connect a provider from **Settings → Integrations → Notifications** and choose the destination for new work. The connection requests only the access needed to discover destinations and create the selected work item. nOps does not ask you to paste a provider API key into the notification settings form. Existing connections remain available while a workspace is being reconnected or moved to the current connection flow. ## Provider capabilities and access The following table describes the provider operations and minimum access categories used by nOps. Provider consent screens may use different names for these permissions. | Provider | Creates | Access requested | | - | - | - | | Jira | Issues in a selected project | Read accessible sites, projects, issue types, and user information; create issues | | Linear | Issues in a selected team | Read accessible teams and issue settings; create issues and read the team members needed for assignment | | GitHub Issues | Issues in a selected repository | Read repositories visible to the connected account; create issues; read available labels and assignees when supported | | GitLab Issues | Issues in a selected project | Read projects visible to the connected account; create issues; read available labels and assignees when supported | | ClickUp Tasks | Tasks in a selected list | Read the workspace, space, folder, and list hierarchy; create tasks; apply supported priority and assignee values | | Notion Pages | Pages under a selected page or database | Search and read shared pages or data sources; create child pages with a title and recommendation details | | PagerDuty Incidents | Low-urgency incidents on a selected service | Read available services and create incidents; the connected PagerDuty profile supplies the required sender identity | The destination picker only shows resources the connected account can access. For Notion, share the page or database with the nOps integration before connecting it. For PagerDuty, choose a service intended for low-urgency notifications rather than routine paging. ## Jira and Linear Jira and Linear are available in the recommendation workflow today: 1. Open **Settings → Integrations → Notifications**. 2. Select **Jira** or **Linear**, connect the workspace, and choose a project or team. 3. Open **Insights → Recommendations**, select recommendations, and choose **Create issues**. 4. Review the destination and issue type, then create the work items. If a connection needs attention, use **Reconnect** on its notification integration card. The existing connection is kept as a temporary fallback while the organization completes the new connection and verification flow. ## GitHub and GitLab cost integrations are separate The GitHub and GitLab cards under the **Cost integrations** section of Settings are for billing, usage, and seat data. They use provider access tokens for cost visibility and are unrelated to GitHub Issues or GitLab Issues created from recommendations. Connecting a GitHub or GitLab cost integration does not connect an issue destination, and connecting an issue-creation provider does not enable cost or seat reporting. ## Availability Jira and Linear are the first providers exposed in the recommendation picker. The remaining provider adapters are being validated for their destination pickers and create operations; availability can vary by workspace while that rollout continues. # Notifications Source: https://help.nops.io/platform/notifications Schedule email reports, configure notification workflows, and view real-time updates in the nOps in-app notification feed. ## Overview nOps powers email, chat, and in-app notifications from **Settings > Notifications**. **Email notifications are on by default**, including for organizations that have not customized their notification settings. Turn them off only in **Settings > Notifications** if you want an explicit opt-out saved for your organization. You can schedule email reports, configure workflows, and receive real-time in-app notifications about cost changes, canvas updates, and more. ## Enabling notifications **Settings > Notifications** is visible to every member of your organization, but only **admins** can turn organization-wide email notifications on or off. Email notifications are configured at the organization level and stay on unless an administrator explicitly disables them here. **1. Open notification settings** Go to **Settings > Notifications**. **2. Confirm or adjust email notifications** Notifications are on unless you have turned them off here. Toggle off to disable canvas and scheduled email; leave them on to use the default workflow and sender configuration for your organization. The page also shows the current connection status (Enabled, Disabled, or Error). ## Create work from recommendations You can turn cost recommendations into trackable work for your team from the **Recommendations** page. **1. Open notification settings** Go to **Settings > Notifications** and choose **Jira** or **Linear**. **2. Connect your workspace** Follow the connection flow and select the Jira project or Linear team that should receive new work items. Organization administrators manage these connections. **3. Create work from a recommendation** Return to **Insights > Recommendations**, select one or more recommendations, and click **Create issues**. Choose the project or team and issue type, then review the recommendations before creating the issues. Existing Jira and Linear connections remain available during the transition. Reconnect the selected workspace if nOps shows that the connection needs attention. ## Scheduled email reports You can schedule email reports for any canvas. This is useful for sending recurring cost summaries to stakeholders who may not log in to nOps regularly. | Option | Description | | - | - | | **One-time** | Send a single email at a specific date and time. | | **Recurring** | Send daily, weekly, or monthly at a time you choose. | | **Recipient** | Any address on your organization's domain (or a verified additional domain). The recipient does not need to be an nOps user. | | **Subject and body** | Customize the email subject and body text. | ### Creating a scheduled report **1. Open the canvas** Navigate to the canvas you want to report on. **2. Open Share Reports** Click the **Share Reports** button (mail icon) in the top-right corner of the canvas toolbar. **3. Configure the schedule** Choose **one-time** or **recurring**, set the date/time (or daily/weekly/monthly recurrence), enter the recipient email, and customize the subject and body. **4. Save** The notification appears in your **Scheduled** list. You can edit, pause, or delete it at any time. ## Slack & Teams delivery Reports and scheduled results can also be delivered to **Slack** and **Microsoft Teams** channels, on their own or alongside email recipients. Connect a workspace in **Settings → Notifications**, then pick channels when you send or schedule a report. See [Slack & Teams delivery](/platform/slack-and-teams) for setup and details. ## In-app notification feed The notification bell in the top navigation shows real-time updates. Click it to open the notification feed, where you can review recent alerts and navigate directly to the relevant canvas or setting. ## Permissions | Action | Who can do it | | - | - | | Enable or disable notifications | Admins | | Schedule a canvas report | Any user (members see their own; admins see all) | *** > **[Back to home](/)** > > Return to the documentation home page. # Organizations Source: https://help.nops.io/platform/organizations Organizations are the top-level tenant in nOps. Manage settings, domains, subscription tiers, SAML/SCIM, and audit logs for your team. ## Overview An **organization** is the top-level boundary in nOps. All users, canvases, integrations, and cost data belong to an organization. Each organization maps to an internal **nOps Client ID** that isolates your data from every other tenant on the platform. When you first sign up, nOps creates an organization for you. Administrators can then configure settings, invite users, connect cloud providers, and enable enterprise security features. ## Organization settings Administrators can manage the following from **Settings** in the nOps dashboard: | Setting | Description | | - | - | | **Name** | The display name for your organization (editable). | | **Domain and Slug** | Your organization's verified domain and URL-friendly identifier (read-only). | | **Available Products** | The nOps products enabled for your account (read-only). | | **Plugins** | [Clara MCP](/plugins/clara-mcp) connectors and the [Clara Slack agent](/plugins/clara-slack-agent), under **Settings → Plugins**. | ## Enterprise identity nOps supports enterprise identity management through SAML and SCIM. > [!NOTE] > > Setting up SSO and SCIM requires the **Inform** plan. See [Security and authentication](/platform/security-and-auth#setting-up-sso) for the full setup flow. > **SAML single sign-on** > > Enable SAML SSO to let your team sign in through your identity provider (Okta, Azure AD, Google Workspace, and others). Once enabled, nOps provides an **ACS URL** and **Entity ID** that you configure in your IdP. > > Administrators can also **enforce SSO** so that email/password and social logins are disabled for the organization. > **SCIM provisioning** > > Enable SCIM to automatically sync user accounts from your identity provider. When a user is added or removed in your IdP, the change is reflected in nOps within minutes. ## Roles and data scopes Beyond who can sign in, administrators can control what each role can see and do. Roles carry both feature permissions and, optionally, a **data scope** that limits which cost data a role can access. See [Roles and data scopes](/platform/roles-and-data-scopes) for details. ## Auth policies Every organization has authentication policies that control MFA requirements, SSO enforcement, session duration, and password rules. These are set to secure defaults for every organization; contact nOps support if you need a policy changed for your organization. See [Security and authentication](/platform/security-and-auth#auth-policies) for the full list and current defaults. ## Audit logs nOps records key actions taken within your organization: user sign-ins, role changes, integration modifications, and more. Administrators can view and export audit logs from **Settings > Security**. ## Switching organizations If your account belongs to multiple organizations, you can switch between them from the organization picker in the top navigation. The active organization determines which data, canvases, and integrations you see. If you administer several organizations set up together as a **portfolio**, you don't need to switch back and forth to see combined usage. See [Portfolio Portal](/portfolio/introduction). *** > **[Next: Users and roles](/platform/users)** > > Learn how to manage team members, assign roles, and control access with permissions. # Roles and data scopes Source: https://help.nops.io/platform/roles-and-data-scopes Control which cost data each role can see, in addition to which features it can use. ## Overview Every user in nOps holds one or more **roles**, and each role carries two kinds of access: * **Permissions:** which features a role can use (for example, viewing budgets or managing integrations). * **Data scope:** which *rows* of cost data a role can see (for example, only certain AWS accounts, a specific department, or a subset of your Cost Allocation values). Permissions and data scope are configured together when you create or edit a role, but they answer different questions. Permissions decide whether someone can open a page or take an action. Data scope decides what they see once they're there: the same Explorer report, filtered differently for different people. > [!NOTE] > > Data scope is optional. Most organizations don't need it. Every role is **Unrestricted** by default, meaning it sees the same cost data as anyone else in the organization. Add a scope only when you need to limit what a specific role can see. ## Get started **1. Open Organization Roles** Go to **Settings → Users**. Scroll down to the **Organization Roles** section, below Organization Users. **2. Create or edit a role** Click **Add role** to create a new one, or click an existing role to edit it. This opens a dialog with three tabs: **Details**, **Permissions**, and **Data scope**. **3. Set the access mode** On the **Data scope** tab, choose: * **Unrestricted:** the role sees all cost data your organization has access to. This is the default. * **Restricted:** the role only sees rows matching the rules you define below. **4. Add scope rules (Restricted only)** Click **Add rule** and configure it. See [Building a scope rule](#building-a-scope-rule) below. You can add multiple rules to a single role. **5. Preview and save** Use **Run preview** to see the impact before saving, then save the role. > [!WARNING] > > A **Restricted** role with no rules denies all cost data. It's a hard deny, not "everything." Add at least one rule, or switch back to Unrestricted. ## Building a scope rule Each rule narrows a role's data down to specific values on one dimension: * **Dimension:** any Explorer dimension (account, region, tag, and more), or **Cost Allocation**, which lets you scope to a specific showback's allocation values. * **Operator:** **Include** (the role sees only rows matching these values) or **Exclude** (the role sees everything except rows matching these values). * **Values:** the specific accounts, tags, or other values to include or exclude. * **Include rows with no value:** when checked, rows where this dimension is empty or unallocated are still visible. Leave this unchecked (the default) if unallocated spend shouldn't be visible to a scoped role. You can add several rules to the same role. Within one role, rules narrow together: a role scoped to `Account = A` **and** `Environment = prod` only sees rows matching both. ## How multiple roles combine If a user holds more than one role, their access is the **union** of every role's scope. Adding a role only ever widens what someone can see, never narrows it. If any one of a user's roles is Unrestricted, that role wins and the user sees everything, regardless of any other role's restrictions. ## Previewing impact Before saving a restricted role, use **Run preview** on the Data scope tab to see: * **Scoped total:** spend visible to the role over the last 30 days, under your current rules. * **Unrestricted total:** the same window with no restrictions, for comparison. * **Matching rows:** how many rows of cost data the rules currently match. Check **Preview as unrestricted role** to see what the total would look like if this role had no restrictions, which is useful for sanity-checking how much a rule set is actually narrowing. ## The roles table The Organization Roles table lists every role available to your organization, including built-in environment roles and any custom roles you've created, with columns for: * **Name** and **Slug** * **Data scope:** a short summary such as "Unrestricted" or a description of the active rules * **Type:** built-in or custom * **Description** > [!NOTE] > > If a role's data scope no longer matches a role that exists in your identity system (for example, if the role was deleted there directly), you'll see a banner noting how many scopes are affected. Those scopes are ignored when resolving access. Recreate the role to restore it, or leave it to be cleaned up. ## FAQs > **Who can manage roles and data scopes?** > > Only organization admins with access to role management can create or edit roles and their data scopes, from Settings → Users. > **What happens if I don't set a data scope?** > > Nothing changes. The role stays **Unrestricted** and behaves exactly as roles always have, with access controlled purely by permissions. > **Can I scope access to Cost Allocation values?** > > Yes. Choose **Cost Allocation** as the dimension, then select the specific showback whose allocation values you want to include or exclude. > **Does a data scope affect totals and charts, or just individual rows?** > > Both. Totals, percentages, and chart values are recalculated under the role's scope. A scoped user's dashboard reflects only the spend they're allowed to see, not the organization's full total. > **What if my organization assigns roles from directory groups (SSO/SCIM)?** > > If your identity provider manages role assignment, per-user role changes made directly in nOps can be overwritten on the next sync. Manage role assignment through your directory's group mapping instead. ## Related * [Users](/platform/users): invite team members and manage their roles * [Organizations](/platform/organizations): organization-level settings and switching * [Explorer](/inform/explorer): the dimensions available for scope rules are the same ones you filter by in Explorer # Security and authentication Source: https://help.nops.io/platform/security-and-auth nOps protects your data with enterprise-grade authentication, including SSO/SAML, MFA, SCIM provisioning, configurable session policies, and strict multi-tenant data isolation. ## Overview nOps uses an enterprise-grade authentication platform under the hood. It provides OAuth, magic link, SSO/SAML, SCIM directory sync, and multi-factor authentication, giving your organization the flexibility to choose the sign-in experience that fits your security requirements. All authentication, session management, and identity provisioning are handled by this platform, so nOps never stores passwords directly. ## Signing in nOps uses an **email-first** sign-in flow. The experience adapts based on whether your organization has SSO configured. **1. Enter your email** On the sign-in page, enter your work email address and click **Continue**. **2. Choose your sign-in method** nOps checks whether your email domain has an SSO connection configured: * **SSO available**: You see a **Sign in with SSO** button. If SSO is not enforced, you also have the option to **Send magic link instead**. * **No SSO**: You are redirected to the magic link flow automatically. Check your inbox for a sign-in link or enter the 6-digit verification code. **3. OAuth providers** Below the primary sign-in method, OAuth buttons are shown for **Google** and **Microsoft**. Your administrator may also enable **GitHub** and **Apple** sign-in. A **Last used** badge appears on the provider you used most recently, so you can quickly sign in the same way again. > [!TIP] > > If your organization enforces SSO, social and magic-link sign-in are disabled for all members. You must authenticate through your corporate identity provider. ## Signing up New organizations are created through the sign-up page. **1. Enter your details** Provide your **Organization name** and **work email address**. Public email domains (gmail.com, yahoo.com, outlook.com, hotmail.com, and others) are blocked. A company email is required. **2. Verify your email** You are redirected to the verification flow. Check your inbox for a magic link or enter the verification code. **3. Complete setup** Once verified, nOps creates your organization and takes you to your home page. You can also sign up with **Google** or **Microsoft** OAuth instead of the email flow. ## Setting up SSO SAML single sign-on lets your team authenticate through a centralized identity provider (Okta, Azure AD, Google Workspace, and others). Administrators configure SSO from the security settings page using a secure setup portal. > [!NOTE] > > The security settings page (and SSO/SCIM setup) requires the **Inform** plan. **1. Open security settings** Go to **Settings > Security**. **2. Invite your IT admin** Click **Invite IT Admin to Configure Features**. A modal opens where you select which features to configure: * **Domain Verification:** verify ownership of your email domain * **Single Sign-On:** configure SAML/OIDC (requires domain verification) * **Directory Sync:** enable SCIM user provisioning * **Audit Logs:** enable audit log streaming * **Log Streams:** configure external log destinations **3. Send or generate the link** Enter your IT admin's email address and click **Send Invite**, or click **Generate Links** to copy a portal link manually. The link expires in **5 minutes**. **4. IT admin configures the connection** Your IT admin opens the setup portal link and configures the SAML connection in your identity provider. They map the required attributes and test the connection. **5. Verify the results** Back on the security settings page, the status badges update to reflect the configuration: * **Domain Verification**: Verified / Not Verified * **Single Sign-On**: Active (with provider name and connection date) / Not Configured * **Directory Sync (SCIM)**: Active (with provider name) / Not Configured **6. Enforce SSO (optional)** To require SAML for all users and disable magic-link and social sign-in, contact nOps support to enable SSO enforcement for your organization. ## Security settings page Administrators can manage authentication from **Settings > Security**. The page includes the following sections: ### Security features card A summary card showing the current status of each security feature: | Feature | Status indicators | | - | - | | **Domain Verification** | Verified or Not Verified | | **Single Sign-On** | Active (provider, connected date) or Not Configured | | **Directory Sync (SCIM)** | Active (provider) or Not Configured | | **Audit Logs** | Active or Not Configured | ### API keys Create and manage API keys for programmatic access to nOps directly from the settings page. ### Audit logs Administrators can: * **Enable audit logging:** toggle audit event collection on or off * **Set retention:** choose how long audit logs are kept (30, 60, 90, 180, 365, or 730 days) * **Export logs:** download audit log data as a file for compliance or analysis ## Multi-factor authentication Multi-factor authentication is built in. Depending on your organization's configuration, users may be prompted for a time-based one-time password (TOTP) or other supported factors during sign-in. Organization administrators can require MFA for all users or for administrators only through [auth policies](#auth-policies). To enable or change MFA requirements, contact nOps support. ## SCIM provisioning When Directory Sync (SCIM) is enabled through the setup portal, your identity provider automatically syncs user accounts with nOps: * **Adding a user** in your IdP creates the corresponding nOps account automatically. * **Removing a user** in your IdP deactivates their nOps account. * Changes sync within minutes, so your nOps user directory stays in sync with your corporate directory without manual intervention. To enable SCIM, follow the [SSO setup steps](#setting-up-sso) above and select **Directory Sync** as one of the features for your IT admin to configure. ## Auth policies Every organization has a set of authentication policies that control how users sign in and what security requirements are enforced. Today these are set to sensible defaults for every organization; if you need a policy changed (for example, enforcing SSO or requiring MFA), contact nOps support. | Policy | Description | Default | | - | - | - | | **MFA required** | Require multi-factor authentication for all users in the organization. | Off | | **MFA required for admins** | Require MFA for administrator accounts only. | Off | | **SSO enforced** | Disable magic-link and social sign-in. All users must authenticate via SAML SSO. | Off | | **Session duration** | Maximum session length (in hours) before re-authentication is required. | 24 hours | | **Allow remember me** | Let users opt in to longer sessions by checking "Remember me" at sign-in. | On | | **Max concurrent sessions** | Limit the number of active sessions a single user can have at the same time. | 5 | | **Password policy: Minimum length** | Minimum number of characters for passwords. | 12 | | **Password policy: Require numbers** | Passwords must contain at least one numeric character. | On | | **Password policy: Require special characters** | Passwords must contain at least one special character. | On | | **Password policy: Rotation (days)** | Number of days before users must change their password. | 90 | | **JIT provisioning** | Automatically create nOps accounts for new users who sign in through SSO for the first time. | On | ## Multi-tenant data isolation nOps is a multi-tenant platform. Every API request is scoped to the calling user's active organization and **nOps Client ID**. This means: * Users can only see cost data, canvases, and integrations that belong to their organization. * API routes verify ownership before returning or modifying any resource. * Switching organizations changes the active tenant context and the data you see in nOps. There is no mechanism for one tenant to access another tenant's data, even if they share the same underlying cloud provider accounts. ## Organization selection Users who belong to multiple organizations see an **organization picker** after signing in. Each organization is shown with its name and domain. Select the organization you want to access, and nOps opens your home page scoped to that tenant. You can switch organizations at any time from within the platform without signing out. *** > **[Back to home](/)** > > Return to the nOps documentation home page. # Slack & Teams Delivery Source: https://help.nops.io/platform/slack-and-teams Connect Slack or Microsoft Teams and deliver nOps reports and scheduled Clara results straight to your channels. ## Overview nOps can deliver reports and scheduled results to **Slack** and **Microsoft Teams** channels, so your team sees cost updates where they already work, with no inbox required. The same notification service powers these deliveries and nOps [email notifications](/platform/notifications). You connect a workspace once in **Settings → Notifications**, then choose channels when you send or schedule a report from Explorer, Recommendations, or a scheduled question in [Ask Clara](/clara/clara-chat#scheduled-questions). > [!TIP] > > This is **one-way delivery** of reports and scheduled results. To **ask Clara questions** in Slack (@mentions, DMs, follow-up threads), see the conversational [Clara Slack Agent](/plugins/clara-slack-agent) instead. > [!NOTE] > > Microsoft Teams delivery is in **beta**. During beta, a Teams administrator must install the nOps app in your tenant before messages can be delivered. Slack is generally available. *** ## How it works * An nOps administrator connects Slack and/or Teams once, at the **organization** level. * Connected channels become available in the channel picker on every report and schedule dialog. * When a report is sent (immediately or on a schedule), nOps posts the result to each selected channel, alongside any email recipients. * Scheduled deliveries reuse the channels you saved, so recurring reports keep landing in the same place. *** ## Connect Slack **1. Open notification settings** Sign in to [clara.nops.io](https://clara.nops.io) with an account that can manage your organization, then go to **Settings → Notifications**. **2. Connect your workspace** In the **Slack** panel, click **Connect Slack** and complete the OAuth flow. The panel shows a **Connected** status when finished. **3. Pick channels (optional)** Add the nOps app to any channels you want to deliver to. You can set **default channels** so new reports are pre-filled with your team's preferred destinations. **4. Send a test message (optional)** Use **Send test** to confirm a channel is wired up correctly before scheduling recurring delivery. *** ## Connect Microsoft Teams **1. Install the nOps app in your tenant** During beta, a Teams administrator installs the nOps app in your organization's Teams tenant so messages can be delivered. **2. Connect Teams in nOps** Go to **Settings → Notifications** and connect Teams in the **Microsoft Teams (Beta)** panel. The panel shows a **Connected** status once the tenant is linked. **3. Select channels** Choose the Teams channels your organization has approved. Add more from the channel picker in any send or schedule dialog. *** ## Deliver to channels Once Slack or Teams is connected, a **Slack / Teams channels** picker appears in the delivery dialogs below. Channels and email recipients can be combined in a single send: a report can go to email *and* one or more channels at the same time. | Surface | Where to deliver | | - | - | | **Explorer reports** | Use **Send now** or **Schedule** on a report and pick channels in the delivery dialog. | | **Recommendations reports** | Use the report **Send** dialog and pick channels. | | **Ask Clara scheduled questions** | When you set up a scheduled question, choose Slack or Teams channels. Results post to those channels on each successful run. | > [!NOTE] > > If Slack or Teams is not connected, the picker links you back to **Settings → Notifications** to finish setup. Channels you have not connected will not appear as options. *** ## Default channels Set **default channels** in **Settings → Notifications** to pre-select the destinations your team uses most. New report and schedule dialogs start with these defaults selected; you can add or remove channels per send. *** ## Permissions | Action | Who can do it | | - | - | | Connect or disconnect Slack / Teams | Admins | | Set default channels | Admins | | Choose channels for a send or schedule | Any user (from the connected channels) | *** ## Security * **Organization-scoped:** An administrator connects each workspace once; the install is bound to your nOps **organization**. * **Connected channels only:** nOps validates that every selected channel is connected for your organization before delivering. * **Access controls:** Delivery respects the same organization and data access rules as the rest of nOps. *** ## FAQs > **How is this different from the Clara Slack Agent?** > > This page covers **delivery** of reports and scheduled results *to* channels (one-way). The [Clara Slack Agent](/plugins/clara-slack-agent) is **conversational**: your team asks Clara questions and gets live answers in Slack threads and DMs. Many teams use both. > **Can I send to email and a channel at the same time?** > > Yes. Delivery dialogs accept email recipients and chat channels together, so a single report can reach both. > **Is Microsoft Teams generally available?** > > Teams is in **beta**. A Teams administrator must install the nOps app in your tenant before messages can be delivered. Slack is generally available. > **Why don't my channels show up in the picker?** > > Make sure Slack or Teams is **Connected** in **Settings → Notifications**, and that the nOps app has been added to the channel. Only channels connected for your organization appear as options. *** > **[Notifications](/platform/notifications)** > > Email delivery, scheduled reports, and the in-app notification feed. > **[Clara Slack Agent](/plugins/clara-slack-agent)** > > Ask Clara about cost and usage conversationally in Slack. > **[Ask Clara](/clara/clara-chat#scheduled-questions)** > > Schedule recurring questions and deliver results to your team. > **[Explorer](/inform/explorer)** > > Dynamic cost analysis you can send to email, Slack, or Teams. # Users and roles Source: https://help.nops.io/platform/users Invite team members, assign roles, and control who can access what with role-based permissions in nOps. ## Overview Every person who accesses nOps has a **user** account that belongs to an organization. Users are assigned a **role** that determines what they can see and do inside the platform. Administrators and owners manage the team from **Settings > Users**. > [!NOTE] > > **Settings > Users** requires admin or owner permissions to open. Members don't see this page in Settings, but they can still update their own theme and appearance from the account menu. See [Profile and preferences](#profile-and-preferences) below. *** ## User management page **Settings > Users** has three sections for admins and owners: ### My Profile Your own profile card. From here you can: * **Edit Profile:** update your first and last name. * **Edit Theme:** open the theme settings modal to fine-tune your visual preferences (see [Profile and preferences](#profile-and-preferences) below). * **Change your avatar:** click your avatar to switch between your account photo (if you signed in with SSO or an identity provider that has one) and a set of nOps profile characters. ### Organization Users Admins and owners see the organization user list: active members, pending invitations, and each person's role. From here they can invite users, change roles, and remove members. ### Organization Roles Admins and owners see a table of every role in the organization (built-in and custom). They can create new roles, edit custom role permissions, or delete custom roles from this section. > [!TIP] > > Roles can also be scoped to restrict *which* rows of cost data their holders see, not just which features they can access. See [Roles and data scopes](/platform/roles-and-data-scopes). *** ## Built-in roles nOps ships with three built-in roles. These cannot be edited or deleted. | Role | Slug | Description | | - | - | - | | **Member** | `member` | Standard access. Can view cost data, create private canvases, use Clara AI, and view shared canvases. | | **Admin** | `admin` | Everything a member can do, plus manage users, roles, integrations, security settings, audit logs, and billing. | | **Owner** | `owner` | Full access. Everything an admin can do, plus delete the organization, change the subscription, and transfer ownership. | > [!TIP] > > The first user in a new organization is automatically assigned the **Admin** role. At least one admin or owner must exist at all times. You cannot demote the last one. *** ## Custom roles Admins can create custom roles from **Settings > Users > Roles** to tailor permissions for specific teams or workflows. ### Creating a custom role **1. Open Roles** Navigate to **Settings > Users** and scroll to the **Organization Roles** section. **2. Click Create Role** Click **Create Role** to open the role creation dialog. **3. Fill in role details** Provide a **name**, **slug** (auto-generated from the name, lowercase with hyphens), and optional **description**. **4. Assign permissions** Check the permissions you want this role to have. Permissions are organized by category (see the [Permissions reference](#permissions-reference) below). **5. Save** Click **Save** to create the role. It is immediately available for assignment. ### Editing a custom role Select a custom role from the roles table and click **Edit**. You can update the name, description, and permissions. The slug cannot be changed after creation. ### Deleting a custom role Click **Delete** on a custom role. Any users currently assigned to the deleted role are automatically reassigned to the default **Member** role. > [!NOTE] > > Built-in roles (Member, Admin, Owner) cannot be edited or deleted. *** ## Permissions reference Permissions are the building blocks behind roles. When creating or editing a custom role, you assign permissions by category. The tables below list every available permission. ### Custom role permissions The permissions available when creating or editing a role come directly from your account's environment, so the exact list can vary. The permissions nOps ships by default include: | Category | Permission | Slug | Description | | - | - | - | - | | **nOps** | Member | `nops:member` | Basic member access to the platform | | **nOps** | Administrator | `nops:administrator` | Full organization management access | | **nOps** | Super Administrator | `nops:super-administrator` | Highest privilege level, reserved for accounts nOps designates | | **Widgets** | Manage Users Table | `widgets:users-table:manage` | Manage users via the embedded user management widget | | **Widgets** | Manage Domain Verification | `widgets:domain-verification:manage` | Configure and verify organization domains | | **Widgets** | Manage SSO | `widgets:sso:manage` | Configure Single Sign-On connections | | **Widgets** | Manage API Keys | `widgets:api-keys:manage` | Create, view, and revoke API keys | ### Platform permission levels nOps also uses broader platform-level permissions to gate features. These are assigned to users based on their role and determine access to major areas of the platform: | Permission | Description | Granted to | | - | - | - | | `nops:member` | Core platform access: canvases, cost data, Clara AI | All members, admins, and owners | | `nops:administrator` | Organization management: settings, users, roles, integrations | Admins and owners | | `nops:super-administrator` | Full platform access: global templates and presets, internal tools | Specific accounts designated by nOps (not automatically granted to every Owner) | > [!TIP] > > Admin-level permissions (`nops:administrator`) implicitly include all member permissions. You do not need to assign both. ### Feature access summary The table below shows which roles have access to key platform features by default: | Feature | Member | Admin | Owner | | - | - | - | - | | View home page | Yes | Yes | Yes | | Use Clara AI chat | Yes | Yes | Yes | | Create private canvases | Yes | Yes | Yes | | Create shared canvases | Yes | Yes | Yes | | View and edit shared canvases | Yes | Yes | Yes | | Delete shared canvases | N/A | Yes | Yes | | Create private data source presets | Yes | Yes | Yes | | Create shared data source presets | Yes | Yes | Yes | | Create private templates | Yes | Yes | Yes | | Create shared templates | N/A | Yes | Yes | | Manage users and roles | N/A | Yes | Yes | | Configure SSO, SCIM, and security | N/A | Yes | Yes | | View and export audit logs | N/A | Yes | Yes | | Manage billing and subscription | N/A | N/A | Yes | | Delete organization | N/A | N/A | Yes | | View commitment recommendations and purchases | Yes | Yes | Yes | | View Commitment Inventory | Yes | Yes | Yes | > [!NOTE] > > Creating **global** templates and presets, and the internal Nexus commitment management tool, are not tied to the Owner role. They require a special designation nOps grants to specific accounts. *** ## Inviting users **1. Open the user list** Go to **Settings > Users**. **2. Click Invite** Click the **Invite** button to open the invitation dialog. **3. Enter email addresses** Type one or more email addresses. Each address receives a separate invitation. **4. Send invitations** Click **Send**. Each user receives an email with a link to join your organization. Invitations appear in the **Pending** list until accepted. You can revoke any pending invitation before it is accepted. Revoked invitations are immediately invalidated and the recipient can no longer use the link to join. > [!NOTE] > > Only work email addresses are accepted. Public email domains (gmail.com, yahoo.com, etc.) are blocked during sign-up. *** ## Changing a user's role Admins can change any user's role from the organization user list: 1. Navigate to **Settings > Users**. 2. Find the user in the list. 3. Select a new role from the dropdown. The change takes effect immediately. You cannot demote yourself if you are the last admin or owner. At least one must remain at all times. *** ## Removing a user Admins can remove users from the organization: 1. Navigate to **Settings > Users**. 2. Find the user in the list and click **Remove** (or the delete action). You cannot remove yourself, and you cannot remove the last admin or owner in the organization. *** ## Profile and preferences Each user can customize their own profile and visual preferences. Admins cannot edit another user's profile, only roles and membership. ### Name Update your first and last name from **Settings > Users > My Profile > Edit Profile**. ### Avatar Click your avatar on **My Profile** to open the picker. Choose your account photo (if your identity provider supplied one) or pick one of nOps' profile character illustrations. ### Theme Everyone (members, admins, and owners) can change their theme from the **account menu** (click your avatar at the bottom of the sidebar) → **Theme**. From there you can: * Switch **Appearance** between Auto, Light, and Dark. * Pick a **color preset**, or click **Shuffle** for a random one. * Click **Customize theme…** to open the full theme settings modal with fine-grained sliders. Admins and owners can also reach the same modal via **Edit Theme** on **Settings > Users > My Profile**. **Fine-grained sliders** (in the customize modal): | Setting | Range | Default | | - | - | - | | **Hue** | 0–360 | 237 | | **Saturation** | 0–100 | 87 | | **Brightness** | 0–100 | 55 | **Color presets** (available from either the account menu or the customize modal): | Preset | Hue | Saturation | Brightness | | - | - | - | - | | Midnight | 0 | 0 | 42 | | Slate | 0 | 44 | 55 | | Dusk | 215 | 100 | 48 | | Daylight | 215 | 55 | 82 | | Ocean | 210 | 100 | 46 | | Lagoon | 185 | 75 | 52 | | Violet | 245 | 70 | 61 | | Emerald | 178 | 65 | 45 | | Sunset | 35 | 98 | 69 | | Coral | 358 | 93 | 66 | ### Clara chat panel The Clara overlay panel on Canvas is resizable. Drag the **left edge** to adjust its width, or the **top/bottom edges** to adjust its height. Your preferred width is saved automatically and reused the next time you open Clara. There's no separate settings form for this; just drag the panel to the size you want. ### Series limit Control the maximum number of data series rendered in canvas charts. Adjustable from **50 to 1,000** (rounded to the nearest 50). The default is **250**. This can also be changed from the Command palette on any canvas. *** > **[Next: Security and authentication](/platform/security-and-auth)** > > Understand the sign-in methods, MFA, SSO, and data isolation features that protect your nOps account. # Clara MCP Source: https://help.nops.io/plugins/clara-mcp Ask Clara about your cloud costs from Cursor, Claude, or any other AI tool that supports MCP. ## Overview **Clara** is nOps’s FinOps assistant. In the product you can chat with Clara on the [Ask Clara](/clara/clara-chat) page, from the Ask Clara button on several pages, and on [canvases](/clara/canvas). The **Clara MCP** brings that same assistant into the AI tool you already work in: **Cursor**, **Claude**, or any other client that supports the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). Install a plugin (or add the server config), sign in once, and you can: * Ask about spend, savings, usage, and commitments in plain language * Work with your reports, dashboards, budgets, cost allocations, unit economics, contracts, and MAP projects without leaving your editor * See anomalies and optimization recommendations as soon as nOps finds them * Put an analysis on a schedule so the answer shows up in Slack or email on its own > [!TIP] > > You need an **active nOps account** and the same data access you have in the web app. MCP does not bypass organization permissions. *** ## Capabilities Clara MCP works with your real nOps data and the things you've built on top of it: reports, budgets, cost allocations, contracts, and more. Here's what you can do, grouped by the kind of work. Some actions (**create**, **update**, **delete**, **send**) change things in your nOps account and need an Admin or Owner role. Those are bolded below, and you can read more in [Read vs. write access](#read-vs-write-access). ### Asking questions about your spend Clara answers from a set of prepared views of your cost data, called **datasets**. Each one covers a topic (AWS billing, commitments, AI tool spend) with a known set of fields to group and filter by, so the same question always comes back the same way. | You can | What happens | | - | - | | See which datasets you have | Clara lists what your account can query. | | Look inside a dataset | Clara shows the fields and metrics available, so you know what you can ask for. | | Ask a question | Clara runs it and returns the rows. Your data stays scoped to your organization automatically. | > [!TIP] > > A good first message after connecting: *"List my Clara datasets."* Then *"What's in the Commitment Management Analysis dataset?"* before you dig into spend or savings. What you'll see depends on your setup: which clouds you've connected, whether Commitment Management and ShareSave are turned on, which third-party tools you've integrated, and your role. Typical datasets: | Dataset | What you can ask about | | - | - | | **Explorer Cost & Usage** | Your detailed AWS bill: spend and usage over time, by account, service, tag, purchase type, and more. The best starting point for most questions. | | **Commitment Management Analysis** | How your Reserved Instances and Savings Plans are performing: savings rate, coverage, savings vs. on-demand pricing, and how much commitment is going unused. | | **Commitment Burndown** | What AWS commitments you still hold, how well they're being used, and when they run out. | | **GCP Commitment Inventory** | The same view for your **GCP** committed use discounts. | | **Recommendations** | What nOps suggests you buy for Compute, Databases, and AI, and how much it would save per year. | | **Savings Realizations** | Savings you've actually realized through ShareSave Risk-Free (excludes the current month). | | **Real-time Billing Commitment Management** | The same savings picture with current-month usage included, up to the last few days. | | **AWS Cost Anomalies** | Unusual spend AWS has flagged: how much extra it cost, how serious it is, and the account, region, and usage type behind it. | | **Cursor Cost & Usage** | Cursor spend and usage by person, model, and hour. Useful for charging teams back and spotting unused seats. Needs the [Cursor integration](/integrations/cursor-admin-api). | | **Claude.ai Enterprise Cost & Usage** | Claude.ai Enterprise spend and usage by person, model, and hour, including each person's spend limit. Needs the [Claude Enterprise integration](/integrations/claude-enterprise). | ### Exploring spend and building reports The everyday work you'd do in [Inform](/inform/introduction): dig into costs, save a view, share it with your team, without switching windows. | You can | In nOps | What happens | | - | - | - | | Explore costs | [Explorer](/inform/explorer) | Totals, trends over time, and heatmaps of your spend and usage, plus a list of the values you can filter on. | | Compare two periods | [Explorer](/inform/explorer) | Clara shows what changed between the two, and what drove the change. | | Work with dashboards | [Explorer Dashboard](/inform/explorer-dashboard) | See your dashboards, and **create**, **update**, **copy**, or **delete** them. | | Work with reports | [Reports](/inform/reports) | See your saved reports and their numbers, **create**, **update**, or **delete** them, and **send** one to your team. | | Check insights | [Insights](/inform/insights) | See the spend anomalies and savings opportunities nOps has found. | | Manage MAP projects | [MAP Manager](/inform/map-manager) | See eligible accounts and project resources, and **create**, **update**, or **delete** projects. | ### Splitting costs across teams Assign spend to the teams, products, or departments that own it, so everyone sees their share. | You can | What happens | | - | - | | Manage cost allocations | See your allocations and totals, and **create**, **update**, **copy**, or **delete** them. | | Manage the rules | See how spend is assigned, and **create**, **update**, **reorder**, or **delete** rules. | | Manage the buckets | Change the set of teams, products, or departments an allocation splits across. | | See the results | Get the dollar amount per bucket, the resources inside a bucket, and how the split has changed over time. | | Preview before you commit | Try a rule change and see the resulting split before saving it. | | Keep up with new values | Find newly available values (a new tag or account) and pull them into your existing rules. | ### Budgets, unit economics, and contracts The guardrails you set in [Operate](/operate/budgets): what you plan to spend, what a unit of your business costs, and what you've committed to your cloud provider. | You can | In nOps | What happens | | - | - | - | | Manage budgets | [Budgets](/operate/budgets) | See budgets and how they're tracking, **create**, **update**, or **delete** them, export to CSV, and **send** one out. | | Set up alerts | [Budgets](/operate/budgets) | **Create**, **update**, or **delete** the thresholds that notify you, for example at 90% of budget. | | Plan next period | [Budgets](/operate/budgets) | Build a plan line by line, or have nOps **generate** one from your spend history. | | Track unit economics | [Business Unit Economics](/operate/business-unit-economics) | See cost per unit of your business, **create** or **update** the setup and its numbers, preview spend, and **send** results. | | Track contracts | [Contract Tracker](/operate/contract-tracker) | See your cloud contracts and how much you've burned through, and **create**, **update**, or **delete** them. | ### Commitments and savings How your Reserved Instances and Savings Plans are doing, and what nOps thinks you should buy next: the same picture as [Optimize](/optimize/commitment-inventory). | You can ask about | What you'll get | | - | - | | What you hold | The commitments still on the books, how well they're used, and when they expire. | | How they're performing | Your savings rate, how much of your usage is covered, and the savings you've actually realized. | | What to buy next | nOps purchase recommendations and the savings each one projects. | ### AI and LLM spend What your AI tools cost, and whether the seats you're paying for are being used. | You can | What happens | | - | - | | Spot AI cost spikes | See anomalies specific to your AI and LLM spend. | | Set your AI view | See and **change** the dashboard your team lands on for AI costs. | | Track seats | See who has a seat for each AI tool and how much they're actually using it. | ### Answers on a schedule Set a question up once and have the answer show up on its own: in [Slack or Teams](/platform/slack-and-teams), by [email](/platform/notifications), or in your [Ask Clara](/clara/clara-chat#scheduled-questions) chats. | You can | What happens | | - | - | | Schedule a question | Save a recurring question to Clara, turn it on or off, **run** it now, or **delete** it. | | Schedule a delivery | Have a report or budget sent out on a cadence to Slack, Teams, or email. | | Check what ran | Review your past runs and the result of any single one. | ### Things to try | If you want to | Ask | | - | - | | Get oriented | *"List my Clara datasets."* | | Understand last month's bill | *"Break down our AWS spend last month by service and account."* | | Check commitment performance | *"How are our Savings Plans and Reserved Instances performing this year?"* | | Find coverage gaps | *"Where is our commitment coverage below 90%?"* | | See what's expiring | *"How much commitment value do we still hold, and when does it run out?"* | | Find more savings | *"What is nOps recommending we buy, and what would it save?"* | | Investigate a spike | *"Any unusual spend in the last two weeks, and what drove it?"* | | See who owns what | *"How is our spend split by team, and what's unallocated?"* | | Put a limit in place | *"Create a budget for our Cursor spend and alert me at 90%."* | | Review AI tool costs | *"Who are our top ten Cursor users by cost this billing cycle?"* | | Stop asking manually | *"Send me this commitment coverage report in Slack every Monday morning."* | *** ## Where to get install packages The fastest path is inside nOps: 1. Sign in to nOps and open **Settings**. 2. Under **Organization Settings**, open **Plugins**, then find **Clara MCP & Connectors**. 3. Under **Latest release**, expand **Download assets** and grab the zip for your tool (when available): * **`clara-cursor-plugin-*.zip`:** Cursor * **`clara-claude-plugin-*.zip`:** Claude Desktop or Claude Code You can also download releases from the open-source repo: [nops-io/clara-mcp](https://github.com/nops-io/clara-mcp/releases). For **other MCP clients**, use the standalone server config on the Plugins page or in [Other MCP clients](#other-mcp-clients-manual-setup) below. Detailed install steps for Cursor and Claude are in that repo’s docs (linked from **Settings → Plugins**). *** ## Install in Cursor ### Prerequisites * [Cursor](https://www.cursor.com) installed * An active nOps account ### Steps **1. Download the Cursor plugin** Get the latest **`clara-cursor-plugin-v*.zip`** from **Settings → Plugins → Clara MCP & Connectors** or [GitHub Releases](https://github.com/nops-io/clara-mcp/releases). **2. Extract into your project** Unzip into your **project root** (or your home directory for a global install): ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}} unzip clara-cursor-plugin-v*.zip -d /path/to/your/project ``` This adds `.cursor/mcp.json`, `.cursor/rules/clara.mdc`, and `.cursor/skills/` where Cursor expects them. **3. Enable the MCP server** Open **Cursor Settings → Tools & MCP** and turn on the **clara** server. **4. Reload Cursor** Run **Cmd+Shift+P → Reload Window** (Mac) or the equivalent on Windows / Linux. ### Verify In Cursor Chat, ask: *"List my Clara datasets."* On the first request, Cursor prompts you to **authorize with nOps** (OAuth). Complete login in the browser; later requests reuse your session. ### What the Cursor package includes | Path | Purpose | | - | - | | `.cursor/mcp.json` | Registers the Clara MCP server | | `.cursor/rules/clara.mdc` | Guidance so Cursor uses Clara tools well | | `.cursor/skills/query-clara/` | General FinOps / cost questions | | `.cursor/skills/commitment-analysis/` | Savings rate, coverage, RI/SP burndown | ### Global install (all projects) Extract to your home directory instead of a single repo: ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}} unzip clara-cursor-plugin-v*.zip -d ~ ``` *** ## Install in Claude Desktop ### Prerequisites * Claude **desktop app** * An active nOps account ### Steps **1. Download the Claude plugin** Get the latest **`clara-claude-plugin-v*.zip`** from **Settings → Plugins → Clara MCP & Connectors** or [GitHub Releases](https://github.com/nops-io/clara-mcp/releases). **2. Add the plugin in Claude** In Claude, go to **Settings → Plugins** and click **+** next to **Personal plugins**. **3. Select the zip** Choose the downloaded **`clara-claude-plugin-v*.zip`**. Clara appears under **Personal plugins** in the sidebar. **4. Connect the MCP connector** Open the Clara plugin → **Connectors** → **Install** next to **clara**, then complete the **nOps OAuth** prompt. ### Verify Start a conversation and ask: *"List my Clara datasets."* ### What the Claude package includes | Path | Purpose | | - | - | | `.claude-plugin/plugin.json` | Plugin manifest | | `.mcp.json` | Clara MCP server config | | `skills/query-clara/` | General Clara queries | | `skills/commitment-analysis/` | Commitment performance analysis | *** ## Install with Claude Code (CLI) If you use **Claude Code** (`claude` CLI) instead of the desktop app: 1. Download **`clara-claude-plugin-v*.zip`** (same package as desktop). 2. Install the plugin: ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}} claude plugin install ./clara-claude-plugin-v*.zip ``` For a single session without a permanent install: ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}} claude --plugin-dir ./clara-claude-plugin-v*.zip ``` 3. Update when new releases ship: ```sh theme={"theme":{"light":"github-light","dark":"github-dark"}} claude plugin update clara ``` 4. Connect the **clara** MCP connector and complete OAuth (same as desktop). **Requirement:** Claude Code **v2.1.128** or later. *** ## Other MCP clients (manual setup) Official plugin zips for **Cursor** and **Claude** include MCP config automatically. For **any other client**, add an HTTP MCP server with the same shape as below. Use the **exact `url` value** from **Settings → Plugins → Clara MCP & Connectors → Standalone MCP (reference)** in nOps (it is configured per environment, not duplicated in this doc): ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "mcpServers": { "clara": { "type": "http", "url": "" } } } ``` | Client | Typical config location | | - | - | | **Cursor** | `.cursor/mcp.json` in the project, or `~/.cursor/mcp.json` globally | | **Claude Code** | `.mcp.json` in the project, or `~/.claude/mcp.json` globally | | **Other** | See your client’s MCP documentation | You can copy the same JSON from **Settings → Plugins → Clara MCP & Connectors → Standalone MCP (reference)** in nOps. Clara uses **OAuth on first use**. There is no long-lived API key to paste into the config file. *** ## Authentication 1. Ask Clara anything in your AI tool (for example *"Show my cloud costs for last month"*). 2. On the **first** request, you'll be sent to an **nOps login** page. Sign in with the account that should own the data. 3. After authorization, the session is stored; you should not need to log in on every message. **Re-authenticate** if your session expires or you switch nOps organizations: run a Clara tool again and follow the prompt, or sign out of nOps in the browser and sign back in first. You'll only ever see the data your nOps role allows. If something is off limits, Clara will say so rather than return it. ### What you can change Clara follows your existing **nOps role**. There's nothing extra to set up: | Your nOps role | What you can do | | - | - | | **Member** | Ask questions and read everything you can see in the app: reports, dashboards, budgets, allocations, contracts, and insights | | **Admin** / **Owner** | All of the above, plus creating, updating, and deleting: the bolded actions in [Capabilities](#capabilities) | If an action fails with a permissions error, check your role with an organization admin, or ask them to make the change for you. > [!WARNING] > > Creating, changing, and deleting through Clara affects your real nOps account, and deletes can't be undone from your AI tool. It's worth asking Clara to confirm what it's about to change before it does. *** ## Clara in nOps vs. Clara MCP | | **In nOps (web)** | **Clara MCP (your AI tool)** | | - | - | - | | **Where** | Ask Clara, canvases | Cursor, Claude, or another MCP client | | **Best for** | Charts and canvases you share with the team | Quick questions while you work, and anything alongside your code | | **Setup** | None. It's already there | Install the plugin, sign in once | Many teams use **both**: canvases for dashboards they share, and Clara MCP in the tool they're in all day. *** ## Troubleshooting ### Stuck on login, or "not authorized" * Sign out of nOps in your browser, sign in again, then ask Clara something. * Double-check you signed in to the **right** nOps organization. ### Clara doesn't show up * **Cursor:** open **Settings → Tools & MCP** and make sure **clara** is switched on, then reload the window. * **Claude:** open **Connectors** and make sure **clara** is installed and connected. * Restart your AI tool after installing a new version of the plugin. ### Clara responds but the numbers look empty or wrong * Check that your nOps role can see the data you're asking about. * For savings questions, end your date range before the **current month**. Most savings data lags by about a month. * Ask Clara what's in the dataset. Available fields depend on your integrations and setup. ### Network Clara MCP connects over **HTTPS**. If you're behind a corporate proxy or firewall, it needs to allow outbound access to the nOps MCP host. ### More help * Repo guides: [install-cursor](https://github.com/nops-io/clara-mcp/blob/main/docs/install-cursor.md), [install-claude](https://github.com/nops-io/clara-mcp/blob/main/docs/install-claude.md), [auth](https://github.com/nops-io/clara-mcp/blob/main/docs/auth.md), [troubleshooting](https://github.com/nops-io/clara-mcp/blob/main/docs/troubleshooting.md) * nOps support: [support.nops.io](https://support.nops.io) or in-app chat *** > **[Clara Slack Agent](/plugins/clara-slack-agent)** > > Ask Clara about spend and commitments in Slack: @mentions, DMs, and scheduled thread delivery. > **[Ask Clara](/clara/clara-chat)** > > Use Clara inside nOps without installing MCP. Ideal when you want charts and canvases in the same session. > **[Home page](/platform/home)** > > Choose where nOps opens when you sign in. > **[Integrations](/platform/integrations)** > > Connect AWS, GCP, and Azure so Clara has cost and commitment data to query. > **[Plugin releases on GitHub](https://github.com/nops-io/clara-mcp/releases)** > > Download Cursor and Claude plugin zips (and manual MCP config for other clients), release notes, and source docs. # Clara Slack Agent Source: https://help.nops.io/plugins/clara-slack-agent Ask Clara about cloud costs and usage in Slack: @mentions, DMs, and scheduled reports powered by your live nOps data. ## Overview **Clara** is nOps’s FinOps assistant. In the web app you can use [Ask Clara](/clara/clara-chat) and [canvases](/clara/canvas). With the **Clara Slack agent**, your team can ask cost and usage questions **where they already work**: in Slack channels, threads, and direct messages. This is not a one-way alert feed. Clara is **fully conversational**: ask a follow-up, request a breakdown by tag or account, or drill into an anomaly in the same thread. Clara reasons over your **live** cloud cost data (the same intelligence that powers nOps) and replies in seconds. > [!TIP] > > This is different from one-way report delivery. The Slack agent uses the shared nOps Slack app > and Slack's Events API so your team can **start** conversations with Clara, not only receive > pushes. For pushing reports and scheduled results *to* channels, see [Slack & Teams > delivery](/platform/slack-and-teams) and [Notifications](/platform/notifications). *** ## What you can ask Mention **@Clara** in a channel (where the bot is added) or send Clara a **DM**. Examples: | Theme | Example prompt | | - | - | | Spend | *"Break down our AWS spend last month by service and account."* | | Anomalies | *"Why did our bill go up 12% this week?"* | | Commitments | *"What's our savings plan utilization right now?"* | | Resources | *"Top 10 most expensive RDS instances this month."* | | Trends | *"How has our Lambda spend changed quarter over quarter?"* | Clara uses your live data on each request, not a fixed export. Follow-ups in the **same thread** keep context (filters and time ranges you already set). *** ## Scheduled reports in Slack You can ask Clara to deliver recurring insights on a schedule, in natural language, without building a report in the app first. Examples: * *"Give me a daily breakdown of AI service costs by account."* * *"Every Monday, summarize our savings plan utilization and top waste opportunities."* Clara runs the analysis against **live data** at delivery time. To change or stop a schedule, reply in the same thread (for example *"Stop the daily AI cost report"* or *"Change that to weekly instead."*). | Use case | Example | | - | - | | Daily AI cost tracking | Flag day-over-day growth above a threshold | | Weekly commitment health | Effective savings rate and commitments expiring in 30 days | | Post-deploy watch | Track an account against the prior week’s baseline | | Monthly team summaries | Per-team spend vs. budget on the first of the month | *** ## Security * **Workspace-scoped:** An nOps administrator connects Slack once for the organization. The same workspace can be used for report delivery, while the conversational agent keeps its own runtime and permissions. * **Identity:** Users must map to your nOps organization. If Clara cannot resolve a Slack user to a valid nOps identity, it will not return cost and usage data. * **Permissions:** Each request is checked against the same cloud data access rules as the web app. *** ## Enable Clara in Slack **1. Sign in to nOps** Open [clara.nops.io](https://clara.nops.io) and sign in with an account that can manage your organization. **2. Open Plugins** Go to **Settings → Organization Settings → Plugins**. **3. Connect your workspace** In **Clara Slack Agent**, turn on **Enable Clara in Slack**, then click **Connect Slack** (or **Reconnect Slack**) and complete the connection flow. If a new workspace is waiting for approval, an organization administrator can approve it before use. **4. Start asking in Slack** @mention Clara in a channel or DM Clara. Add the app to channels where the whole team should see answers. Setup usually takes a few minutes. You need permission to manage the Slack agent in nOps (typically an administrator). Existing Slack installations remain available as a temporary fallback while the connection is being verified. *** ## Who benefits | Audience | How Slack helps | | - | - | | **Engineering** | Cost context during incidents, deploys, and capacity planning without opening another tool | | **FinOps** | Fewer ad-hoc *"what did we spend on X?"* interruptions; Clara handles routine lookups | | **Managers** | Team-level spend in standup channels without dashboard context switches | | **Finance / leadership** | Quick budget answers in planning conversations already in Slack | *** ## Clara Slack vs Clara MCP | | **Clara Slack agent** | **[Clara MCP](/plugins/clara-mcp)** | | - | - | - | | **Where** | Slack (channels, threads, DMs) | Cursor, Claude, or another MCP client | | **Best for** | Team-wide questions in Slack | Individual workflows in your daily AI harness | | **Setup** | **Settings → Plugins** + Slack OAuth | Plugin zip or MCP config + OAuth once | Many teams use **both**: Slack for broad collaboration, and MCP in the tools engineers use to build and operate systems. *** > **[Clara MCP](/plugins/clara-mcp)** > > Connect Cursor, Claude, or your harness to nOps datasets and commitment analysis. > **[Notifications](/platform/notifications)** > > Email and scheduled canvas delivery, separate from the conversational Slack agent. > **[Ask Clara](/clara/clara-chat)** > > Use Clara inside nOps with charts and canvases in the same session. > **[Organizations](/platform/organizations)** > > Organization settings, SSO, and audit logs. # Portfolio Portal Source: https://help.nops.io/portfolio/introduction Roll up AI model usage across multiple nOps organizations you administer, from a single parent organization. **Portfolio Portal** lets you view AI model usage across several nOps organizations you administer, without switching orgs. It's built for teams that manage more than one nOps customer organization (for example, a partner or managed-services team, or a parent company overseeing several subsidiaries) and want a combined view of AI spend across all of them. > [!NOTE] > > Portfolio Portal currently works on **Model Overview** only. Support for other pages (Cost Allocation, Business Unit Economics, and Budgets) is planned but not yet available. If you switch to a portfolio scope elsewhere in the product, you won't see any effect yet. ## How it works nOps sets up a **portfolio** for you: one organization is designated the **parent**, and one or more other organizations become its **child companies**. This is a setup step done by your nOps account team, not something you configure yourself. See [Getting set up](#getting-set-up). Once your portfolio exists, sign in to the **parent** organization. If you're an administrator there, you'll see a **View usage for** selector next to the date filter on Model Overview. ## Viewing your portfolio On [Model Overview](/ai/tracking), the **View usage for** selector offers: * **All portfolios:** a combined roll-up across every organization in the portfolio you administer. * A single organization: pick one by name to see just its usage. Every section on the page respects your selection: * The model usage stat cards, trend chart, and platform token mix. * **Spend & budget by client**, which breaks out a row per organization when you're viewing **All portfolios**. Click a client to expand into its projects and per-integration actuals. * The all-time model leaderboard and model detail panes. ## Organizations you can't see You only see usage for organizations where you have administrator access. If the portfolio includes an organization you don't administer, it's named in a notice below the header: > Not included: *Acme Corp*. You don't have admin access to that organization. That organization's data is left out of **All portfolios** entirely. It's not partially included or estimated. ## Sharing a view Your scope selection is written into the page URL, so sharing a link reproduces exactly what you were looking at, whether that's **All portfolios** or a single organization. ## Getting set up Portfolios aren't self-serve. To get one set up, contact your nOps account team with: * Which organization should be the **parent**. * Which organizations should be added as **child companies**. * Who should be able to view the combined roll-up (they'll need administrator access on the parent, and on any child organization they should see). ## FAQs > **Why don't I see a View usage for selector?** > > It only appears if you're signed in to a **parent** organization and you're an administrator there. Signing in to a child organization won't show it, even if that organization belongs to a portfolio elsewhere. > **Why is one of my organizations excluded from All portfolios?** > > You need administrator access on that specific organization for its data to be included. It's still named in the exclusion notice so you know it exists, but its usage isn't rolled up until you have access. > **Does this change anything for users in a child organization?** > > No. Portfolio Portal only adds a viewing option for portfolio administrators on the parent organization. Users signed in to a child organization see their usual Model Overview, scoped to just that organization. > **Will Portfolio Portal expand to other pages?** > > Yes. Model Overview is the first surface. Expanding to other pages like Cost Allocation is planned. > **Is this the same as the Portfolio summary on Budgets?** > > No. The **Portfolio summary** cards on [Budgets](/operate/budgets) total up your own organization's budgets. They don't involve other organizations. Portfolio Portal is specifically about rolling up usage across multiple organizations you administer. ## Related > **[AI tracking](/ai/tracking)** > > See how Model Overview and AI Explorer work, including the Viewing several organizations section. > **[Organizations](/platform/organizations)** > > Learn about organizations as the top-level tenant in nOps, and switching between them. # nOps Customer Service SLAs Source: https://help.nops.io/support/customer-service-sla Last updated: June 2026

Support response times, severity levels, help desk hours, and platform availability commitments for nOps customers. This Service Level Agreement ("SLA") for nOps, Inc. ("nOps", "we", or "us") services (the "Service(s)") sets forth the support service levels for every applicable nOps Service. This SLA may be updated from time to time. ## Service request definitions * **Excused Downtime** means the total number of minutes in the applicable month that the Services are unavailable due to or resulting from: (i) maintenance; (ii) force majeure events or other events beyond the reasonable control of nOps, including acts of God, natural disasters, epidemics, pandemics, terrorism, war, government actions, labor disputes, power failures, internet or telecommunications failures, or denial-of-service attacks; (iii) outages or failures of third-party cloud service providers (e.g., AWS, Azure, or Google Cloud) on which nOps relies; (iv) failures or unavailability of your own infrastructure; or (v) downtime authorized by you. * **Impact** means the extent of deviation from the normal service level, in terms of the number of users or business processes affected. * **Issue** means your communication to us via (i) a support ticket; (ii) an email addressed to [support@nops.io](mailto:support@nops.io); or (iii) a telephone call to a designated customer success manager, of an unscheduled or unanticipated incident that adversely affects the delivery of the Services. * **Required Monthly Availability** means the total number of minutes in the applicable month, minus the Excused Downtime and the Scheduled Downtime. * **Response Time** means our action in response to notification from you to us of an Issue. * **Scheduled Downtime** means the total number of minutes in any given month that the Services are unavailable due to our scheduled maintenance and repair. * **Support Request** means a request made to us for the purpose of initiating our assistance for a support-related activity or Issue. ## Severity and time-to-respond At nOps, we collaborate closely with our customers to ensure that any reported technical or business issues are given the appropriate level of priority. Our response times and the steps we take to resolve your problem are determined based on an evaluation of how the reported technical issue impacts your business. The more significant the impact on your business, the higher the priority assigned to the issue. It is a common understanding between both parties that the customer has the authority to specify the priority of their service request. When a request is marked as high-priority, a designated nOps customer success manager (CSM) will be at your disposal to assist while we work on resolving the issue. The following guidelines are provided to assist you in determining the appropriate priority level. ## Help desk support We will endeavor to provide the maintenance and support services set forth below as part of the nOps AWS marketplace subscription: * Our support help desk ("Help Desk") is available between **12:00 AM ET and 8:00 PM ET**, Monday through Friday. Support is provided in English. * We are available **24 hours per day, 7 days per week** for Severity Level 1 Issues (as defined in the Issues Classification table below). * Support for Severity Level 1 issues during national holidays or off-hours (between 8:00 PM ET and 12:00 AM ET) and on weekends requires a phone call to your designated nOps CSM to engage support. You may issue a Support Request by emailing the nOps Help Desk at [support@nops.io](mailto:support@nops.io). For all valid nOps subscriptions, you must create a Support Request for Severity Level 1, Severity Level 2, and Severity Level 3 issues. Registered users may create a support ticket by: * Submitting a Support Request through the **in-app** support chat. * Emailing the nOps Help Desk at [support@nops.io](mailto:support@nops.io). * Calling your designated CSM. Issues communicated to any other nOps.io person or entity, or from an unregistered person, will be considered Severity Level 4 issues. By submitting a Support Request, you authorize the nOps technical support team to download or copy any data necessary for troubleshooting the reported issue. If you have concerns about this authorization, contact your nOps CSM. Communication directly with an account executive, project manager, engineer, or management contact is not covered by the Issue Response and Resolution Times chart below. ## Our support response and resolution commitment ### Issues classification | Severity level | Definition | | - | - | | Severity Level 1 | Customer cannot use most or all of a product or service (i.e., most pages in the product are not loading or displaying an error message). Data corruption or loss has occurred or will occur. | | Severity Level 2 | Customer is prevented from executing one or more critical business processes (for example: Cloud Publishing, CCMS) for a substantial number of users, or Services are usable with limited capabilities and/or intermittent interruptions which have serious business Impact. | | Severity Level 3 | Primary product functionality is severely impacted and unusable. Customers are unable to utilize a common feature to its fullest ability. Data may not be displayed as expected but is not lost. There is no commercially reasonable workaround for customers. | | Severity Level 4 | Some customers (not all) are receiving intermittent errors on product pages or cannot use the product in possibly obscure ways. The product may be loading slowly or partially (missing images), and there is a workaround that customers can use. | > [!NOTE] > > When submitting a ticket, use your best judgment to identify the severity of the issue. For a > Severity Level 1 issue, you need not confirm with every user. A quick sanity check with a few > colleagues in different locations (to rule out local internet issues) is sufficient. Upon > engagement, the nOps support team will evaluate the situation and may, in its discretion, > reclassify an issue to the appropriate level. ### Issue response and resolution times We shall endeavor to provide the following response and resolution times: | Issue severity | Response time | Resolution time | | - | - | - | | Severity Level 1 | Less than 30 minutes | Fewer than 8 hours | | Severity Level 2 | Less than 4 hours | 2 business days | | Severity Level 3 | Less than 8 hours | 4 business days | | Severity Level 4 | Less than 24 hours | N/A (resolution not guaranteed) | ## Services availability nOps will use commercially reasonable efforts to provide a Required Monthly Availability of **99.9%** for the nOps SaaS platform [https://clara.nops.io](https://clara.nops.io) (formerly `app.nops.io`). We will use commercially reasonable efforts to ensure the Services are available (i.e., accessible and usable) at the Required Monthly Availability. # Send OpenTelemetry data to nOps Source: https://help.nops.io/telemetry/opentelemetry Point your AI gateways, agent tools, and services at nOps with a standard OpenTelemetry setup and an API key. ## Overview nOps accepts telemetry from your own software using [OpenTelemetry](https://opentelemetry.io) (OTel), the open standard most AI gateways, coding agents, and application frameworks already support. Traces, logs, and metrics all work. This is **push, not pull**. nOps can't fetch this data from your cloud account, because it only exists inside your running software. You configure your software once with the nOps address and an API key. After that it sends data every few seconds on its own until you remove the setting or revoke the key. Every record nOps receives is tagged with your organization automatically, based on the API key. You don't add an ID yourself, and anything you send that tries to set one is overwritten. > [!NOTE] > > You need nOps administrator access to create API keys, and the **Inform + Operate** plan, the same plan that includes the [Public API](/developers). ## What you need | You need | Value | | - | - | | **Endpoint** | `https://api.nops.io/otel` | | **Protocol** | `http/protobuf` | | **Auth header** | `Authorization: Bearer ` | | **Key permission** | `telemetry:write` | > [!WARNING] > > Only `http/protobuf` is supported. `http/json` and `grpc` are rejected. If your software can only send gRPC or can't set a custom header, use the [OpenTelemetry Collector](#use-an-opentelemetry-collector) option below. ## Step 1: Create an API key 1. Sign in to [nOps](https://clara.nops.io/dashboard) as an administrator. 2. Open **Settings → Security → API Keys**. 3. Create a key and name it after the sender, for example `ai-gateway-prod` or `claude-code-engineering`. 4. Give it **only** the `telemetry:write` permission. 5. Copy the key. nOps shows it once. > [!TIP] > > Create one key per sender. If a key leaks, you can revoke it without cutting off your other senders, and nOps can tell which sender each record came from. A telemetry-only key can do nothing except send data, so the damage from a leak is limited. ## Step 2: Point your software at nOps Pick the option that matches what you're sending from. ### Any OpenTelemetry SDK or tool Every official OTel SDK reads the same standard environment variables: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} OTEL_EXPORTER_OTLP_ENDPOINT=https://api.nops.io/otel OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer%20 OTEL_EXPORTER_OTLP_COMPRESSION=gzip OTEL_SERVICE_NAME= ``` * Set the endpoint **without** `/v1/traces`, `/v1/logs`, or `/v1/metrics`. The SDK adds the right path for each signal. * The `%20` in the header stands for the space after `Bearer`. The OTel specification requires header values in this variable to be URL-encoded, and some SDKs reject a literal space. * `OTEL_SERVICE_NAME` is how you'll tell your services apart in the data. ### Claude Code Claude Code can export usage, cost, and session events over OpenTelemetry. Administrators can turn it on for everyone through Claude Code's managed settings file, in its `env` block: ```json theme={"theme":{"light":"github-light","dark":"github-dark"}} { "env": { "CLAUDE_CODE_ENABLE_TELEMETRY": "1", "OTEL_METRICS_EXPORTER": "otlp", "OTEL_LOGS_EXPORTER": "otlp", "OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf", "OTEL_EXPORTER_OTLP_ENDPOINT": "https://api.nops.io/otel", "OTEL_EXPORTER_OTLP_HEADERS": "Authorization=Bearer%20" } } ``` Individual developers can instead set the same values in their shell or in `~/.claude/settings.json`. Claude Code ignores these settings when they come from a repository's `.claude/settings.json`. > [!NOTE] > > By default Claude Code does not include prompt text in telemetry. Leave `OTEL_LOG_USER_PROMPTS` and similar content settings off unless you intentionally want prompts and responses sent to nOps. ### AI gateways Most AI gateways, including LiteLLM, Portkey, and Kong, have an OpenTelemetry option in their config file or admin page. It asks for the same three things: an endpoint, a protocol, and an authorization header. Use the values from [What you need](#what-you-need). The exact field names differ by gateway, so check your gateway's documentation for its OTel or OTLP settings. ### Use an OpenTelemetry Collector Use a Collector when your software only speaks gRPC, can't set custom headers, or already sends to a Collector. Run the standard OpenTelemetry Collector next to your software. It accepts telemetry on its normal ports and forwards it to nOps: ```yaml theme={"theme":{"light":"github-light","dark":"github-dark"}} receivers: otlp: protocols: grpc: { endpoint: 0.0.0.0:4317 } http: { endpoint: 0.0.0.0:4318 } processors: batch: {} exporters: otlphttp/nops: endpoint: https://api.nops.io/otel compression: gzip headers: Authorization: "Bearer ${env:NOPS_TELEMETRY_KEY}" service: pipelines: traces: { receivers: [otlp], processors: [batch], exporters: [otlphttp/nops] } metrics: { receivers: [otlp], processors: [batch], exporters: [otlphttp/nops] } logs: { receivers: [otlp], processors: [batch], exporters: [otlphttp/nops] } ``` Already sending to another tool such as Datadog or Grafana? Keep your existing exporter and add `otlphttp/nops` beside it in each pipeline. The Collector sends to both. ## Step 3: Check that it works Send a few test traces with `telemetrygen`, part of the OpenTelemetry Collector contrib project: ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}} telemetrygen traces --traces 5 --otlp-http \ --otlp-endpoint api.nops.io:443 \ --otlp-http-url-path /otel/v1/traces \ --otlp-header 'Authorization="Bearer "' ``` A successful request returns HTTP `200`. If you'd rather test with your real software, run it briefly and watch its logs for export errors. ## Limits | Limit | Value | | - | - | | Request size | 4 MB per request. Use gzip and keep batches modest | | Rate | Requests are limited per organization. OTel exporters retry automatically when they hit the limit | | Format | Protobuf only | ## Troubleshooting | Symptom | Likely cause | | - | - | | `401` | The key is wrong, revoked, or the header is malformed. If `Bearer%20` fails in your tool, try a literal space instead | | `403` | The key is missing the `telemetry:write` permission, or your organization isn't on the **Inform + Operate** plan | | `404` | The endpoint includes `/v1/traces` twice, or points at the wrong host. The base should be `https://api.nops.io/otel` | | `413` | A request is too large. Lower your exporter's batch size | | `415` | Your software is sending JSON. Set the protocol to `http/protobuf` | | `429` | You're sending faster than your limit allows. Exporters retry on their own, so brief bursts are fine. If it persists, contact support | | `503` | nOps is temporarily unable to accept data. Exporters retry automatically | | No requests at all | Your software is using gRPC (port 4317). Switch to `http/protobuf`, or use a Collector | | `200` but no data | The exporter for that signal is turned off, for example `OTEL_TRACES_EXPORTER=none`, or your software doesn't emit that signal | ## FAQs > **Can I send to nOps and another tool at the same time?** > > Yes. Use an OpenTelemetry Collector with more than one exporter, as shown above. > **Can I set my own organization ID in the data?** > > No. nOps assigns your organization from the API key and removes any attribute you send whose name starts with `nops_` or `nops.`. Other attributes pass through unchanged. > **What happens if I revoke a key?** > > Sending stops within a couple of minutes. Data already received stays in your organization's records. > **Should I send prompt or response text?** > > Only if you need it. AI gateway and agent traces can include the full text of prompts and responses. Check your exporter's settings and remove sensitive content you don't want stored. > **Does it work with the development environment?** > > If you've been given access to a nOps test environment, use the endpoint you were given in place of `https://api.nops.io/otel`, together with a key created in that environment. ## Related * [Authentication](/developers/authentication) * [Rate limits](/developers/rate-limits) * [AI overview](/ai/introduction)