Skip to content

Commit 665f6ea

Browse files
committed
feat(billing): add usage.get method, update usage.paygo endpoint
1 parent 9938665 commit 665f6ea

5 files changed

Lines changed: 303 additions & 12 deletions

File tree

src/resources/billing/api.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ Methods:
1414

1515
Types:
1616

17+
- <code><a href="./src/resources/billing/usage.ts">UsageGetResponse</a></code>
1718
- <code><a href="./src/resources/billing/usage.ts">UsagePaygoResponse</a></code>
1819

1920
Methods:
2021

21-
- <code title="get /accounts/{account_id}/billing/usage/paygo">client.billing.usage.<a href="./src/resources/billing/usage.ts">paygo</a>({ ...params }) -> UsagePaygoResponse</code>
22+
- <code title="get /accounts/{account_id}/billable/usage">client.billing.usage.<a href="./src/resources/billing/usage.ts">get</a>({ ...params }) -> UsageGetResponse</code>
23+
- <code title="get /accounts/{account_id}/paygo-usage">client.billing.usage.<a href="./src/resources/billing/usage.ts">paygo</a>({ ...params }) -> UsagePaygoResponse</code>

src/resources/billing/billing.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { APIResource } from '../../resource';
44
import * as ProfilesAPI from './profiles';
55
import { ProfileGetParams, ProfileGetResponse, Profiles } from './profiles';
66
import * as UsageAPI from './usage';
7-
import { Usage, UsagePaygoParams, UsagePaygoResponse } from './usage';
7+
import { Usage, UsageGetParams, UsageGetResponse, UsagePaygoParams, UsagePaygoResponse } from './usage';
88

