Skip to content

AI spend and cloud cost connectors

Spend connectors read what vendors billed, so Shield360 can compare it with the estimate it builds from observed usage. Every connector here is read-only: it reads cost, seat and key data, and never changes anything at the vendor.

There are two kinds:

  • AI spend connectors read AI vendors’ bills: pay-per-token API costs (OpenAI, Anthropic, Azure OpenAI, Amazon Bedrock) and per-seat tools (GitHub Copilot, Cursor, ChatGPT Enterprise). They feed the spend report, Costs → Actual vs estimate, Costs → API keys and the subscriptions the connectors keep for you.
  • Cloud cost connectors (AWS Cost Explorer, Azure Cost Management and the Google Cloud billing export) read the whole cloud bill for every service. Their rows are kept apart from every AI figure and appear only on Costs → Cloud.
Open Connectors

Open Connectors (/connectors) and select the project and environment the costs belong to. Spend connectors belong to a project and write to that environment’s database.

Choose the connector type

Select Add connector, then choose a type from the AI spend category.

Fill in the credentials and settings

Follow the section for your vendor below. Each secret field also has a … from the Vault (optional) field: name a Vault entry there instead of pasting the secret, and Shield360 reads the secret from the Vault at every sync.

Save and test

Save the connector, then use its test button. The test is a real sync: it reads the vendor now and reports what it found, for example Synced $1,234.56 over 31 days, 42 seats. or the vendor’s error.

These settings are common to every spend connector:

FieldWhat it does
Days to read back7, 31 (default) or 90. Each sync re-reads this many days, so late corrections from the vendor are picked up. Days older than that keep what earlier syncs found.
Import full history on the next syncOn by default for connectors that report history. The next sync reads everything the vendor keeps, once, then the switch turns itself off. Turn it on again to re-import. Seat connectors (GitHub Copilot, Cursor, ChatGPT Enterprise) don’t have it, because vendors only report today’s seat holders.
Sync every6 hours or Day (default). Vendors publish costs daily. A failed sync is retried within the hour instead of waiting the full interval.

To change a secret later, type the new value. Leaving a secret field blank when you edit a connector keeps the stored secret.


Reads daily OpenAI API costs from OpenAI’s Admin API, grouped by project, line item and API key. It also lists every project’s API keys, with each key’s name, owner and redacted hint, so Costs → API keys can match billed keys to the machines seen using them. Costs per API key are only available from a date OpenAI sets; earlier costs are imported without a key.

What you’ll need

  • An OpenAI organisation owner, to create the admin key.
  • An OpenAI admin key (not an ordinary project API key).

Shield360 calls these endpoints on https://api.openai.com, all with GET:

EndpointUsed for
/v1/organization/costsDaily costs by project, line item and API key.
/v1/organization/projectsProject names.
/v1/organization/projects/{project_id}/api_keysEach project’s keys, for key attribution.
Create an admin key

Sign in to the OpenAI platform as an organisation owner and create an admin key under your organisation’s settings (admin keys are separate from project API keys). See OpenAI’s Administration API reference and Usage and Costs API.

Copy the key

Copy the key when it’s shown. You can’t view it again.

Add it to Shield360

Add an OpenAI API costs connector and paste the key into Admin key, or store it in the Vault and name the entry in Admin key from the Vault (optional).

Troubleshooting

MessageCause and fix
Set the OpenAI admin key.No key was given and the Vault entry is empty. Paste the key or fix the Vault entry.
Reading OpenAI costs failed (needs an admin key): HTTP 401: …The key is wrong, revoked, or an ordinary project key. Create an admin key.
Reading OpenAI costs failed (needs an admin key): HTTP 403: …The key can’t read organisation costs. Create the key as an organisation owner.
Reading OpenAI costs failed (needs an admin key): HTTP 429: …OpenAI’s rate limit for the Admin API. Shield360 paces its requests and retries once; if it still fails, the next sync retries within the hour.
Costs appear but Costs → API keys is emptyListing projects or keys failed. Costs are still correct; check that the key belongs to the organisation that owns the projects.

Reads daily Anthropic API costs from the Admin API cost report, by workspace and model. Anthropic reports cost per workspace and model only, so Shield360 also reads token usage per API key and divides each day’s cost for a model between the keys that used it. The total still matches what Anthropic charged. It also lists the organisation’s API keys and workspaces.

