Skip to content

Commit 0d94d28

Browse files
authored
feat: v3 invoice api actions (#4671)
1 parent 9456faa commit 0d94d28

17 files changed

Lines changed: 1836 additions & 137 deletions

File tree

api/spec/packages/aip-client-javascript/README.md

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -425,12 +425,16 @@ they can change or be removed without notice or semver consideration.
425425

426426
### Internal Invoices
427427

428-
| Method | HTTP | Description |
429-
| --------------------------------- | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
430-
| `client.internal.invoices.list` | `GET /openmeter/billing/invoices` | List billing invoices. Returns a page of invoices. Gathering invoices are never included. Use `filter` to narrow by status, customer, dates, or service period start. Use `sort` to control ordering. |
431-
| `client.internal.invoices.get` | `GET /openmeter/billing/invoices/{invoiceId}` | Get a billing invoice by ID. Returns the full invoice resource including line items, status details, totals, and workflow configuration snapshot. |
432-
| `client.internal.invoices.update` | `PUT /openmeter/billing/invoices/{invoiceId}` | Update a billing invoice. Only the mutable fields of the invoice can be edited: description, labels, supplier, customer, workflow settings, and top-level lines. Top-level lines are matched by `id`; lines without an `id` are created, and existing lines omitted from `lines` are deleted. Detailed (child) lines are always computed and cannot be edited directly. Only invoices in draft status can be updated. |
433-
| `client.internal.invoices.delete` | `DELETE /openmeter/billing/invoices/{invoiceId}` | Delete a billing invoice. Only standard invoices in draft status can be deleted. Deleting an invoice will also delete all associated line items and workflow configuration. |
428+
| Method | HTTP | Description |
429+
| --------------------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
430+
| `client.internal.invoices.list` | `GET /openmeter/billing/invoices` | List billing invoices. Returns a page of invoices. Gathering invoices are never included. Use `filter` to narrow by status, customer, dates, or service period start. Use `sort` to control ordering. |
431+
| `client.internal.invoices.get` | `GET /openmeter/billing/invoices/{invoiceId}` | Get a billing invoice by ID. Returns the full invoice resource including line items, status details, totals, and workflow configuration snapshot. |
432+
| `client.internal.invoices.update` | `PUT /openmeter/billing/invoices/{invoiceId}` | Update a billing invoice. Only the mutable fields of the invoice can be edited: description, labels, supplier, customer, workflow settings, and top-level lines. Top-level lines are matched by `id`; lines without an `id` are created, and existing lines omitted from `lines` are deleted. Detailed (child) lines are always computed and cannot be edited directly. Only invoices in draft status can be updated. |
433+
| `client.internal.invoices.delete` | `DELETE /openmeter/billing/invoices/{invoiceId}` | Delete a billing invoice. Only standard invoices in draft status can be deleted. Deleting an invoice will also delete all associated line items and workflow configuration. |
434+
| `client.internal.invoices.advance` | `POST /openmeter/billing/invoices/{invoiceId}/advance` | Advance a billing invoice. Advances the invoice to the next workflow state. The next state is determined by the invoice's current status and workflow configuration. Only invoices in draft or issued status can be advanced. |
435+
| `client.internal.invoices.approve` | `POST /openmeter/billing/invoices/{invoiceId}/approve` | Approve a billing invoice. This call instantly sends the invoice to the customer using the configured billing profile app. This call is valid in two invoice statuses: - draft: the invoice will be sent to the customer, the invoice state becomes issued - manual_approval_needed: the invoice will be sent to the customer, the invoice state becomes issued |
436+
| `client.internal.invoices.retry` | `POST /openmeter/billing/invoices/{invoiceId}/retry` | Retry sending a billing invoice. Retry advancing the invoice after a failed attempt. The action can be called when the invoice's statusDetails' actions field contain the "retry" action. |
437+
| `client.internal.invoices.snapshotQuantities` | `POST /openmeter/billing/invoices/{invoiceId}/snapshot-quantities` | Snapshot quantities for usage-based line items. This call will snapshot the quantities for all usage based line items in the invoice. This call is only valid in draft.waiting_for_collection status, where the collection period can be skipped using this action. |
434438

435439
### Internal Currencies
436440

api/spec/packages/aip-client-javascript/src/funcs/invoices.ts

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ import type {
1515
UpdateInvoiceResponse,
1616
DeleteInvoiceRequest,
1717
DeleteInvoiceResponse,
18+
AdvanceInvoiceRequest,
19+
AdvanceInvoiceResponse,
20+
ApproveInvoiceRequest,
21+
ApproveInvoiceResponse,
22+
RetryInvoiceRequest,
23+
RetryInvoiceResponse,
24+
SnapshotQuantitiesInvoiceRequest,
25+
SnapshotQuantitiesInvoiceResponse,
1826
} from '../models/operations/invoices.js'
1927

2028
/**
@@ -158,3 +166,152 @@ export function deleteInvoice(
158166
await http(client).delete(path, options)
159167
})
160168
}
169+
170+
/**
171+
* Advance billing invoice's next status
172+
*
173+
* Advance a billing invoice.
174+
*
175+
* Advances the invoice to the next workflow state. The next state is determined by
176+
* the invoice's current status and workflow configuration. Only invoices in draft
177+
* or issued status can be advanced.
178+
*
179+
* POST /openmeter/billing/invoices/{invoiceId}/advance
180+
*/
181+
export function advanceInvoice(
182+
client: Client,
183+
req: AdvanceInvoiceRequest,
184+
options?: RequestOptions,
185+
): Promise<Result<AdvanceInvoiceResponse>> {
186+
return request(() => {
187+
const path = `openmeter/billing/invoices/${(() => {
188+
if (req.invoiceId === undefined) {
189+
throw new Error('missing path parameter: invoiceId')
190+
}
191+
return encodeURIComponent(String(req.invoiceId))
192+
})()}/advance`
193+
return http(client)
194+
.post(path, options)
195+
.json()
196+
.then((data) => {
197+
if (client._options.validate) {
198+
assertValid(schemas.advanceInvoiceResponseWire, data)
199+
}
200+
return fromWire(data, schemas.advanceInvoiceResponse)
201+
})
202+
})
203+
}
204+
205+
/**
206+
* Send the invoice to the customer
207+
*
208+
* Approve a billing invoice.
209+
*
210+
* This call instantly sends the invoice to the customer using the configured
211+
* billing profile app.
212+
*
213+
* This call is valid in two invoice statuses:
214+
*
215+
* - draft: the invoice will be sent to the customer, the invoice state becomes
216+
* issued
217+
* - manual_approval_needed: the invoice will be sent to the customer, the invoice
218+
* state becomes issued
219+
*
220+
* POST /openmeter/billing/invoices/{invoiceId}/approve
221+
*/
222+
export function approveInvoice(
223+
client: Client,
224+
req: ApproveInvoiceRequest,
225+
options?: RequestOptions,
226+
): Promise<Result<ApproveInvoiceResponse>> {
227+
return request(() => {
228+
const path = `openmeter/billing/invoices/${(() => {
229+
if (req.invoiceId === undefined) {
230+
throw new Error('missing path parameter: invoiceId')
231+
}
232+
return encodeURIComponent(String(req.invoiceId))
233+
})()}/approve`
234+
return http(client)
235+
.post(path, options)
236+
.json()
237+
.then((data) => {
238+
if (client._options.validate) {
239+
assertValid(schemas.approveInvoiceResponseWire, data)
240+
}
241+
return fromWire(data, schemas.approveInvoiceResponse)
242+
})
243+
})
244+
}
245+
246+
/**
247+
* Retry advancing the invoice after a failed attempt
248+
*
249+
* Retry sending a billing invoice.
250+
*
251+
* Retry advancing the invoice after a failed attempt.
252+
*
253+
* The action can be called when the invoice's statusDetails' actions field contain
254+
* the "retry" action.
255+
*
256+
* POST /openmeter/billing/invoices/{invoiceId}/retry
257+
*/
258+
export function retryInvoice(
259+
client: Client,
260+
req: RetryInvoiceRequest,
261+
options?: RequestOptions,
262+
): Promise<Result<RetryInvoiceResponse>> {
263+
return request(() => {
264+
const path = `openmeter/billing/invoices/${(() => {
265+
if (req.invoiceId === undefined) {
266+
throw new Error('missing path parameter: invoiceId')
267+
}
268+
return encodeURIComponent(String(req.invoiceId))
269+
})()}/retry`
270+
return http(client)
271+
.post(path, options)
272+
.json()
273+
.then((data) => {
274+
if (client._options.validate) {
275+
assertValid(schemas.retryInvoiceResponseWire, data)
276+
}
277+
return fromWire(data, schemas.retryInvoiceResponse)
278+
})
279+
})
280+
}
281+
282+
/**
283+
* Snapshot quantities for usage based line items
284+
*
285+
* Snapshot quantities for usage-based line items.
286+
*
287+
* This call will snapshot the quantities for all usage based line items in the
288+
* invoice.
289+
*
290+
* This call is only valid in draft.waiting_for_collection status, where the
291+
* collection period can be skipped using this action.
292+
*
293+
* POST /openmeter/billing/invoices/{invoiceId}/snapshot-quantities
294+
*/
295+
export function snapshotQuantitiesInvoice(
296+
client: Client,
297+
req: SnapshotQuantitiesInvoiceRequest,
298+
options?: RequestOptions,
299+
): Promise<Result<SnapshotQuantitiesInvoiceResponse>> {
300+
return request(() => {
301+
const path = `openmeter/billing/invoices/${(() => {
302+
if (req.invoiceId === undefined) {
303+
throw new Error('missing path parameter: invoiceId')
304+
}
305+
return encodeURIComponent(String(req.invoiceId))
306+
})()}/snapshot-quantities`
307+
return http(client)
308+
.post(path, options)
309+
.json()
310+
.then((data) => {
311+
if (client._options.validate) {
312+
assertValid(schemas.snapshotQuantitiesInvoiceResponseWire, data)
313+
}
314+
return fromWire(data, schemas.snapshotQuantitiesInvoiceResponse)
315+
})
316+
})
317+
}

api/spec/packages/aip-client-javascript/src/models/operations/invoices.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,23 @@ export type DeleteInvoiceRequest = {
5555
invoiceId: string
5656
}
5757
export type DeleteInvoiceResponse = void
58+
59+
export type AdvanceInvoiceRequest = {
60+
invoiceId: string
61+
}
62+
export type AdvanceInvoiceResponse = Invoice
63+
64+
export type ApproveInvoiceRequest = {
65+
invoiceId: string
66+
}
67+
export type ApproveInvoiceResponse = Invoice
68+
69+
export type RetryInvoiceRequest = {
70+
invoiceId: string
71+
}
72+
export type RetryInvoiceResponse = Invoice
73+
74+
export type SnapshotQuantitiesInvoiceRequest = {
75+
invoiceId: string
76+
}
77+
export type SnapshotQuantitiesInvoiceResponse = Invoice

api/spec/packages/aip-client-javascript/src/models/schemas.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6149,6 +6149,30 @@ export const deleteInvoicePathParams = z.object({
61496149
invoiceId: ulid,
61506150
})
61516151

6152+
export const advanceInvoicePathParams = z.object({
6153+
invoiceId: ulid,
6154+
})
6155+
6156+
export const advanceInvoiceResponse = invoice
6157+
6158+
export const approveInvoicePathParams = z.object({
6159+
invoiceId: ulid,
6160+
})
6161+
6162+
export const approveInvoiceResponse = invoice
6163+
6164+
export const retryInvoicePathParams = z.object({
6165+
invoiceId: ulid,
6166+
})
6167+
6168+
export const retryInvoiceResponse = invoice
6169+
6170+
export const snapshotQuantitiesInvoicePathParams = z.object({
6171+
invoiceId: ulid,
6172+
})
6173+
6174+
export const snapshotQuantitiesInvoiceResponse = invoice
6175+
61526176
export const createTaxCodeBody = createTaxCodeRequest
61536177

61546178
export const createTaxCodeResponse = taxCode
@@ -12711,6 +12735,30 @@ export const deleteInvoicePathParamsWire = z.object({
1271112735
invoiceId: ulidWire,
1271212736
})
1271312737

12738+
export const advanceInvoicePathParamsWire = z.object({
12739+
invoiceId: ulidWire,
12740+
})
12741+
12742+
export const advanceInvoiceResponseWire = invoiceWire
12743+
12744+
export const approveInvoicePathParamsWire = z.object({
12745+
invoiceId: ulidWire,
12746+
})
12747+
12748+
export const approveInvoiceResponseWire = invoiceWire
12749+
12750+
export const retryInvoicePathParamsWire = z.object({
12751+
invoiceId: ulidWire,
12752+
})
12753+
12754+
export const retryInvoiceResponseWire = invoiceWire
12755+
12756+
export const snapshotQuantitiesInvoicePathParamsWire = z.object({
12757+
invoiceId: ulidWire,
12758+
})
12759+
12760+
export const snapshotQuantitiesInvoiceResponseWire = invoiceWire
12761+
1271412762
export const createTaxCodeBodyWire = createTaxCodeRequestWire
1271512763

1271612764
export const createTaxCodeResponseWire = taxCodeWire

api/spec/packages/aip-client-javascript/src/sdk/internal.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import {
99
getInvoice,
1010
updateInvoice,
1111
deleteInvoice,
12+
advanceInvoice,
13+
approveInvoice,
14+
retryInvoice,
15+
snapshotQuantitiesInvoice,
1216
} from '../funcs/invoices.js'
1317
import {
1418
listCurrencies,
@@ -30,6 +34,14 @@ import type {
3034
UpdateInvoiceResponse,
3135
DeleteInvoiceRequest,
3236
DeleteInvoiceResponse,
37+
AdvanceInvoiceRequest,
38+
AdvanceInvoiceResponse,
39+
ApproveInvoiceRequest,
40+
ApproveInvoiceResponse,
41+
RetryInvoiceRequest,
42+
RetryInvoiceResponse,
43+
SnapshotQuantitiesInvoiceRequest,
44+
SnapshotQuantitiesInvoiceResponse,
3345
} from '../models/operations/invoices.js'
3446
import type {
3547
ListCurrenciesRequest,
@@ -192,6 +204,89 @@ export class InternalInvoices {
192204
): Promise<DeleteInvoiceResponse> {
193205
return unwrap(await deleteInvoice(this._client, request, options))
194206
}
207+
208+
/**
209+
* Advance billing invoice's next status
210+
*
211+
* Advance a billing invoice.
212+
*
213+
* Advances the invoice to the next workflow state. The next state is determined by
214+
* the invoice's current status and workflow configuration. Only invoices in draft
215+
* or issued status can be advanced.
216+
*
217+
* POST /openmeter/billing/invoices/{invoiceId}/advance
218+
*/
219+
async advance(
220+
request: AdvanceInvoiceRequest,
221+
options?: RequestOptions,
222+
): Promise<AdvanceInvoiceResponse> {
223+
return unwrap(await advanceInvoice(this._client, request, options))
224+
}
225+
226+
/**
227+
* Send the invoice to the customer
228+
*
229+
* Approve a billing invoice.
230+
*
231+
* This call instantly sends the invoice to the customer using the configured
232+
* billing profile app.
233+
*
234+
* This call is valid in two invoice statuses:
235+
*
236+
* - draft: the invoice will be sent to the customer, the invoice state becomes
237+
* issued
238+
* - manual_approval_needed: the invoice will be sent to the customer, the invoice
239+
* state becomes issued
240+
*
241+
* POST /openmeter/billing/invoices/{invoiceId}/approve
242+
*/
243+
async approve(
244+
request: ApproveInvoiceRequest,
245+
options?: RequestOptions,
246+
): Promise<ApproveInvoiceResponse> {
247+
return unwrap(await approveInvoice(this._client, request, options))
248+
}
249+
250+
/**
251+
* Retry advancing the invoice after a failed attempt
252+
*
253+
* Retry sending a billing invoice.
254+
*
255+
* Retry advancing the invoice after a failed attempt.
256+
*
257+
* The action can be called when the invoice's statusDetails' actions field contain
258+
* the "retry" action.
259+
*
260+
* POST /openmeter/billing/invoices/{invoiceId}/retry
261+
*/
262+
async retry(
263+
request: RetryInvoiceRequest,
264+
options?: RequestOptions,
265+
): Promise<RetryInvoiceResponse> {
266+
return unwrap(await retryInvoice(this._client, request, options))
267+
}
268+
269+
/**
270+
* Snapshot quantities for usage based line items
271+
*
272+
* Snapshot quantities for usage-based line items.
273+
*
274+
* This call will snapshot the quantities for all usage based line items in the
275+
* invoice.
276+
*
277+
* This call is only valid in draft.waiting_for_collection status, where the
278+
* collection period can be skipped using this action.
279+
*
280+
* POST /openmeter/billing/invoices/{invoiceId}/snapshot-quantities
281+
*/
282+
async snapshotQuantities(
283+
request: SnapshotQuantitiesInvoiceRequest,
284+
options?: RequestOptions,
285+
): Promise<SnapshotQuantitiesInvoiceResponse> {
286+
return unwrap(
287+
await snapshotQuantitiesInvoice(this._client, request, options),
288+
)
289+
}
195290
}
196291

197292
export class InternalCurrencies {

0 commit comments

Comments
 (0)