99
export class Billing extends APIResource {
1010
profiles: ProfilesAPI.Profiles = new ProfilesAPI.Profiles(this._client);
@@ -23,7 +23,9 @@ export declare namespace Billing {
2323

2424
export {
2525
Usage as Usage,
26+
type UsageGetResponse as UsageGetResponse,
2627
type UsagePaygoResponse as UsagePaygoResponse,
28+
type UsageGetParams as UsageGetParams,
2729
type UsagePaygoParams as UsagePaygoParams,
2830
};
2931
}

src/resources/billing/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22

33
export { Billing } from './billing';
44
export { Profiles, type ProfileGetResponse, type ProfileGetParams } from './profiles';
5-
export { Usage, type UsagePaygoResponse, type UsagePaygoParams } from './usage';
5+
export {
6+
Usage,
7+
type UsageGetResponse,
8+
type UsagePaygoResponse,
9+
type UsageGetParams,
10+
type UsagePaygoParams,
11+
} from './usage';

src/resources/billing/usage.ts

Lines changed: 268 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,30 @@ import { APIResource } from '../../resource';
44
import * as Core from '../../core';
55

66
export class Usage extends APIResource {
7+
/**
8+
* Returns cost and usage data for a single Cloudflare account, aligned with the
9+
* [FinOps FOCUS v1.3](https://focus.finops.org/focus-specification/v1-3/) Cost and
10+
* Usage dataset specification.
11+
*
12+
* Each record represents one billable metric for one account on one day. This
13+
* includes all metered usage, including usage that falls within free-tier
14+
* allowances and may result in zero cost.
15+
*
16+
* **Note:** Cost and pricing fields are not yet populated and will be absent from
17+
* responses until billing integration is complete.
18+
*
19+
* When `from` and `to` are omitted, defaults to the start of the current month
20+
* through today. The maximum date range is 31 days.
21+
*/
22+
get(params: UsageGetParams, options?: Core.RequestOptions): Core.APIPromise<UsageGetResponse> {
23+
const { account_id, ...query } = params;
24+
return (
25+
this._client.get(`/accounts/${account_id}/billable/usage`, { query, ...options }) as Core.APIPromise<{
26+
result: UsageGetResponse;
27+
}>
28+
)._thenUnwrap((obj) => obj.result);
29+
}
30+
731
/**
832
* Returns billable usage data for PayGo (self-serve) accounts. When no query
933
* parameters are provided, returns usage for the current billing period. This
@@ -13,14 +37,212 @@ export class Usage extends APIResource {
1337
paygo(params: UsagePaygoParams, options?: Core.RequestOptions): Core.APIPromise<UsagePaygoResponse> {
1438
const { account_id, ...query } = params;
1539
return (
16-
this._client.get(`/accounts/${account_id}/billing/usage/paygo`, {
17-
query,
18-
...options,
19-
}) as Core.APIPromise<{ result: UsagePaygoResponse }>
40+
this._client.get(`/accounts/${account_id}/paygo-usage`, { query, ...options }) as Core.APIPromise<{
41+
result: UsagePaygoResponse;
42+
}>
2043
)._thenUnwrap((obj) => obj.result);
2144
}
2245
}
2346

47+
/**
48+
* Contains the array of cost and usage records.
49+
*/
50+
export type UsageGetResponse = Array<UsageGetResponse.UsageGetResponseItem>;
51+
52+
export namespace UsageGetResponse {
53+
/**
54+
* A single cost and usage record for a metered product within a specific charge
55+
* period, aligned with the FinOps FOCUS v1.3 specification.
56+
*/
57+
export interface UsageGetResponseItem {
58+
/**
59+
* Public identifier of the Cloudflare account (account tag).
60+
*/
61+
BillingAccountId: string;
62+
63+
/**
64+
* Display name of the Cloudflare account.
65+
*/
66+
BillingAccountName: string;
67+
68+
/**
69+
* Highest-level classification of a charge based on the nature of how it gets
70+
* billed. Currently only "Usage" is supported.
71+
*/
72+
ChargeCategory: 'Usage';
73+
74+
/**
75+
* Self-contained summary of the charge's purpose and price.
76+
*/
77+
ChargeDescription: string;
78+
79+
/**
80+
* Indicates how often a charge occurs. Currently only "Usage-Based" is supported.
81+
*/
82+
ChargeFrequency: 'Usage-Based';
83+
84+
/**
85+
* Exclusive end of the time interval during which the usage was consumed.
86+
*/
87+
ChargePeriodEnd: string;
88+
89+
/**
90+
* Inclusive start of the time interval during which the usage was consumed.
91+
*/
92+
ChargePeriodStart: string;
93+
94+
/**
95+
* Measured usage amount within the charge period. Reflects raw metered consumption
96+
* before pricing transformations.
97+
*/
98+
ConsumedQuantity: number;
99+
100+
/**
101+
* Unit of measure for the consumed quantity (e.g., "GB", "Requests",
102+
* "vCPU-Hours").
103+
*/
104+
ConsumedUnit: string;
105+
106+
/**
107+
* Name of the entity providing the underlying infrastructure or platform.
108+
*/
109+
HostProviderName: string;
110+
111+
/**
112+
* Name of the entity responsible for invoicing for the services consumed.
113+
*/
114+
InvoiceIssuerName: string;
115+
116+
/**
117+
* Name of the entity that made the services available for purchase.
118+
*/
119+
ServiceProviderName: string;
120+
121+
/**
122+
* The display name of the billable metric. Cloudflare extension; replaces FOCUS
123+
* SkuMeter.
124+
*/
125+
x_BillableMetricName: string;
126+
127+
/**
128+
* A charge serving as the basis for invoicing, inclusive of all reduced rates and
129+
* discounts while excluding the amortization of upfront charges (one-time or
130+
* recurring).
131+
*/
132+
BilledCost?: number | null;
133+
134+
/**
135+
* Currency that a charge was billed in (ISO 4217).
136+
*/
137+
BillingCurrency?: string | null;
138+
139+
/**
140+
* Exclusive end of the billing cycle that contains this usage record.
141+
*/
142+
BillingPeriodEnd?: string | null;
143+
144+
/**
145+
* Inclusive start of the billing cycle that contains this usage record.
146+
*/
147+
BillingPeriodStart?: string | null;
148+
149+
/**
150+
* Indicates whether the row represents a correction to one or more charges
151+
* invoiced in a previous billing period.
152+
*/
153+
ChargeClass?: 'Correction' | null;
154+
155+
/**
156+
* Cost calculated by multiplying ContractedUnitPrice and the corresponding
157+
* PricingQuantity.
158+
*/
159+
ContractedCost?: number | null;
160+
161+
/**
162+
* The agreed-upon unit price for a single PricingUnit of the associated billable
163+
* metric, inclusive of negotiated discounts, if present, while excluding any other
164+
* discounts.
165+
*/
166+
ContractedUnitPrice?: number | null;
167+
168+
/**
169+
* The amortized cost of the charge after applying all reduced rates, discounts,
170+
* and the applicable portion of relevant, prepaid purchases (one-time or
171+
* recurring) that covered the charge.
172+
*/
173+
EffectiveCost?: number | null;
174+
175+
/**
176+
* Cost calculated by multiplying ListUnitPrice and the corresponding
177+
* PricingQuantity.
178+
*/
179+
ListCost?: number | null;
180+
181+
/**
182+
* Suggested provider-published unit price for a single PricingUnit of the
183+
* associated billable metric, exclusive of any discounts.
184+
*/
185+
ListUnitPrice?: number | null;
186+
187+
/**
188+
* Volume of a given service used or purchased, based on the PricingUnit.
189+
*/
190+
PricingQuantity?: number | null;
191+
192+
/**
193+
* Provider-specified measurement unit for determining unit prices, indicating how
194+
* the provider rates measured usage after applying pricing rules like block
195+
* pricing.
196+
*/
197+
PricingUnit?: string | null;
198+
199+
/**
200+
* Provider-assigned identifier for an isolated geographic area where a service is
201+
* provided.
202+
*/
203+
RegionId?: string | null;
204+
205+
/**
206+
* Name of an isolated geographic area where a service is provided.
207+
*/
208+
RegionName?: string | null;
209+
210+
/**
211+
* Unique identifier assigned to a grouping of services. For Cloudflare, this is
212+
* the subscription or contract ID.
213+
*/
214+
SubAccountId?: string;
215+
216+
/**
217+
* Name assigned to a grouping of services. For Cloudflare, this is the
218+
* subscription or contract display name.
219+
*/
220+
SubAccountName?: string;
221+
222+
/**
223+
* The unique identifier for the billable metric in the Cloudflare catalog.
224+
* Cloudflare extension; replaces FOCUS SkuId.
225+
*/
226+
x_BillableMetricId?: string;
227+
228+
/**
229+
* The product family the charge belongs to (e.g., "R2", "Workers"). Cloudflare
230+
* extension; replaces FOCUS ServiceName.
231+
*/
232+
x_ProductFamilyName?: string;
233+
234+
/**
235+
* The identifier for the Cloudflare zone (zone tag). Cloudflare extension.
236+
*/
237+
x_ZoneId?: string | null;
238+
239+
/**
240+
* The display name of the Cloudflare zone. Cloudflare extension.
241+
*/
242+
x_ZoneName?: string | null;
243+
}
244+
}
245+
24246
/**
25247
* Contains the array of billable usage records.
26248
*/
@@ -87,26 +309,65 @@ export namespace UsagePaygoResponse {
87309
* Identifies the Cloudflare service.
88310
*/
89311
ServiceName: string;
312+
313+
/**
314+
* Identifies the product family for the Cloudflare service.
315+
*/
316+
ServiceFamilyName?: string;
90317
}
91318
}
92319

320+
export interface UsageGetParams {
321+
/**
322+
* Path param: Represents a Cloudflare resource identifier tag.
323+
*/
324+
account_id: string;
325+
326+
/**
327+
* Query param: Start date for the usage query (ISO 8601). Required if `to` is set.
328+
* When omitted along with `to`, defaults to the start of the current month.
329+
* Filters by charge period (when consumption happened), not billing period. The
330+
* maximum date range is 31 days.
331+
*/
332+
from?: string;
333+
334+
/**
335+
* Query param: Filter results by billable metric id (e.g.,
336+
* workers_standard_requests).
337+
*/
338+
metric?: string;
339+
340+
/**
341+
* Query param: End date for the usage query (ISO 8601). Required if `from` is set.
342+
* When omitted along with `from`, defaults to today. Filters by charge period
343+
* (when consumption happened), not billing period. The maximum date range is 31
344+
* days.
345+
*/
346+
to?: string;
347+
}
348+
93349
export interface UsagePaygoParams {
94350
/**
95351
* Path param: Represents a Cloudflare resource identifier tag.
96352
*/
97353
account_id: string;
98354

99355
/**
100-
* Query param: Defines the start date for the usage query (e.g., 2025-02-01).
356+
* Query param: Start date for the usage query (ISO 8601).
101357
*/
102358
from?: string;
103359

104360
/**
105-
* Query param: Defines the end date for the usage query (e.g., 2025-03-01).
361+
* Query param: End date for the usage query (ISO 8601).
106362
*/
107363
to?: string;
108364
}
109365

110366
export declare namespace Usage {
111-
export { type UsagePaygoResponse as UsagePaygoResponse, type UsagePaygoParams as UsagePaygoParams };
367+
export {
368+
type UsageGetResponse as UsageGetResponse,
369+
type UsagePaygoResponse as UsagePaygoResponse,
370+
type UsageGetParams as UsageGetParams,
371+
type UsagePaygoParams as UsagePaygoParams,
372+
};
112373
}

tests/api-resources/billing/usage.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,26 @@ const client = new Cloudflare({
1010
});
1111

1212
describe('resource usage', () => {
13+
test('get: only required params', async () => {
14+
const responsePromise = client.billing.usage.get({ account_id: '023e105f4ecef8ad9ca31a8372d0c353' });
15+
const rawResponse = await responsePromise.asResponse();
16+
expect(rawResponse).toBeInstanceOf(Response);
17+
const response = await responsePromise;
18+
expect(response).not.toBeInstanceOf(Response);
19+
const dataAndResponse = await responsePromise.withResponse();
20+
expect(dataAndResponse.data).toBe(response);
21+
expect(dataAndResponse.response).toBe(rawResponse);
22+
});
23+
24+
test('get: required and optional params', async () => {
25+
const response = await client.billing.usage.get({
26+
account_id: '023e105f4ecef8ad9ca31a8372d0c353',
27+
from: '2025-05-01',
28+
metric: 'workers_standard_requests',
29+
to: '2025-05-31',
30+
});
31+
});
32+
1333
test('paygo: only required params', async () => {
1434
const responsePromise = client.billing.usage.paygo({ account_id: '023e105f4ecef8ad9ca31a8372d0c353' });
1535
const rawResponse = await responsePromise.asResponse();
@@ -24,8 +44,8 @@ describe('resource usage', () => {
2444
test('paygo: required and optional params', async () => {
2545
const response = await client.billing.usage.paygo({
2646
account_id: '023e105f4ecef8ad9ca31a8372d0c353',
27-
from: '2025-02-01',
28-
to: '2025-03-01',
47+
from: '2025-05-01',
48+
to: '2025-05-31',
2949
});
3050
});
3151
});

0 commit comments

Comments
 (0)