What you’ll need

  • An Anthropic Console organisation with the Admin API (API organisations only).
  • A member with the admin role, to create the key.
  • An Admin API key, starting sk-ant-admin.

Shield360 calls these endpoints on https://api.anthropic.com, all with GET:

EndpointUsed for
/v1/organizations/cost_reportDaily costs by workspace and model.
/v1/organizations/usage_report/messagesTokens per API key and model, to divide each day’s cost between keys.
/v1/organizations/api_keysThe organisation’s keys, for key attribution.
/v1/organizations/workspacesWorkspace names.
Create an Admin API key

In the Anthropic Console, as an organisation admin, create an Admin API key under your organisation’s settings. Admin keys start sk-ant-admin and are separate from ordinary API keys. See Anthropic’s Admin API overview and Usage and Cost API.

Copy the key

Copy the key when it’s shown. You can’t view it again.

Add it to Shield360

Add an Anthropic API costs connector and paste the key into Admin key, or name a Vault entry in Admin key from the Vault (optional).

Troubleshooting

MessageCause and fix
Set the Anthropic admin key.No key was given and the Vault entry is empty.
Reading the Anthropic cost report failed (needs an admin key): HTTP 401: …The key is wrong, revoked, or an ordinary API key. Use a key starting sk-ant-admin.
Reading the Anthropic cost report failed (needs an admin key): HTTP 403: …The organisation can’t use the Admin API, for example an individual account.
Reading the Anthropic cost report failed (needs an admin key): HTTP 429: …Rate limited. The next sync retries within the hour.
Costs appear but aren’t split by keyReading token usage failed. Costs are still correct; they stay unattributed until usage can be read.

Reads every Claude Enterprise member’s effective monthly spend limit, where it comes from (set for them, their seat tier, their group, or the organisation default), and what they have spent against it this month. Nothing is entered by hand. When an administrator raises someone from $500 to $750 in claude.ai, the next sync records the change. It also adds an audit log entry and raises an alert. Limits are shown under Costs → Budgets → Limits set in vendors.

With an optional Analytics API key, the connector also reads each member’s daily costs, broken out by product (chat, Claude Code, Cowork and others) and model. Without one it reads limits only, as before.

What you’ll need

  • A Claude Enterprise organisation with usage credits turned on (the primary owner turns them on in claude.ai billing settings).
  • The primary owner, to create the keys.
  • A Claude Enterprise Admin API key with the read:spend_limits scope.
  • Optional, for costs: a Claude Enterprise Analytics API key with the read:analytics scope.

Shield360 calls these endpoints on https://api.anthropic.com, page by page:

EndpointKeyWhat it reads
GET /v1/organizations/spend_limits/effectiveAdmin API key (read:spend_limits)Each member’s limit, where it comes from, and their spend this month
GET /v1/organizations/analytics/user_cost_reportAnalytics API key (read:analytics)Each member’s cost per day, grouped by product and model (bucket_width=1d)

Amounts arrive in cents and are shown in dollars. An amount of No limit means the member has no cap, and $0 means nothing beyond what their plan includes.

  • Costs exist from 1 January 2026, and Anthropic serves at most the last 365 days. The first sync with an Analytics API key imports everything it can. After that, each sync re-reads the days set in Days to read back.
  • Each member’s costs are stored per day as Claude Enterprise, with the product as the project and the model as the line item. The person is the member’s email address in lower case. Deleted accounts and service accounts have no email, so they’re stored under Anthropic’s user ID.
  • Anthropic usually has costs ready within 4 hours, and always within 24. Every response says how current its data is (data_refreshed_at). Shield360 stores only whole days up to that point, so a partly reported day is never saved. The next sync picks it up.
  • Anthropic can revise a month’s costs until about 7 days after the month ends. Keep Days to read back at 31 or more so those corrections are picked up.
  • The Analytics API allows 60 requests a minute for the whole organisation, shared with anything else that uses it. Shield360 spaces its requests and waits when it is rate limited.
  • If reading costs fails, the limits are still read, the sync reports costs not read: …, and the costs already stored stay. If reading limits fails, the costs are still read and the sync reports spend limits not read: …. The sync fails only when both fail.

Where the costs count

The amount is what Anthropic charges for usage after discounts and before credits. On a usage-based plan that’s the usage bill. On a seat-based plan it’s usage credits only, because seats are billed separately and Shield360 counts them as subscriptions. The costs count as billed API use in the AI cost total and the ledger, on the Anthropic line.

