spend-limits-api changedmanage-claude/spend-limits-api
Nearest release: v2.1.314, published under an hour after this site recorded the change. Shown because the two are within 24 hours of each other. Nothing here says the release caused the edit.
Recorded here
Lines+159added
Lines−65removed
From line
1,185
where the diff opens
First seen
14 Aug 2026
this site's first read of the page
Recorded edits17to this page, all time
The whole hunk
from line 1185, old and new numbered
/
from line 1185
11851185
11861186## Example workflows
11871187
1188Some of these workflows combine the Spend Limits API with the [Analytics APIs](https://platform.claude.com/docs/en/manage-claude/analytics-api) cost endpoints. The Analytics cost endpoints are designed for organization-wide spend reporting across a date range. `GET /spend_limits/effective` returns the cap that currently applies to each member. Start a sweep with Analytics to discover which members to look at, then read their current caps with `/effective`.
1188Some of these workflows combine the Spend Limits API with the cost endpoint of the [Usage and Cost Analytics API](https://platform.claude.com/docs/en/manage-claude/usage-cost-analytics-api). The cost endpoint is designed for organization-wide spend reporting across a date range. `GET /spend_limits/effective` returns the cap that currently applies to each member. Start a sweep with the cost endpoint to discover which members to look at, then read their current caps with `/effective`.
11891189
1190Spend Limits endpoints require the `spend_limits` scopes and Analytics cost endpoints require `read:analytics`; see [Analytics APIs](https://platform.claude.com/docs/en/manage-claude/analytics-api) for how to provision access. The examples use one Admin API key that has the scopes of every API they call. A primary owner [selects these scopes when creating the key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys#choose-scopes-for-a-claude-enterprise-key). All monetary values on both are decimal strings in minor units (cents). Both APIs paginate with an opaque cursor. Set an explicit `limit` and page through `next_page` until it’s `null` to cover the whole organization.
1190Spend Limits endpoints require the `spend_limits` scopes and the cost endpoint requires `read:analytics`. The examples use one Admin API key that has the scopes of every API they call. A primary owner [selects these scopes when creating the key](https://platform.claude.com/docs/en/manage-claude/admin-api-keys#choose-scopes-for-a-claude-enterprise-key). All monetary values on both are decimal strings in minor units (cents). Both APIs paginate with an opaque cursor. Set an explicit `limit` and page through `next_page` until it’s `null` to cover the whole organization.
11911191
1192Two of these workflows read spend from `user_cost_report`, which remains supported. For new integrations, call the cost endpoint of the [Usage and Cost Analytics API](https://platform.claude.com/docs/en/manage-claude/usage-cost-analytics-api#migrate-from-enterprise-analytics-reports) with `group_by[]=actor&actor_types[]=user_actor` to get cost for each user.
1193
11941192### Automate the increase-request review flow
11951193
11961194Run a scheduled job that fetches pending requests, applies your organization’s approval policy, and resolves each one.
from line 1437
14391437
14401438Find members approaching their cap so you can raise it before they’re blocked.
14411439
14421. Pull each member’s month-to-date spend from the Analytics API (one row for each member, highest spend first by default):
14401. Pull each member’s month-to-date spend from the Usage and Cost Analytics API (one row for each member, highest spend first by default):
14431441
14441442 <CodeGroup>
14451443 ```bash cURL
1446 curl "https://api.anthropic.com/v1/organizations/analytics/user_cost_report?starting_at=2026-06-01T00:00:00Z&limit=1000" \
1447 -H "x-api-key: $ANTHROPIC_API_KEY" \
1448 -H "anthropic-version: 2023-06-01"
1444 curl -g "https://api.anthropic.com/v1/organizations/analytics/cost?\
1445 starting_at=2026-06-01T00:00:00Z&\
1446 group_by[]=actor&\
1447 actor_types[]=user_actor&\
1448 limit=1000" \
1449 -H "anthropic-version: 2023-06-01" \
1450 -H "anthropic-beta: analytics-usage-cost-2026-08-24" \
1451 -H "x-api-key: $ANTHROPIC_API_KEY"
14491452 ```
14501453
14511454 ```bash CLI
1452 ant beta:organization:analytics:user-cost-report list \
1455 ant beta:organization:analytics:cost list \
14531456 --starting-at 2026-06-01T00:00:00Z \
1457 --actor-type user_actor \
1458 --group-by actor \
14541459 --limit 1000
14551460 ```
14561461
from line 1462
14571462 ```python Python
14581463 client = anthropic.Anthropic()
14591464
1460 cost_rows = client.beta.organization.analytics.user_cost_report.list(
1461 starting_at="2026-06-01T00:00:00Z", limit=1000
1465 cost_rows = client.beta.organization.analytics.cost.list(
1466 starting_at="2026-06-01T00:00:00Z",
1467 actor_types=["user_actor"],
1468 group_by=["actor"],
1469 limit=1000,
14621470 )
14631471
14641472 for cost_row in cost_rows:
1465 print(f"{cost_row.actor.user_id}: {cost_row.amount}")
1473 actor = cost_row.group.actor
1474 if actor is not None and actor.type == "user_actor":
1475 print(f"{actor.user_id}: {cost_row.cost.amount}")
14661476 ```
14671477
14681478 ```typescript TypeScript
14691479 const client = new Anthropic();
14701480
1471 const costRows = await client.beta.organization.analytics.userCostReport.list({
1481 const costRows = await client.beta.organization.analytics.cost.list({
14721482 starting_at: "2026-06-01T00:00:00Z",
1483 actor_types: ["user_actor"],
1484 group_by: ["actor"],
14731485 limit: 1000
14741486 });
14751487
14761488 for await (const costRow of costRows) {
1477 console.log(`${costRow.actor.user_id}: ${costRow.amount}`);
1489 const { actor } = costRow.group;
1490 if (actor?.type === "user_actor") {
1491 console.log(`${actor.user_id}: ${costRow.cost.amount}`);
1492 }
14781493 }
14791494 ```
14801495
14811496 ```csharp C#
1497 using Anthropic.Models.Beta.Organization.Analytics;
1498 using Anthropic.Models.Beta.Organization.Analytics.Cost;
1499
14821500 AnthropicClient client = new();
14831501
1484 var page = await client.Beta.Organization.Analytics.UserCostReport.List(
1502 var page = await client.Beta.Organization.Analytics.Cost.List(
14851503 new()
14861504 {
14871505 StartingAt = DateTimeOffset.Parse("2026-06-01T00:00:00Z"),
1506 ActorTypes = [BetaAnalyticsActorType.UserActor],
1507 GroupBy = [BetaAnalyticsCostGroupBy.Actor],
14881508 Limit = 1000,
14891509 }
14901510 );
from line 1511
14911511
14921512 await foreach (var costRow in page.Paginate())
14931513 {
1494 Console.WriteLine($"{costRow.Actor.UserID}: {costRow.Amount}");
1514 if (costRow.Group.Actor is { } actor && actor.TryPickReportUser(out var user))
1515 {
1516 Console.WriteLine($"{user.UserID}: {costRow.Cost.Amount}");
1517 }
14951518 }
14961519 ```
14971520
from line 1521
14981521 ```go Go
14991522 client := anthropic.NewClient()
15001523
1501 costRows := client.Beta.Organization.Analytics.UserCostReport.ListAutoPaging(context.Background(), anthropic.BetaOrganizationAnalyticsUserCostReportListParams{
1524 costRows := client.Beta.Organization.Analytics.Cost.ListAutoPaging(context.Background(), anthropic.BetaOrganizationAnalyticsCostListParams{
15021525 StartingAt: time.Date(2026, time.June, 1, 0, 0, 0, 0, time.UTC),
1526 ActorTypes: []anthropic.BetaAnalyticsActorType{anthropic.BetaAnalyticsActorTypeUserActor},
1527 GroupBy: []anthropic.BetaAnalyticsCostGroupBy{anthropic.BetaAnalyticsCostGroupByActor},
15031528 Limit: anthropic.Int(1000),
15041529 })
15051530
15061531 for costRows.Next() {
15071532 costRow := costRows.Current()
1508 fmt.Printf("%s: %s\n", costRow.Actor.UserID, costRow.Amount)
1533 if user, ok := costRow.Group.Actor.AsAny().(anthropic.BetaAnalyticsReportUserActor); ok {
1534 fmt.Printf("%s: %s\n", user.UserID, costRow.Cost.Amount)
1535 }
15091536 }
15101537 if err := costRows.Err(); err != nil {
15111538 log.Fatal(err)
from line 1540
15131540 ```
15141541
15151542 ```java Java
1516 import com.anthropic.models.beta.organization.analytics.usercostreport.UserCostReportListParams;
1543 import com.anthropic.models.beta.organization.analytics.BetaAnalyticsActorType;
1544 import com.anthropic.models.beta.organization.analytics.cost.BetaAnalyticsCostGroupBy;
1545 import com.anthropic.models.beta.organization.analytics.cost.CostListParams;
15171546 import java.time.OffsetDateTime;
15181547
15191548 void main() {
15201549 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
15211550
1522 var params = UserCostReportListParams.builder()
1551 var params = CostListParams.builder()
15231552 .startingAt(OffsetDateTime.parse("2026-06-01T00:00:00Z"))
1553 .addActorType(BetaAnalyticsActorType.USER_ACTOR)
1554 .addGroupBy(BetaAnalyticsCostGroupBy.ACTOR)
15241555 .limit(1000)
15251556 .build();
1526 var costRows = client.beta().organization().analytics().userCostReport().list(params);
1557 var costRows = client.beta().organization().analytics().cost().list(params);
15271558
15281559 for (var costRow : costRows.autoPager()) {
1529 IO.println(costRow.actor().userId() + ": " + costRow.amount());
1560 costRow.group().actor().flatMap(actor -> actor.user()).ifPresent(user ->
1561 IO.println(user.userId() + ": " + costRow.cost().amount())
1562 );
15301563 }
15311564 }
15321565 ```
15331566
15341567 ```php PHP
1568 use Anthropic\Beta\Organization\Analytics\AnalyticsReportUserActor;
1569 // ...
1570
15351571 $client = new Client();
15361572
1537 $costRows = $client->beta->organization->analytics->userCostReport->list(
1573 $costRows = $client->beta->organization->analytics->cost->list(
15381574 startingAt: new \DateTimeImmutable('2026-06-01T00:00:00Z'),
1575 actorTypes: ['user_actor'],
1576 groupBy: ['actor'],
15391577 limit: 1000,
15401578 );
15411579
15421580 foreach ($costRows->pagingEachItem() as $costRow) {
1543 echo "{$costRow->actor->userID}: {$costRow->amount}\n";
1581 $actor = $costRow->group->actor;
1582 if ($actor instanceof AnalyticsReportUserActor) {
1583 echo "{$actor->userID}: {$costRow->cost->amount}\n";
1584 }
15441585 }
15451586 ```
15461587
from line 1588
15471588 ```ruby Ruby
15481589 client = Anthropic::Client.new
15491590
1550 page = client.beta.organization.analytics.user_cost_report.list(
1591 page = client.beta.organization.analytics.cost.list(
15511592 starting_at: Time.utc(2026, 6, 1),
1593 actor_types: [:user_actor],
1594 group_by: [:actor],
15521595 limit: 1000
15531596 )
15541597
15551598 page.auto_paging_each do |cost_row|
1556 puts "#{cost_row.actor.user_id}: #{cost_row.amount}"
1599 actor = cost_row.group.actor
1600 if actor.is_a?(Anthropic::Models::Beta::Organization::BetaAnalyticsReportUserActor)
1601 puts "#{actor.user_id}: #{cost_row.cost.amount}"
1602 end
15571603 end
15581604 ```
15591605 </CodeGroup>
15601606
1561 Each row contains `actor.user_id`, `actor.email_address`, and `amount` (the member’s spend in cents). Page through `next_page` to cover the whole organization.
1607 Each row contains `group.actor.user_id`, `group.actor.email_address`, and `cost.amount` (the member’s spend in cents). Page through `next_page` to cover the whole organization.
15621608
156316092. For the top spenders (or everyone above a dollar threshold), fetch effective caps in batches:
15641610
from line 1763
17171763
17181764Surface members whose spend has jumped week over week.
17191765
17201. Pull per-member daily cost for the trailing 2 weeks from the Analytics API:
17661. Pull per-member daily cost for the trailing 2 weeks from the Usage and Cost Analytics API:
17211767
17221768 <CodeGroup>
17231769 ```bash cURL
1724 curl "https://api.anthropic.com/v1/organizations/analytics/user_cost_report?starting_at=2026-06-09T00:00:00Z&ending_at=2026-06-23T00:00:00Z&bucket_width=1d&limit=1000" \
1725 -H "x-api-key: $ANTHROPIC_API_KEY" \
1726 -H "anthropic-version: 2023-06-01"
1770 curl -g "https://api.anthropic.com/v1/organizations/analytics/cost?\
1771 starting_at=2026-06-09T00:00:00Z&\
1772 ending_at=2026-06-23T00:00:00Z&\
1773 time_bucket_width=1d&\
1774 group_by[]=actor&\
1775 actor_types[]=user_actor&\
1776 limit=1000" \
1777 -H "anthropic-version: 2023-06-01" \
1778 -H "anthropic-beta: analytics-usage-cost-2026-08-24" \
1779 -H "x-api-key: $ANTHROPIC_API_KEY"
17271780 ```
17281781
17291782 ```bash CLI
1730 ant beta:organization:analytics:user-cost-report list \
1783 ant beta:organization:analytics:cost list \
17311784 --starting-at 2026-06-09T00:00:00Z \
17321785 --ending-at 2026-06-23T00:00:00Z \
1733 --bucket-width 1d \
1786 --time-bucket-width 1d \
1787 --actor-type user_actor \
1788 --group-by actor \
17341789 --limit 1000
17351790 ```
17361791
from line 1792
17371792 ```python Python
17381793 client = anthropic.Anthropic()
17391794
1740 cost_rows = client.beta.organization.analytics.user_cost_report.list(
1795 cost_rows = client.beta.organization.analytics.cost.list(
17411796 starting_at="2026-06-09T00:00:00Z",
17421797 ending_at="2026-06-23T00:00:00Z",
1743 bucket_width="1d",
1798 time_bucket_width="1d",
1799 actor_types=["user_actor"],
1800 group_by=["actor"],
17441801 limit=1000,
17451802 )
17461803
17471804 for cost_row in cost_rows:
1748 print(f"{cost_row.actor.user_id} {cost_row.starting_at}: {cost_row.amount}")
1805 actor = cost_row.group.actor
1806 if actor is not None and actor.type == "user_actor":
1807 print(f"{actor.user_id} {cost_row.starting_at}: {cost_row.cost.amount}")
17491808 ```
17501809
17511810 ```typescript TypeScript
17521811 const client = new Anthropic();
17531812
1754 const costRows = await client.beta.organization.analytics.userCostReport.list({
1813 const costRows = await client.beta.organization.analytics.cost.list({
17551814 starting_at: "2026-06-09T00:00:00Z",
17561815 ending_at: "2026-06-23T00:00:00Z",
1757 bucket_width: "1d",
1816 time_bucket_width: "1d",
1817 actor_types: ["user_actor"],
1818 group_by: ["actor"],
17581819 limit: 1000
17591820 });
17601821
17611822 for await (const costRow of costRows) {
1762 console.log(`${costRow.actor.user_id} ${costRow.starting_at}: ${costRow.amount}`);
1823 const { actor } = costRow.group;
1824 if (actor?.type === "user_actor") {
1825 console.log(`${actor.user_id} ${costRow.starting_at}: ${costRow.cost.amount}`);
1826 }
17631827 }
17641828 ```
17651829
17661830 ```csharp C#
1767 using Anthropic.Models.Beta.Organization.Analytics.UserCostReport;
1831 using Anthropic.Models.Beta.Organization.Analytics;
1832 using Anthropic.Models.Beta.Organization.Analytics.Cost;
17681833
17691834 AnthropicClient client = new();
17701835
1771 var page = await client.Beta.Organization.Analytics.UserCostReport.List(
1836 var page = await client.Beta.Organization.Analytics.Cost.List(
17721837 new()
17731838 {
17741839 StartingAt = DateTimeOffset.Parse("2026-06-09T00:00:00Z"),
17751840 EndingAt = DateTimeOffset.Parse("2026-06-23T00:00:00Z"),
1776 BucketWidth = BucketWidth.Day,
1841 TimeBucketWidth = BetaAnalyticsTimeBucketWidth.Day,
1842 ActorTypes = [BetaAnalyticsActorType.UserActor],
1843 GroupBy = [BetaAnalyticsCostGroupBy.Actor],
17771844 Limit = 1000,
17781845 }
17791846 );
from line 1847
17801847
17811848 await foreach (var costRow in page.Paginate())
17821849 {
1783 Console.WriteLine($"{costRow.Actor.UserID} {costRow.StartingAt}: {costRow.Amount}");
1850 if (costRow.Group.Actor is { } actor && actor.TryPickReportUser(out var user))
1851 {
1852 Console.WriteLine($"{user.UserID} {costRow.StartingAt}: {costRow.Cost.Amount}");
1853 }
17841854 }
17851855 ```
17861856
from line 1857
17871857 ```go Go
17881858 client := anthropic.NewClient()
17891859
1790 costRows := client.Beta.Organization.Analytics.UserCostReport.ListAutoPaging(context.Background(), anthropic.BetaOrganizationAnalyticsUserCostReportListParams{
1791 StartingAt: time.Date(2026, time.June, 9, 0, 0, 0, 0, time.UTC),
1792 EndingAt: anthropic.Time(time.Date(2026, time.June, 23, 0, 0, 0, 0, time.UTC)),
1793 BucketWidth: anthropic.BetaOrganizationAnalyticsUserCostReportListParamsBucketWidthDay,
1794 Limit: anthropic.Int(1000),
1860 costRows := client.Beta.Organization.Analytics.Cost.ListAutoPaging(context.Background(), anthropic.BetaOrganizationAnalyticsCostListParams{
1861 StartingAt: time.Date(2026, time.June, 9, 0, 0, 0, 0, time.UTC),
1862 EndingAt: anthropic.Time(time.Date(2026, time.June, 23, 0, 0, 0, 0, time.UTC)),
1863 TimeBucketWidth: anthropic.BetaAnalyticsTimeBucketWidthDay,
1864 ActorTypes: []anthropic.BetaAnalyticsActorType{anthropic.BetaAnalyticsActorTypeUserActor},
1865 GroupBy: []anthropic.BetaAnalyticsCostGroupBy{anthropic.BetaAnalyticsCostGroupByActor},
1866 Limit: anthropic.Int(1000),
17951867 })
17961868
17971869 for costRows.Next() {
17981870 costRow := costRows.Current()
1799 fmt.Printf("%s %s: %s\n", costRow.Actor.UserID, costRow.StartingAt, costRow.Amount)
1871 if user, ok := costRow.Group.Actor.AsAny().(anthropic.BetaAnalyticsReportUserActor); ok {
1872 fmt.Printf("%s %s: %s\n", user.UserID, costRow.StartingAt.Format(time.RFC3339), costRow.Cost.Amount)
1873 }
18001874 }
18011875 if err := costRows.Err(); err != nil {
18021876 log.Fatal(err)
from line 1878
18041878 ```
18051879
18061880 ```java Java
1807 import com.anthropic.models.beta.organization.analytics.usercostreport.UserCostReportListParams;
1881 import com.anthropic.models.beta.organization.analytics.BetaAnalyticsActorType;
1882 import com.anthropic.models.beta.organization.analytics.BetaAnalyticsTimeBucketWidth;
1883 import com.anthropic.models.beta.organization.analytics.cost.BetaAnalyticsCostGroupBy;
1884 import com.anthropic.models.beta.organization.analytics.cost.CostListParams;
18081885 import java.time.OffsetDateTime;
18091886
18101887 void main() {
18111888 AnthropicClient client = AnthropicOkHttpClient.fromEnv();
18121889
1813 var params = UserCostReportListParams.builder()
1890 var params = CostListParams.builder()
18141891 .startingAt(OffsetDateTime.parse("2026-06-09T00:00:00Z"))
18151892 .endingAt(OffsetDateTime.parse("2026-06-23T00:00:00Z"))
1816 .bucketWidth(UserCostReportListParams.BucketWidth.DAY)
1893 .timeBucketWidth(BetaAnalyticsTimeBucketWidth.DAY)
1894 .addActorType(BetaAnalyticsActorType.USER_ACTOR)
1895 .addGroupBy(BetaAnalyticsCostGroupBy.ACTOR)
18171896 .limit(1000)
18181897 .build();
1819 var costRows = client.beta().organization().analytics().userCostReport().list(params);
1898 var costRows = client.beta().organization().analytics().cost().list(params);
18201899
18211900 for (var costRow : costRows.autoPager()) {
1822 IO.println(costRow.actor().userId() + " " + costRow.startingAt().orElseThrow() + ": " + costRow.amount());
1901 costRow.group().actor().flatMap(actor -> actor.user()).ifPresent(user ->
1902 IO.println(user.userId() + " " + costRow.startingAt() + ": " + costRow.cost().amount())
1903 );
18231904 }
18241905 }
18251906 ```
18261907
18271908 ```php PHP
1909 use Anthropic\Beta\Organization\Analytics\AnalyticsReportUserActor;
1910 // ...
1911
18281912 $client = new Client();
18291913
1830 $costRows = $client->beta->organization->analytics->userCostReport->list(
1914 $costRows = $client->beta->organization->analytics->cost->list(
18311915 startingAt: new \DateTimeImmutable('2026-06-09T00:00:00Z'),
18321916 endingAt: new \DateTimeImmutable('2026-06-23T00:00:00Z'),
1833 bucketWidth: '1d',
1917 timeBucketWidth: '1d',
1918 actorTypes: ['user_actor'],
1919 groupBy: ['actor'],
18341920 limit: 1000,
18351921 );
18361922
18371923 foreach ($costRows->pagingEachItem() as $costRow) {
1838 $startingAt = $costRow->startingAt?->format(\DateTimeInterface::ATOM);
1839 echo "{$costRow->actor->userID} {$startingAt}: {$costRow->amount}\n";
1924 $actor = $costRow->group->actor;
1925 if ($actor instanceof AnalyticsReportUserActor) {
1926 $startingAt = $costRow->startingAt->format(\DateTimeInterface::ATOM);
1927 echo "{$actor->userID} {$startingAt}: {$costRow->cost->amount}\n";
1928 }
18401929 }
18411930 ```
18421931
from line 1932
18431932 ```ruby Ruby
18441933 client = Anthropic::Client.new
18451934
1846 page = client.beta.organization.analytics.user_cost_report.list(
1935 page = client.beta.organization.analytics.cost.list(
18471936 starting_at: Time.utc(2026, 6, 9),
18481937 ending_at: Time.utc(2026, 6, 23),
1849 bucket_width: :"1d",
1938 time_bucket_width: :"1d",
1939 actor_types: [:user_actor],
1940 group_by: [:actor],
18501941 limit: 1000
18511942 )
18521943
18531944 page.auto_paging_each do |cost_row|
1854 puts "#{cost_row.actor.user_id} #{cost_row.starting_at}: #{cost_row.amount}"
1945 actor = cost_row.group.actor
1946 if actor.is_a?(Anthropic::Models::Beta::Organization::BetaAnalyticsReportUserActor)
1947 puts "#{actor.user_id} #{cost_row.starting_at}: #{cost_row.cost.amount}"
1948 end
18551949 end
18561950 ```
18571951 </CodeGroup>
18581952
1859 With `bucket_width` set, each member spans one row for each day with usage. Page through `next_page` to collect every member’s full series.
1953 With `time_bucket_width` set, each member spans one row for each day with usage. Page through `next_page` to collect every member’s full series.
18601954
18612. Group rows by `actor.user_id`. For each member, sum the most recent 7 days and the prior 7 days. Flag members whose recent week exceeds the prior week by your chosen multiple (for example, three). Recent-day cost is provisional and can be revised upward; for repeatable comparisons, set `ending_at` at or before a previously returned `data_refreshed_at` (see [Data availability and freshness](https://platform.claude.com/docs/en/manage-claude/analytics-api#data-availability-and-freshness)).
19552. Group rows by `group.actor.user_id`. For each member, sum the most recent 7 days and the prior 7 days. Flag members whose recent week exceeds the prior week by your chosen multiple (for example, three). Cost for recent days can still change. For repeatable comparisons, set `ending_at` at or before a `data_refreshed_at` you have already seen (see [Data freshness](https://platform.claude.com/docs/en/manage-claude/usage-cost-analytics-api#data-freshness)).
18621956
186319573. Act on flagged members: adjust the cap with `POST /v1/organizations/spend_limits`, or contact the member.
18641958
No line in this hunk matches that.