They don’t replace Shield360’s estimate for Anthropic API usage. The Enterprise bill covers claude.ai use, which the collector already reports as plan usage, outside the total. It doesn’t cover usage on Console API keys. For the same reason, they’re left out of the reconciliation and of per-key attribution. They show on each person’s page.

Create the key

As the primary owner, create an Admin API key for your Claude Enterprise organisation and give it the read:spend_limits scope only. See Anthropic’s Spend Limits API and Admin API keys.

Add it to Shield360

Add a Claude Enterprise connector and paste the key into Admin key, or name a Vault entry in Admin key from the Vault (optional). Choose how often to sync. A change in claude.ai shows up within that time.

Turn on API access

As the primary owner, go to claude.ai → Organization settings → API and turn on public API access. See Anthropic’s Analytics APIs.

Create the key

Create an Analytics API key. It has the read:analytics scope. Copy it when it’s shown.

Add it to Shield360

In the Claude Enterprise connector, paste the key into Analytics API key (optional), or name a Vault entry in Analytics API key from the Vault (optional). Leave Import full history on the next sync on to import costs from 1 January 2026.

MessageCause and fix
Reading Claude Enterprise spend limits failed (… read:spend_limits …): HTTP 401The admin key is wrong or revoked. Create a new one.
… HTTP 403The key lacks the read:spend_limits scope, or the organisation isn’t on Claude Enterprise.
… HTTP 400 or … HTTP 404Usage credits aren’t turned on for the organisation.
costs not read: Reading Claude Enterprise costs failed (… read:analytics …): HTTP 401The Analytics API key is wrong or revoked, or an Admin API key was pasted instead.
costs not read: … HTTP 429The organisation’s 60 requests a minute were used up, possibly by another tool. The next sync tries again.

Reads the organisation’s Copilot seats: who holds each seat, its plan, when it was assigned, and when it was last used. Seat cost comes from the seat price. On every sync, Shield360 keeps a matching subscription in step with the seat list.

What you’ll need

  • The GitHub organisation name (the login in github.com/<org>).
  • A GitHub organisation owner, to create or approve the token.
  • A token that can read Copilot billing for that organisation.
  • Your negotiated seat price, if it isn’t the list price.

Shield360 calls one endpoint on https://api.github.com: GET /orgs/{org}/copilot/billing/seats.

When Enterprise is set, it also reads the enterprise’s billing budgets with GET /enterprises/{enterprise}/settings/billing/budgets. These include enterprise, organisation, repository, cost centre and per-user budgets, such as a person’s monthly Copilot premium-request budget, each with what it has consumed. They’re shown under Limits set in vendors. Reading budgets needs an enterprise owner or billing manager’s token. If it fails, the sync still records seats and reports spend limits not read: ….

Create a token

Create one of these, as or with the approval of an organisation owner:

  • A fine-grained personal access token whose resource owner is the organisation, with the organisation permission GitHub Copilot Business set to Read-only. Fine-grained tokens can be limited to this one permission, so prefer them.
  • A classic personal access token with the manage_billing:copilot scope.

See GitHub’s reference for listing Copilot seats for the permissions it accepts, and managing personal access tokens.

Approve the token, if your organisation requires it

Organisations can require owners to approve fine-grained tokens before they work. Approve the request in the organisation’s settings.

Add it to Shield360

Add a GitHub Copilot connector and fill in:

FieldValue
GitHub organisationThe organisation login, for example contoso.
Price per seat per month (USD)Leave blank for the list price (Business $19, Enterprise $39). Set your negotiated price so seat cost matches your invoice.
TokenThe token, or name a Vault entry in Token from the Vault (optional).

Set an expiry on the token and a reminder to replace it before it expires.

Troubleshooting

MessageCause and fix
Set the GitHub organisation. or That is not a GitHub organisation name.Enter the organisation’s login (letters, digits and hyphens), not its display name or URL.
Reading Copilot seats failed (the token needs Copilot billing read access): HTTP 401: …The token is wrong or expired. Create a new one.
… HTTP 403: …The token lacks the permission, is awaiting owner approval, or its owner is not an organisation owner.
… HTTP 404: …The organisation name is wrong, or a fine-grained token’s resource owner is a different account.
… HTTP 422: …Copilot Business or Enterprise isn’t enabled for the organisation, or seats are managed somewhere this endpoint can’t read.

Reads the Cursor team’s members as seats, each member’s last active day, and usage billed beyond the included requests for the current billing cycle, per member. On every sync, Shield360 keeps a matching subscription in step with the member list.

What you’ll need

  • A Cursor team on a plan with the Admin API.
  • A Cursor team admin, to create the key.
  • A Cursor Admin API key.
  • Your negotiated seat price, if it isn’t the list price.

Shield360 calls these endpoints on https://api.cursor.com, sending the key as the HTTP basic-auth user name:

EndpointUsed for
GET /teams/membersTeam members (seats).
POST /teams/spendUsage beyond the included requests, per member, for the billing cycle.
POST /teams/daily-usage-dataEach member’s last active day.

The same POST /teams/spend response carries each member’s effective monthly limit and whether an administrator set it for them. Shield360 shows these under Limits set in vendors and records each change, so a limit raised in Cursor needs no re-entry.

Create an Admin API key

As a team admin, open the Cursor dashboard’s team settings and create an Admin API key (the app labels it Team settings → Advanced → Admin API keys). See Cursor’s Admin API documentation.

Add it to Shield360

Add a Cursor connector and fill in:

FieldValue
Price per seat per month (USD)Leave blank for the list price ($40 for Business). Set your negotiated price to match your invoice.
Admin API keyThe key, or name a Vault entry in Admin API key from the Vault (optional).

Troubleshooting

MessageCause and fix
Set the Cursor admin API key.No key was given and the Vault entry is empty.
Reading Cursor members failed (needs an admin API key): HTTP 401: …The key is wrong or revoked, or it isn’t an Admin API key.
Reading Cursor spend failed (needs an admin API key): HTTP 403: …The key can’t read team spend. Create it as a team admin.
Seats appear with no last active dayDaily usage couldn’t be read, or the member wasn’t active in the window. Seats and spend are still correct.

Microsoft 365 Copilot is an AI spend connector too: its licences become seats and a kept subscription, as here. It also reads use by app and, if you switch them on, audited interactions, so it has its own guide: Microsoft 365 Copilot connector.

Reads the ChatGPT Enterprise workspace’s active users as seats, through OpenAI’s Enterprise Compliance API. ChatGPT Enterprise bills per seat, so cost comes from the seat price. On every sync, Shield360 keeps a matching subscription in step with the user list.

What you’ll need

  • A ChatGPT Enterprise or Edu workspace.
  • The Compliance API enabled for the workspace (OpenAI does this on request).
  • The workspace id.
  • A Compliance API key.
  • Your contracted seat price.

Shield360 calls one endpoint on https://api.chatgpt.com: GET /v1/compliance/workspaces/{workspace_id}/users.

Ask OpenAI to enable the Compliance API

The Compliance API is enabled per workspace by OpenAI. Ask your OpenAI account team, or search the OpenAI Help Center for the Compliance API for Enterprise.

Create a Compliance API key and find the workspace id

Once it’s enabled, a workspace owner creates a Compliance API key as OpenAI’s instructions describe, and notes the workspace id. Copy the key when it’s shown.

Add it to Shield360

Add a ChatGPT Enterprise connector and fill in:

FieldValue
Workspace idThe workspace id (letters, digits, _ and -).
Price per seat per month (USD)Your contracted price. Enterprise is priced by contract; the default is $60.
Compliance API keyThe key, or name a Vault entry in Compliance API key from the Vault (optional).

Troubleshooting

MessageCause and fix
Set the ChatGPT workspace id. or That is not a ChatGPT workspace id.Enter the workspace id itself, not a URL or name.
Set the workspace id and the Compliance API key.The key is missing or the Vault entry is empty.
Reading ChatGPT Enterprise users failed (needs the Compliance API): HTTP 401: …The key is wrong or revoked.
… HTTP 403: …The Compliance API isn’t enabled for this workspace, or the key belongs to another workspace.
… HTTP 404: …The workspace id is wrong.

Reads daily Azure OpenAI and Azure AI Foundry costs from Azure Cost Management, as actual cost, by resource group and meter. It keeps only these services: Azure OpenAI, Cognitive Services, Foundry Models, Azure AI Foundry Models and Azure AI services. Full history is read a year at a time, going back until Cost Management has nothing more.

What you’ll need

  • A Microsoft Entra app registration with a client secret.
  • The Cost Management Reader role for the app on each subscription.
  • The directory (tenant) id and application (client) id.
  • The ids of the subscriptions that hold your Azure OpenAI resources.

Shield360 makes two kinds of request:

RequestUsed for
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/tokenClient-credentials sign-in, with the scope https://management.azure.com/.default.
POST https://management.azure.com/subscriptions/{subscription}/providers/Microsoft.CostManagement/query?api-version=2023-11-01The cost query, once per subscription per year of history.
Register an app

In the Azure portal, open Microsoft Entra ID → App registrations → New registration. Give it a name such as shield360-cost-reader, keep it single-tenant and leave the redirect URI empty. See Register an application.

Note the ids

On the app’s Overview page, copy the Directory (tenant) ID and the Application (client) ID. Subscription ids are on the Subscriptions page.

Create a client secret

Open Certificates & secrets → Client secrets → New client secret and choose an expiry. Copy the secret’s Value (not its ID) when it’s shown; you can’t see it again. Note the expiry date: the connector stops working when the secret expires.

Assign Cost Management Reader on each subscription

For each subscription, open Access control (IAM) → Add role assignment, choose Cost Management Reader, and assign it to the app. Assign it at subscription scope; it grants read access to cost data and nothing else. See Assign Azure roles using the Azure portal and Cost Management access.

With the Azure CLI, one command does the app, secret and role together for one subscription:

Terminal window
az ad sp create-for-rbac --name shield360-cost-reader \
--role "Cost Management Reader" \
--scopes /subscriptions/<subscription-id>

Its output’s appId is the client id, password the client secret and tenant the tenant id. Run az role assignment create for each additional subscription.

Add it to Shield360

Add an Azure OpenAI (Cost Management) connector and fill in:

FieldValue
Directory (tenant) idThe tenant id.
Application (client) idThe client id.
Subscription idsComma separated, for example 0b1c…, 7d2e…. Each must be a full 36-character subscription id.
Client secretThe secret’s value, or name a Vault entry in Client secret from the Vault (optional).

Role assignments can take a few minutes to apply. Azure troubleshooting is shared with Azure Cost Management; see Azure troubleshooting.

Reads daily Amazon Bedrock costs from AWS Cost Explorer, as unblended cost, by service and usage type. It keeps every service with “Bedrock” in its name, which includes models bought through AWS Marketplace (for example “Claude … (Amazon Bedrock Edition)”).

What you’ll need

  • Cost Explorer enabled for the AWS account.
  • An IAM user with an access key, allowed ce:GetCostAndUsage and, optionally, ce:GetDimensionValues.
  • Ideally, that user in the management (payer) account, to see all accounts.

Shield360 calls two AWS API actions, signed with Signature Version 4 against https://ce.us-east-1.amazonaws.com (Cost Explorer’s single endpoint):

  • ce:GetDimensionValues (optional) looks up the Cost Explorer services with “Bedrock” in their name for the window, so the cost query asks for those services only.
  • ce:GetCostAndUsage reads the daily costs, filtered to those services.

If the key isn’t allowed ce:GetDimensionValues, the sync still works: Shield360 reads the costs of every service and keeps the Bedrock ones, which can take more pages.

Enable Cost Explorer

If nobody has opened Cost Explorer in the account before, open it once in the AWS Billing and Cost Management console to enable it. Data can take up to 24 hours to appear. See Enabling Cost Explorer.

Create the policy

Create an IAM policy with this content. Cost Explorer doesn’t support resource-level permissions, so the resource is *. ce:GetDimensionValues is optional; leave it out and the connector reads every service’s costs and keeps the Bedrock ones.

{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Shield360CostExplorerRead",
"Effect": "Allow",
"Action": ["ce:GetCostAndUsage", "ce:GetDimensionValues"],
"Resource": "*"
}
]
}

See Cost Explorer API permissions.

Create an IAM user and access key

Create an IAM user with no console access, attach the policy, and create an access key for it (use case: application running outside AWS). Create it in the management account of your AWS Organization to see every member account’s costs; in a member account it sees that account only. See Managing access keys for IAM users.

Temporary credentials from an assumed role or IAM Identity Center need a session token, which the connector doesn’t take. Use the IAM user’s long-term key, and rotate it on a schedule.

Add it to Shield360

Add an Amazon Bedrock (Cost Explorer) connector and fill in:

FieldValue
Access key idThe access key id, starting AKIA.
Secret access keyThe secret, or name a Vault entry in Secret access key from the Vault (optional).

Cost Explorer keeps 14 months of history, or 38 months when multi-year data is turned on in Cost Explorer’s preferences. The full-history import starts as early as the account allows and steps forward automatically if AWS refuses the range. AWS troubleshooting is shared with AWS Cost Explorer; see AWS troubleshooting.

Reads daily AWS costs for every service from Cost Explorer, as unblended cost, grouped by service and by a cost allocation tag you name, or by linked account when no tag is set. Shown on Costs → Cloud and kept out of the AI figures.

What you’ll need

  • Cost Explorer enabled for the AWS account.
  • An IAM user with an access key, allowed ce:GetCostAndUsage only.
  • That user in the management (payer) account, to see every account.
  • Optionally, an activated cost allocation tag that names the project or team.

Shield360 calls one AWS API action: ce:GetCostAndUsage, against https://ce.us-east-1.amazonaws.com. It doesn’t call GetDimensionValues, GetTags or any other action, so it needs no other permission.

To follow the account’s AWS Budgets as well, set AWS account id (for budgets) and allow budgets:ViewBudget. Both AWS connectors then call DescribeBudgets and show each cost budget, with its actual spend, under Limits set in vendors. Leave the account id blank to skip budgets.

Follow the Amazon Bedrock IAM policy steps. This connector needs only ce:GetCostAndUsage, so you can leave ce:GetDimensionValues out of the policy, and one IAM user can serve both connectors. Create it in the management account so the bill covers every linked account. Then add an AWS (Cost Explorer, all services) connector and fill in Access key id and Secret access key (or Secret access key from the Vault (optional)).

The Cost allocation tag field names the tag that says which project or team a resource belongs to, for example Project. Leave it blank to group by linked account instead.

Tag your resources

Use one tag key consistently across resources, for example Project=payments.

Activate the tag for cost allocation

In the management account, open Billing and Cost Management → Cost allocation tags, find the user-defined tag and activate it. Activated tags can take up to 24 hours to appear, and apply from activation onward. See Activating user-defined cost allocation tags.

Enter the tag key in Shield360

Type the tag key exactly as it’s spelled in AWS (it’s case-sensitive) into Cost allocation tag.

Costs on resources without the tag, and costs from before the tag was activated, are shown as (untagged).

MessageCause and fix
Set the AWS access key id.The access key id is missing or malformed. Paste the id (upper-case letters and digits, starting AKIA).
Set the access key id and secret access key.The secret is missing or the Vault entry is empty.
The tag key has characters a tag cannot have.Check the Cost allocation tag spelling.
AWS Cost Explorer failed (needs ce:GetCostAndUsage): HTTP 400: … AccessDeniedException …The user’s policy doesn’t allow ce:GetCostAndUsage, or an organisation policy (SCP) denies it. Attach the policy above. A Bedrock key without ce:GetDimensionValues doesn’t cause this error; the connector falls back to reading every service.
… UnrecognizedClientException … or … InvalidClientTokenId …The access key id is wrong or deleted.
… InvalidSignatureException … or … SignatureDoesNotMatch …The secret access key doesn’t match the key id.
… DataUnavailableException …Cost Explorer isn’t enabled yet, or has no data for the account. Enable it and wait up to 24 hours.
… LimitExceededException …Too many Cost Explorer requests. The next sync retries within the hour.
Everything is (untagged)The tag isn’t activated as a cost allocation tag, or the key is spelled differently.
Only one account’s costsThe key belongs to a member account. Create the user in the management account.

A ValidationException about the time period during the full-history import is handled automatically: Shield360 retries with the latest start date AWS keeps.

Reads daily Azure costs for every service from Cost Management, as actual cost, grouped by service and by a tag you name, or by resource group when no tag is set. Shown on Costs → Cloud and kept out of the AI figures.

What you’ll need

  • A Microsoft Entra app registration with a client secret.
  • The Cost Management Reader role for the app on each subscription.
  • The directory (tenant) id and application (client) id.
  • The subscription ids to read.
  • Optionally, a resource tag key that names the project or team.

Shield360 makes the same two requests as the Azure OpenAI connector: a client-credentials token from login.microsoftonline.com, then a Microsoft.CostManagement/query per subscription, a year of history at a time.

Both Azure connectors also read each subscription’s cost budgets, with their current spend, from Microsoft.Consumption/budgets. The Cost Management Reader role already allows this. Budgets are shown under Limits set in vendors. Turn off Read budgets to skip them.

Follow the Azure OpenAI app registration and role steps; one app can serve both connectors. Assign Cost Management Reader on every subscription you list. Then add an Azure (Cost Management, all services) connector and fill in:

FieldValue
Directory (tenant) idThe tenant id from the app’s Overview page.
Application (client) idThe client id from the app’s Overview page.
Subscription idsComma separated, full 36-character ids.
TagThe resource tag key that names the project or team, for example project. Leave blank to group by resource group. Costs on untagged resources are shown as (untagged).
Client secretThe secret’s value, or name a Vault entry in Client secret from the Vault (optional).

These apply to both Azure connectors.

MessageCause and fix
Set the directory (tenant) id and the application (client) id.Fill in both ids.
Give one or more Azure subscription ids, comma separated.Each id must be a full subscription id (36 characters with hyphens), not a subscription name.
Set the tenant id, client id and client secret.The client secret is missing or the Vault entry is empty.
Azure sign-in failed: HTTP 400: … AADSTS90002 …The tenant id is wrong.
Azure sign-in failed: HTTP 400: … AADSTS700016 …The client id is wrong, or the app is in another tenant.
Azure sign-in failed: HTTP 401: … AADSTS7000215 …The client secret is wrong. Paste the secret’s Value, not its Secret ID.
Azure sign-in failed: … AADSTS7000222 …The client secret has expired. Create a new one and update the connector.
Azure Cost Management failed for <subscription> (needs Cost Management Reader): HTTP 401: … or HTTP 403: …The app has no Cost Management Reader role on that subscription, or the assignment hasn’t applied yet. Assign it and wait a few minutes.
Azure Cost Management failed for <subscription> …: HTTP 429: …Cost Management is throttling queries. The next sync retries within the hour.
Azure Cost Management failed for <subscription> …: HTTP 400: …The subscription type may not be supported by Cost Management. See Understand Cost Management data.

Reads daily Google Cloud costs for every service, including Vertex AI and Gemini, from the Cloud Billing export in BigQuery. Costs are grouped by service and by a resource label you name, or by Google Cloud project when no label is set, with credits applied so the figure matches the invoice. Shown on Costs → Cloud and kept out of the AI figures.

Google Cloud has no cost API of its own; the BigQuery export is the supported source. The export starts when it’s turned on, so earlier days are absent.

What you’ll need

  • Cloud Billing export to BigQuery, standard usage cost, turned on.
  • The export table’s full name, as project.dataset.table.
  • A service account with a JSON key.
  • BigQuery Job User on the table’s project, Data Viewer on the dataset.

Shield360 signs in as the service account with the read-only scope https://www.googleapis.com/auth/bigquery.readonly, then calls:

RequestUsed for
POST https://bigquery.googleapis.com/bigquery/v2/projects/{project}/queriesRuns one read-only SELECT over the export table for the window.
GET https://bigquery.googleapis.com/bigquery/v2/projects/{project}/queries/{job_id}Waits for a query BigQuery hasn’t finished within its 60-second wait (up to 10 more waits), then reads further pages of results.

{project} is the project named first in the table path, so the query job runs and is billed there.

Turn on the standard usage cost export

A billing account administrator opens Billing → Billing export → BigQuery export and turns on Standard usage cost export to a dataset. See Set up Cloud Billing data export to BigQuery.

Find the table name

Google creates a table named gcp_billing_export_v1_<billing account id> in that dataset once data arrives, which can take a few hours. Its full name is <project id>.<dataset>.<table>, for example acme-billing.billing.gcp_billing_export_v1_0123AB_4567CD_89EF01.

Create a service account

Create a service account, for example shield360-billing-reader, in the project that holds the export dataset. See Create service accounts.

Grant BigQuery Job User on the table's project

Grant BigQuery Job User (roles/bigquery.jobUser) on the project named first in the table path. Shield360 runs its query there, so this is the project that needs the role, whichever project the service account lives in.

Grant BigQuery Data Viewer on the dataset

Grant BigQuery Data Viewer (roles/bigquery.dataViewer) on the export dataset only, not the whole project. See Control access to datasets.

Create a JSON key

Create a JSON key for the service account and download it. If your organisation policy blocks service account keys, an administrator needs to allow keys for this account. See Create and delete service account keys.

Add it to Shield360

Add a Google Cloud (billing export) connector and fill in:

FieldValue
Billing export tableThe table as project.dataset.table. The project id must be the plain id (lower-case letters, digits and hyphens), not a domain-scoped id.
LabelThe resource label key that names the project or team, for example team. Leave blank to group by Google Cloud project. Resources without the label are shown as (unlabelled).
Service account key (JSON)The whole contents of the JSON key file, or name a Vault entry in Service account key from the Vault (optional).

Delete the downloaded key file once it’s stored.

Troubleshooting

MessageCause and fix
Set the billing export table as project.dataset.table.Enter the full three-part name, without backticks or a domain prefix.
A Google Cloud label key is lower case letters, digits, hyphens and underscores.Check the Label spelling; label keys start with a lower-case letter.
The service account key is not the JSON key file's contents.Paste the whole file, from { to }.
The service account key needs client_email and private_key.The JSON isn’t a service account key. Create a JSON key for the service account.
Google sign-in failed for <account>: …The key was deleted or disabled, or the service account was removed. Create a new key.
Reading the billing export failed (needs BigQuery Job User and Data Viewer): HTTP 403: … bigquery.jobs.create …Grant BigQuery Job User on the project named in the table path.
… HTTP 403: Access Denied: Table …Grant BigQuery Data Viewer on the export dataset.
… HTTP 403: … BigQuery API has not been used …Enable the BigQuery API in the project named in the table path.
… HTTP 404: Not found: Table … or … Dataset …The table name is wrong, or the export hasn’t written its first data yet.
… The request timed out.A large export took too long for the first read. Run the test again; BigQuery usually answers a repeated query from its cache.
BigQuery: …BigQuery rejected the query. The message says why, for example a table that isn’t a standard usage cost export.
BigQuery did not finish the billing export query (job <id>) in 11 minutes; nothing was recorded. …The query was still running after every wait. The connector is marked as failed and no costs are written for the window. Run the sync again (BigQuery often answers a repeated query from its cache), or lower Days to read back so each sync reads fewer days.
BigQuery did not finish the billing export query and returned no job to wait on; nothing was recorded.BigQuery returned an unfinished result with no job to poll. Run the sync again.

Reads the max budget on each LiteLLM virtual key, user and team that has one, how often it resets, and the spend LiteLLM counts against it. Shown under Limits set in vendors, with every change recorded. This connector reads limits only, not costs.

What you’ll need

  • The LiteLLM proxy’s URL, reachable from Shield360. For a proxy on a private network, turn on Allow private network.
  • The proxy’s master key, or a key with the proxy admin role.

Shield360 calls GET /key/list, GET /user/list and GET /team/list on the proxy. Keys are named by their alias. LiteLLM’s key ids are hashed again before they’re kept, and the masked key names are never read.

Choose a key

Use the master key (LITELLM_MASTER_KEY), or create a key for a user with the proxy_admin role. See LiteLLM’s budgets and virtual keys.

Add it to Shield360

Add a LiteLLM budgets connector, set Proxy URL, and paste the key into Admin key, or name a Vault entry in Admin key from the Vault (optional).

Reads the credit limit on each OpenRouter API key, how often it resets (daily, weekly, monthly or never), and the key’s usage in that period. Credits are US dollars. Disabled keys and keys without a limit are left out. Shown under Limits set in vendors. This connector reads limits only, not costs.

Shield360 calls GET https://openrouter.ai/api/v1/keys, 100 keys at a time. The masked key OpenRouter returns is never read.

Create a management key

In OpenRouter, open Settings → Provisioning keys and create a key. It can list keys but can’t call models. See OpenRouter’s provisioning keys.

Add it to Shield360

Add an OpenRouter key limits connector and paste the key into Management key, or name a Vault entry in Management key from the Vault (optional).

MessageCause and fix
Set the <field>, or name the Vault entry holding it.Saving without a secret. Paste the secret or name a Vault entry.
The vault has no entry called <name>.The Vault entry named in … from the Vault (optional) doesn’t exist in this environment. Create it or fix the name.
That is not a valid vault entry name.Vault entry names use letters, digits, ., _, / and -.
No database in <environment> to write to.The environment has no database configuration. Add one to the project’s environment first.