diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 5153ca9..97e4d74 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "1.49.0"
+ ".": "1.50.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index 8f4293e..df8db45 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 118
+configured_endpoints: 126
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/orb%2Forb-a5a28a58483355d3cc3da7ac5c452d548ee17183324318198052968121ca7dba.yml
openapi_spec_hash: a317931a99e6d4a122919135a0363e40
-config_hash: 05c94c0e6dbeab2c9b554c2e0d6371a0
+config_hash: bcf82bddb691f6be773ac6cae8c03b9a
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e47afe0..16d9c9c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 1.50.0 (2026-01-08)
+
+Full Changelog: [v1.49.0...v1.50.0](https://github.com/orbcorp/orb-go/compare/v1.49.0...v1.50.0)
+
+### Features
+
+* **api:** manual updates ([619d599](https://github.com/orbcorp/orb-go/commit/619d5991d058fbad50a8db80355a0015965d25ce))
+
## 1.49.0 (2026-01-06)
Full Changelog: [v1.48.0...v1.49.0](https://github.com/orbcorp/orb-go/compare/v1.48.0...v1.49.0)
diff --git a/README.md b/README.md
index 45260ae..9c3aa4a 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/orbcorp/orb-go@v1.49.0'
+go get -u 'github.com/orbcorp/orb-go@v1.50.0'
```
diff --git a/api.md b/api.md
index dcbb2b3..3c24a59 100644
--- a/api.md
+++ b/api.md
@@ -381,15 +381,18 @@ Methods:
Response Types:
- orb.InvoiceFetchUpcomingResponse
+- orb.InvoiceListSummaryResponse
Methods:
- client.Invoices.New(ctx context.Context, body orb.InvoiceNewParams) (shared.Invoice, error)
- client.Invoices.Update(ctx context.Context, invoiceID string, body orb.InvoiceUpdateParams) (shared.Invoice, error)
- client.Invoices.List(ctx context.Context, query orb.InvoiceListParams) (pagination.Page[shared.Invoice], error)
+- client.Invoices.DeleteLineItem(ctx context.Context, invoiceID string, lineItemID string) error
- client.Invoices.Fetch(ctx context.Context, invoiceID string) (shared.Invoice, error)
- client.Invoices.FetchUpcoming(ctx context.Context, query orb.InvoiceFetchUpcomingParams) (orb.InvoiceFetchUpcomingResponse, error)
- client.Invoices.Issue(ctx context.Context, invoiceID string, body orb.InvoiceIssueParams) (shared.Invoice, error)
+- client.Invoices.ListSummary(ctx context.Context, query orb.InvoiceListSummaryParams) (pagination.Page[orb.InvoiceListSummaryResponse], error)
- client.Invoices.MarkPaid(ctx context.Context, invoiceID string, body orb.InvoiceMarkPaidParams) (shared.Invoice, error)
- client.Invoices.Pay(ctx context.Context, invoiceID string) (shared.Invoice, error)
- client.Invoices.Void(ctx context.Context, invoiceID string) (shared.Invoice, error)
@@ -441,6 +444,20 @@ Methods:
- client.Plans.ExternalPlanID.Update(ctx context.Context, otherExternalPlanID string, body orb.PlanExternalPlanIDUpdateParams) (orb.Plan, error)
- client.Plans.ExternalPlanID.Fetch(ctx context.Context, externalPlanID string) (orb.Plan, error)
+## Migrations
+
+Response Types:
+
+- orb.PlanMigrationGetResponse
+- orb.PlanMigrationListResponse
+- orb.PlanMigrationCancelResponse
+
+Methods:
+
+- client.Plans.Migrations.Get(ctx context.Context, planID string, migrationID string) (orb.PlanMigrationGetResponse, error)
+- client.Plans.Migrations.List(ctx context.Context, planID string, query orb.PlanMigrationListParams) (pagination.Page[orb.PlanMigrationListResponse], error)
+- client.Plans.Migrations.Cancel(ctx context.Context, planID string, migrationID string) (orb.PlanMigrationCancelResponse, error)
+
# Prices
Response Types:
@@ -581,11 +598,24 @@ Response Types:
- orb.MutatedSubscription
- orb.SubscriptionChangeGetResponse
+- orb.SubscriptionChangeListResponse
- orb.SubscriptionChangeApplyResponse
- orb.SubscriptionChangeCancelResponse
Methods:
- client.SubscriptionChanges.Get(ctx context.Context, subscriptionChangeID string) (orb.SubscriptionChangeGetResponse, error)
+- client.SubscriptionChanges.List(ctx context.Context, query orb.SubscriptionChangeListParams) (pagination.Page[orb.SubscriptionChangeListResponse], error)
- client.SubscriptionChanges.Apply(ctx context.Context, subscriptionChangeID string, body orb.SubscriptionChangeApplyParams) (orb.SubscriptionChangeApplyResponse, error)
- client.SubscriptionChanges.Cancel(ctx context.Context, subscriptionChangeID string) (orb.SubscriptionChangeCancelResponse, error)
+
+# CreditBlocks
+
+Response Types:
+
+- orb.CreditBlockGetResponse
+
+Methods:
+
+- client.CreditBlocks.Get(ctx context.Context, blockID string) (orb.CreditBlockGetResponse, error)
+- client.CreditBlocks.Delete(ctx context.Context, blockID string) error
diff --git a/client.go b/client.go
index 637dd95..a41e714 100644
--- a/client.go
+++ b/client.go
@@ -35,6 +35,7 @@ type Client struct {
Webhooks *WebhookService
SubscriptionChanges *SubscriptionChangeService
+ CreditBlocks *CreditBlockService
}
// DefaultClientOptions read from the environment (ORB_API_KEY, ORB_WEBHOOK_SECRET,
@@ -79,6 +80,7 @@ func NewClient(opts ...option.RequestOption) (r *Client) {
r.Alerts = NewAlertService(opts...)
r.DimensionalPriceGroups = NewDimensionalPriceGroupService(opts...)
r.SubscriptionChanges = NewSubscriptionChangeService(opts...)
+ r.CreditBlocks = NewCreditBlockService(opts...)
return
}
diff --git a/creditblock.go b/creditblock.go
new file mode 100644
index 0000000..3b7cf95
--- /dev/null
+++ b/creditblock.go
@@ -0,0 +1,188 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package orb
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "slices"
+ "time"
+
+ "github.com/orbcorp/orb-go/internal/apijson"
+ "github.com/orbcorp/orb-go/internal/requestconfig"
+ "github.com/orbcorp/orb-go/option"
+)
+
+// CreditBlockService contains methods and other services that help with
+// interacting with the orb API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewCreditBlockService] method instead.
+type CreditBlockService struct {
+ Options []option.RequestOption
+}
+
+// NewCreditBlockService generates a new service that applies the given options to
+// each request. These options are applied after the parent client's options (if
+// there is one), and before any request-specific options.
+func NewCreditBlockService(opts ...option.RequestOption) (r *CreditBlockService) {
+ r = &CreditBlockService{}
+ r.Options = opts
+ return
+}
+
+// This endpoint returns a credit block identified by its block_id.
+func (r *CreditBlockService) Get(ctx context.Context, blockID string, opts ...option.RequestOption) (res *CreditBlockGetResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if blockID == "" {
+ err = errors.New("missing required block_id parameter")
+ return
+ }
+ path := fmt.Sprintf("credit_blocks/%s", blockID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// This endpoint deletes a credit block by its ID.
+//
+// When a credit block is deleted:
+//
+// - The block is removed from the customer's credit ledger.
+// - Any usage of the credit block is reversed, and the ledger is replayed as if
+// the block never existed.
+// - If invoices were generated from the purchase of the credit block, they will be
+// deleted if in draft status, voided if issued, or a credit note will be issued
+// if the invoice is paid.
+//
+//
+// Issued invoices that had credits applied from this block will not be regenerated, but the ledger will
+// reflect the state as if credits from the deleted block were never applied.
+//
+func (r *CreditBlockService) Delete(ctx context.Context, blockID string, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
+ if blockID == "" {
+ err = errors.New("missing required block_id parameter")
+ return
+ }
+ path := fmt.Sprintf("credit_blocks/%s", blockID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
+ return
+}
+
+// The Credit Block resource models prepaid credits within Orb.
+type CreditBlockGetResponse struct {
+ ID string `json:"id,required"`
+ Balance float64 `json:"balance,required"`
+ EffectiveDate time.Time `json:"effective_date,required,nullable" format:"date-time"`
+ ExpiryDate time.Time `json:"expiry_date,required,nullable" format:"date-time"`
+ Filters []CreditBlockGetResponseFilter `json:"filters,required"`
+ MaximumInitialBalance float64 `json:"maximum_initial_balance,required,nullable"`
+ PerUnitCostBasis string `json:"per_unit_cost_basis,required,nullable"`
+ Status CreditBlockGetResponseStatus `json:"status,required"`
+ JSON creditBlockGetResponseJSON `json:"-"`
+}
+
+// creditBlockGetResponseJSON contains the JSON metadata for the struct
+// [CreditBlockGetResponse]
+type creditBlockGetResponseJSON struct {
+ ID apijson.Field
+ Balance apijson.Field
+ EffectiveDate apijson.Field
+ ExpiryDate apijson.Field
+ Filters apijson.Field
+ MaximumInitialBalance apijson.Field
+ PerUnitCostBasis apijson.Field
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *CreditBlockGetResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r creditBlockGetResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type CreditBlockGetResponseFilter struct {
+ // The property of the price to filter on.
+ Field CreditBlockGetResponseFiltersField `json:"field,required"`
+ // Should prices that match the filter be included or excluded.
+ Operator CreditBlockGetResponseFiltersOperator `json:"operator,required"`
+ // The IDs or values that match this filter.
+ Values []string `json:"values,required"`
+ JSON creditBlockGetResponseFilterJSON `json:"-"`
+}
+
+// creditBlockGetResponseFilterJSON contains the JSON metadata for the struct
+// [CreditBlockGetResponseFilter]
+type creditBlockGetResponseFilterJSON struct {
+ Field apijson.Field
+ Operator apijson.Field
+ Values apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *CreditBlockGetResponseFilter) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r creditBlockGetResponseFilterJSON) RawJSON() string {
+ return r.raw
+}
+
+// The property of the price to filter on.
+type CreditBlockGetResponseFiltersField string
+
+const (
+ CreditBlockGetResponseFiltersFieldPriceID CreditBlockGetResponseFiltersField = "price_id"
+ CreditBlockGetResponseFiltersFieldItemID CreditBlockGetResponseFiltersField = "item_id"
+ CreditBlockGetResponseFiltersFieldPriceType CreditBlockGetResponseFiltersField = "price_type"
+ CreditBlockGetResponseFiltersFieldCurrency CreditBlockGetResponseFiltersField = "currency"
+ CreditBlockGetResponseFiltersFieldPricingUnitID CreditBlockGetResponseFiltersField = "pricing_unit_id"
+)
+
+func (r CreditBlockGetResponseFiltersField) IsKnown() bool {
+ switch r {
+ case CreditBlockGetResponseFiltersFieldPriceID, CreditBlockGetResponseFiltersFieldItemID, CreditBlockGetResponseFiltersFieldPriceType, CreditBlockGetResponseFiltersFieldCurrency, CreditBlockGetResponseFiltersFieldPricingUnitID:
+ return true
+ }
+ return false
+}
+
+// Should prices that match the filter be included or excluded.
+type CreditBlockGetResponseFiltersOperator string
+
+const (
+ CreditBlockGetResponseFiltersOperatorIncludes CreditBlockGetResponseFiltersOperator = "includes"
+ CreditBlockGetResponseFiltersOperatorExcludes CreditBlockGetResponseFiltersOperator = "excludes"
+)
+
+func (r CreditBlockGetResponseFiltersOperator) IsKnown() bool {
+ switch r {
+ case CreditBlockGetResponseFiltersOperatorIncludes, CreditBlockGetResponseFiltersOperatorExcludes:
+ return true
+ }
+ return false
+}
+
+type CreditBlockGetResponseStatus string
+
+const (
+ CreditBlockGetResponseStatusActive CreditBlockGetResponseStatus = "active"
+ CreditBlockGetResponseStatusPendingPayment CreditBlockGetResponseStatus = "pending_payment"
+)
+
+func (r CreditBlockGetResponseStatus) IsKnown() bool {
+ switch r {
+ case CreditBlockGetResponseStatusActive, CreditBlockGetResponseStatusPendingPayment:
+ return true
+ }
+ return false
+}
diff --git a/creditblock_test.go b/creditblock_test.go
new file mode 100644
index 0000000..adc7574
--- /dev/null
+++ b/creditblock_test.go
@@ -0,0 +1,58 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package orb_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/orbcorp/orb-go"
+ "github.com/orbcorp/orb-go/internal/testutil"
+ "github.com/orbcorp/orb-go/option"
+)
+
+func TestCreditBlockGet(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.CreditBlocks.Get(context.TODO(), "block_id")
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestCreditBlockDelete(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ err := client.CreditBlocks.Delete(context.TODO(), "block_id")
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/internal/version.go b/internal/version.go
index f335c92..00a06b7 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "1.49.0" // x-release-please-version
+const PackageVersion = "1.50.0" // x-release-please-version
diff --git a/invoice.go b/invoice.go
index d5d8e4d..bf67220 100644
--- a/invoice.go
+++ b/invoice.go
@@ -114,6 +114,27 @@ func (r *InvoiceService) ListAutoPaging(ctx context.Context, query InvoiceListPa
return pagination.NewPageAutoPager(r.List(ctx, query, opts...))
}
+// This endpoint deletes an invoice line item from a draft invoice.
+//
+// This endpoint only allows deletion of one-off line items (not subscription-based
+// line items). The invoice must be in a draft status for this operation to
+// succeed.
+func (r *InvoiceService) DeleteLineItem(ctx context.Context, invoiceID string, lineItemID string, opts ...option.RequestOption) (err error) {
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...)
+ if invoiceID == "" {
+ err = errors.New("missing required invoice_id parameter")
+ return
+ }
+ if lineItemID == "" {
+ err = errors.New("missing required line_item_id parameter")
+ return
+ }
+ path := fmt.Sprintf("invoices/%s/invoice_line_items/%s", invoiceID, lineItemID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...)
+ return
+}
+
// This endpoint is used to fetch an [`Invoice`](/core-concepts#invoice) given an
// identifier.
func (r *InvoiceService) Fetch(ctx context.Context, invoiceID string, opts ...option.RequestOption) (res *shared.Invoice, err error) {
@@ -154,6 +175,59 @@ func (r *InvoiceService) Issue(ctx context.Context, invoiceID string, body Invoi
return
}
+// This is a lighter-weight endpoint that returns a list of all
+// [`Invoice`](/core-concepts#invoice) summaries for an account in a list format.
+//
+// These invoice summaries do not include line item details, minimums, maximums,
+// and discounts, making this endpoint more efficient.
+//
+// The list of invoices is ordered starting from the most recently issued invoice
+// date. The response also includes
+// [`pagination_metadata`](/api-reference/pagination), which lets the caller
+// retrieve the next page of results if they exist.
+//
+// By default, this only returns invoices that are `issued`, `paid`, or `synced`.
+//
+// When fetching any `draft` invoices, this returns the last-computed invoice
+// values for each draft invoice, which may not always be up-to-date since Orb
+// regularly refreshes invoices asynchronously.
+func (r *InvoiceService) ListSummary(ctx context.Context, query InvoiceListSummaryParams, opts ...option.RequestOption) (res *pagination.Page[InvoiceListSummaryResponse], err error) {
+ var raw *http.Response
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+ path := "invoices/summary"
+ cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
+ if err != nil {
+ return nil, err
+ }
+ err = cfg.Execute()
+ if err != nil {
+ return nil, err
+ }
+ res.SetPageConfig(cfg, raw)
+ return res, nil
+}
+
+// This is a lighter-weight endpoint that returns a list of all
+// [`Invoice`](/core-concepts#invoice) summaries for an account in a list format.
+//
+// These invoice summaries do not include line item details, minimums, maximums,
+// and discounts, making this endpoint more efficient.
+//
+// The list of invoices is ordered starting from the most recently issued invoice
+// date. The response also includes
+// [`pagination_metadata`](/api-reference/pagination), which lets the caller
+// retrieve the next page of results if they exist.
+//
+// By default, this only returns invoices that are `issued`, `paid`, or `synced`.
+//
+// When fetching any `draft` invoices, this returns the last-computed invoice
+// values for each draft invoice, which may not always be up-to-date since Orb
+// regularly refreshes invoices asynchronously.
+func (r *InvoiceService) ListSummaryAutoPaging(ctx context.Context, query InvoiceListSummaryParams, opts ...option.RequestOption) *pagination.PageAutoPager[InvoiceListSummaryResponse] {
+ return pagination.NewPageAutoPager(r.ListSummary(ctx, query, opts...))
+}
+
// This endpoint allows an invoice's status to be set to the `paid` status. This
// can only be done to invoices that are in the `issued` or `synced` status.
func (r *InvoiceService) MarkPaid(ctx context.Context, invoiceID string, body InvoiceMarkPaidParams, opts ...option.RequestOption) (res *shared.Invoice, err error) {
@@ -1078,197 +1152,791 @@ func (r InvoiceFetchUpcomingResponseStatus) IsKnown() bool {
return false
}
-type InvoiceNewParams struct {
- // An ISO 4217 currency string. Must be the same as the customer's currency if it
- // is set.
- Currency param.Field[string] `json:"currency,required"`
- // Optional invoice date to set. Must be in the past, if not set, `invoice_date` is
- // set to the current time in the customer's timezone.
- InvoiceDate param.Field[time.Time] `json:"invoice_date,required" format:"date-time"`
- LineItems param.Field[[]InvoiceNewParamsLineItem] `json:"line_items,required"`
- // The id of the `Customer` to create this invoice for. One of `customer_id` and
- // `external_customer_id` are required.
- CustomerID param.Field[string] `json:"customer_id"`
- // An optional discount to attach to the invoice.
- Discount param.Field[shared.DiscountUnionParam] `json:"discount"`
- // An optional custom due date for the invoice. If not set, the due date will be
- // calculated based on the `net_terms` value.
- DueDate param.Field[time.Time] `json:"due_date" format:"date-time"`
- // The `external_customer_id` of the `Customer` to create this invoice for. One of
- // `customer_id` and `external_customer_id` are required.
- ExternalCustomerID param.Field[string] `json:"external_customer_id"`
- // An optional memo to attach to the invoice. If no memo is provided, we will
- // attach the default memo
- Memo param.Field[string] `json:"memo"`
- // User-specified key/value pairs for the resource. Individual keys can be removed
- // by setting the value to `null`, and the entire metadata mapping can be cleared
- // by setting `metadata` to `null`.
- Metadata param.Field[map[string]string] `json:"metadata"`
- // The net terms determines the due date of the invoice. Due date is calculated
- // based on the invoice or issuance date, depending on the account's configured due
- // date calculation method. A value of '0' here represents that the invoice is due
- // on issue, whereas a value of '30' represents that the customer has 30 days to
- // pay the invoice. Do not set this field if you want to set a custom due date.
- NetTerms param.Field[int64] `json:"net_terms"`
- // When true, this invoice will be submitted for issuance upon creation. When
- // false, the resulting invoice will require manual review to issue. Defaulted to
- // false.
- WillAutoIssue param.Field[bool] `json:"will_auto_issue"`
-}
-
-func (r InvoiceNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-type InvoiceNewParamsLineItem struct {
- // A date string to specify the line item's end date in the customer's timezone.
- EndDate param.Field[time.Time] `json:"end_date,required" format:"date"`
- ItemID param.Field[string] `json:"item_id,required"`
- ModelType param.Field[InvoiceNewParamsLineItemsModelType] `json:"model_type,required"`
- // The name of the line item.
- Name param.Field[string] `json:"name,required"`
- // The number of units on the line item
- Quantity param.Field[float64] `json:"quantity,required"`
- // A date string to specify the line item's start date in the customer's timezone.
- StartDate param.Field[time.Time] `json:"start_date,required" format:"date"`
- // Configuration for unit pricing
- UnitConfig param.Field[shared.UnitConfigParam] `json:"unit_config,required"`
-}
-
-func (r InvoiceNewParamsLineItem) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-type InvoiceNewParamsLineItemsModelType string
-
-const (
- InvoiceNewParamsLineItemsModelTypeUnit InvoiceNewParamsLineItemsModelType = "unit"
-)
-
-func (r InvoiceNewParamsLineItemsModelType) IsKnown() bool {
- switch r {
- case InvoiceNewParamsLineItemsModelTypeUnit:
- return true
- }
- return false
-}
-
-type InvoiceUpdateParams struct {
- // An optional custom due date for the invoice. If not set, the due date will be
- // calculated based on the `net_terms` value.
- DueDate param.Field[time.Time] `json:"due_date" format:"date-time"`
- // The date of the invoice. Can only be modified for one-off draft invoices.
- InvoiceDate param.Field[time.Time] `json:"invoice_date" format:"date-time"`
- // User-specified key/value pairs for the resource. Individual keys can be removed
- // by setting the value to `null`, and the entire metadata mapping can be cleared
- // by setting `metadata` to `null`.
- Metadata param.Field[map[string]string] `json:"metadata"`
- // The net terms determines the due date of the invoice. Due date is calculated
- // based on the invoice or issuance date, depending on the account's configured due
- // date calculation method. A value of '0' here represents that the invoice is due
- // on issue, whereas a value of '30' represents that the customer has 30 days to
- // pay the invoice. Do not set this field if you want to set a custom due date.
- NetTerms param.Field[int64] `json:"net_terms"`
-}
-
-func (r InvoiceUpdateParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-type InvoiceListParams struct {
- Amount param.Field[string] `query:"amount"`
- AmountGt param.Field[string] `query:"amount[gt]"`
- AmountLt param.Field[string] `query:"amount[lt]"`
- // Cursor for pagination. This can be populated by the `next_cursor` value returned
- // from the initial request.
- Cursor param.Field[string] `query:"cursor"`
- CustomerID param.Field[string] `query:"customer_id"`
- DateType param.Field[InvoiceListParamsDateType] `query:"date_type"`
- DueDate param.Field[time.Time] `query:"due_date" format:"date"`
- // Filters invoices by their due dates within a specific time range in the past.
- // Specify the range as a number followed by 'd' (days) or 'm' (months). For
- // example, '7d' filters invoices due in the last 7 days, and '2m' filters those
- // due in the last 2 months.
- DueDateWindow param.Field[string] `query:"due_date_window"`
- DueDateGt param.Field[time.Time] `query:"due_date[gt]" format:"date"`
- DueDateLt param.Field[time.Time] `query:"due_date[lt]" format:"date"`
- ExternalCustomerID param.Field[string] `query:"external_customer_id"`
- InvoiceDateGt param.Field[time.Time] `query:"invoice_date[gt]" format:"date-time"`
- InvoiceDateGte param.Field[time.Time] `query:"invoice_date[gte]" format:"date-time"`
- InvoiceDateLt param.Field[time.Time] `query:"invoice_date[lt]" format:"date-time"`
- InvoiceDateLte param.Field[time.Time] `query:"invoice_date[lte]" format:"date-time"`
- IsRecurring param.Field[bool] `query:"is_recurring"`
- // The number of items to fetch. Defaults to 20.
- Limit param.Field[int64] `query:"limit"`
- Status param.Field[[]InvoiceListParamsStatus] `query:"status"`
- SubscriptionID param.Field[string] `query:"subscription_id"`
-}
-
-// URLQuery serializes [InvoiceListParams]'s query parameters as `url.Values`.
-func (r InvoiceListParams) URLQuery() (v url.Values) {
- return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
- ArrayFormat: apiquery.ArrayQueryFormatBrackets,
- NestedFormat: apiquery.NestedQueryFormatBrackets,
- })
-}
-
-type InvoiceListParamsDateType string
-
-const (
- InvoiceListParamsDateTypeDueDate InvoiceListParamsDateType = "due_date"
- InvoiceListParamsDateTypeInvoiceDate InvoiceListParamsDateType = "invoice_date"
-)
-
-func (r InvoiceListParamsDateType) IsKnown() bool {
- switch r {
- case InvoiceListParamsDateTypeDueDate, InvoiceListParamsDateTypeInvoiceDate:
- return true
- }
- return false
-}
-
-type InvoiceListParamsStatus string
-
-const (
- InvoiceListParamsStatusDraft InvoiceListParamsStatus = "draft"
- InvoiceListParamsStatusIssued InvoiceListParamsStatus = "issued"
- InvoiceListParamsStatusPaid InvoiceListParamsStatus = "paid"
- InvoiceListParamsStatusSynced InvoiceListParamsStatus = "synced"
- InvoiceListParamsStatusVoid InvoiceListParamsStatus = "void"
-)
-
-func (r InvoiceListParamsStatus) IsKnown() bool {
- switch r {
- case InvoiceListParamsStatusDraft, InvoiceListParamsStatusIssued, InvoiceListParamsStatusPaid, InvoiceListParamsStatusSynced, InvoiceListParamsStatusVoid:
- return true
- }
- return false
-}
-
-type InvoiceFetchUpcomingParams struct {
- SubscriptionID param.Field[string] `query:"subscription_id,required"`
-}
-
-// URLQuery serializes [InvoiceFetchUpcomingParams]'s query parameters as
-// `url.Values`.
-func (r InvoiceFetchUpcomingParams) URLQuery() (v url.Values) {
- return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
- ArrayFormat: apiquery.ArrayQueryFormatBrackets,
- NestedFormat: apiquery.NestedQueryFormatBrackets,
- })
-}
-
-type InvoiceIssueParams struct {
- // If true, the invoice will be issued synchronously. If false, the invoice will be
- // issued asynchronously. The synchronous option is only available for invoices
- // that have no usage fees. If the invoice is configured to sync to an external
- // provider, a successful response from this endpoint guarantees the invoice is
- // present in the provider.
- Synchronous param.Field[bool] `json:"synchronous"`
-}
-
-func (r InvoiceIssueParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// #InvoiceApiResourceWithoutLineItems
+type InvoiceListSummaryResponse struct {
+ ID string `json:"id,required"`
+ // This is the final amount required to be charged to the customer and reflects the
+ // application of the customer balance to the `total` of the invoice.
+ AmountDue string `json:"amount_due,required"`
+ AutoCollection InvoiceListSummaryResponseAutoCollection `json:"auto_collection,required"`
+ BillingAddress shared.Address `json:"billing_address,required,nullable"`
+ // The creation time of the resource in Orb.
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // A list of credit notes associated with the invoice
+ CreditNotes []InvoiceListSummaryResponseCreditNote `json:"credit_notes,required"`
+ // An ISO 4217 currency string or `credits`
+ Currency string `json:"currency,required"`
+ Customer shared.CustomerMinified `json:"customer,required"`
+ CustomerBalanceTransactions []InvoiceListSummaryResponseCustomerBalanceTransaction `json:"customer_balance_transactions,required"`
+ // Tax IDs are commonly required to be displayed on customer invoices, which are
+ // added to the headers of invoices.
+ //
+ // ### Supported Tax ID Countries and Types
+ //
+ // | Country | Type | Description |
+ // | ---------------------- | ------------ | ------------------------------------------------------------------------------------------------------- |
+ // | Albania | `al_tin` | Albania Tax Identification Number |
+ // | Andorra | `ad_nrt` | Andorran NRT Number |
+ // | Angola | `ao_tin` | Angola Tax Identification Number |
+ // | Argentina | `ar_cuit` | Argentinian Tax ID Number |
+ // | Armenia | `am_tin` | Armenia Tax Identification Number |
+ // | Aruba | `aw_tin` | Aruba Tax Identification Number |
+ // | Australia | `au_abn` | Australian Business Number (AU ABN) |
+ // | Australia | `au_arn` | Australian Taxation Office Reference Number |
+ // | Austria | `eu_vat` | European VAT Number |
+ // | Azerbaijan | `az_tin` | Azerbaijan Tax Identification Number |
+ // | Bahamas | `bs_tin` | Bahamas Tax Identification Number |
+ // | Bahrain | `bh_vat` | Bahraini VAT Number |
+ // | Bangladesh | `bd_bin` | Bangladesh Business Identification Number |
+ // | Barbados | `bb_tin` | Barbados Tax Identification Number |
+ // | Belarus | `by_tin` | Belarus TIN Number |
+ // | Belgium | `eu_vat` | European VAT Number |
+ // | Benin | `bj_ifu` | Benin Tax Identification Number (Identifiant Fiscal Unique) |
+ // | Bolivia | `bo_tin` | Bolivian Tax ID |
+ // | Bosnia and Herzegovina | `ba_tin` | Bosnia and Herzegovina Tax Identification Number |
+ // | Brazil | `br_cnpj` | Brazilian CNPJ Number |
+ // | Brazil | `br_cpf` | Brazilian CPF Number |
+ // | Bulgaria | `bg_uic` | Bulgaria Unified Identification Code |
+ // | Bulgaria | `eu_vat` | European VAT Number |
+ // | Burkina Faso | `bf_ifu` | Burkina Faso Tax Identification Number (Numéro d'Identifiant Fiscal Unique) |
+ // | Cambodia | `kh_tin` | Cambodia Tax Identification Number |
+ // | Cameroon | `cm_niu` | Cameroon Tax Identification Number (Numéro d'Identifiant fiscal Unique) |
+ // | Canada | `ca_bn` | Canadian BN |
+ // | Canada | `ca_gst_hst` | Canadian GST/HST Number |
+ // | Canada | `ca_pst_bc` | Canadian PST Number (British Columbia) |
+ // | Canada | `ca_pst_mb` | Canadian PST Number (Manitoba) |
+ // | Canada | `ca_pst_sk` | Canadian PST Number (Saskatchewan) |
+ // | Canada | `ca_qst` | Canadian QST Number (Québec) |
+ // | Cape Verde | `cv_nif` | Cape Verde Tax Identification Number (Número de Identificação Fiscal) |
+ // | Chile | `cl_tin` | Chilean TIN |
+ // | China | `cn_tin` | Chinese Tax ID |
+ // | Colombia | `co_nit` | Colombian NIT Number |
+ // | Congo-Kinshasa | `cd_nif` | Congo (DR) Tax Identification Number (Número de Identificação Fiscal) |
+ // | Costa Rica | `cr_tin` | Costa Rican Tax ID |
+ // | Croatia | `eu_vat` | European VAT Number |
+ // | Croatia | `hr_oib` | Croatian Personal Identification Number (OIB) |
+ // | Cyprus | `eu_vat` | European VAT Number |
+ // | Czech Republic | `eu_vat` | European VAT Number |
+ // | Denmark | `eu_vat` | European VAT Number |
+ // | Dominican Republic | `do_rcn` | Dominican RCN Number |
+ // | Ecuador | `ec_ruc` | Ecuadorian RUC Number |
+ // | Egypt | `eg_tin` | Egyptian Tax Identification Number |
+ // | El Salvador | `sv_nit` | El Salvadorian NIT Number |
+ // | Estonia | `eu_vat` | European VAT Number |
+ // | Ethiopia | `et_tin` | Ethiopia Tax Identification Number |
+ // | European Union | `eu_oss_vat` | European One Stop Shop VAT Number for non-Union scheme |
+ // | Finland | `eu_vat` | European VAT Number |
+ // | France | `eu_vat` | European VAT Number |
+ // | Georgia | `ge_vat` | Georgian VAT |
+ // | Germany | `de_stn` | German Tax Number (Steuernummer) |
+ // | Germany | `eu_vat` | European VAT Number |
+ // | Greece | `eu_vat` | European VAT Number |
+ // | Guinea | `gn_nif` | Guinea Tax Identification Number (Número de Identificação Fiscal) |
+ // | Hong Kong | `hk_br` | Hong Kong BR Number |
+ // | Hungary | `eu_vat` | European VAT Number |
+ // | Hungary | `hu_tin` | Hungary Tax Number (adószám) |
+ // | Iceland | `is_vat` | Icelandic VAT |
+ // | India | `in_gst` | Indian GST Number |
+ // | Indonesia | `id_npwp` | Indonesian NPWP Number |
+ // | Ireland | `eu_vat` | European VAT Number |
+ // | Israel | `il_vat` | Israel VAT |
+ // | Italy | `eu_vat` | European VAT Number |
+ // | Japan | `jp_cn` | Japanese Corporate Number (_Hōjin Bangō_) |
+ // | Japan | `jp_rn` | Japanese Registered Foreign Businesses' Registration Number (_Tōroku Kokugai Jigyōsha no Tōroku Bangō_) |
+ // | Japan | `jp_trn` | Japanese Tax Registration Number (_Tōroku Bangō_) |
+ // | Kazakhstan | `kz_bin` | Kazakhstani Business Identification Number |
+ // | Kenya | `ke_pin` | Kenya Revenue Authority Personal Identification Number |
+ // | Kyrgyzstan | `kg_tin` | Kyrgyzstan Tax Identification Number |
+ // | Laos | `la_tin` | Laos Tax Identification Number |
+ // | Latvia | `eu_vat` | European VAT Number |
+ // | Liechtenstein | `li_uid` | Liechtensteinian UID Number |
+ // | Liechtenstein | `li_vat` | Liechtenstein VAT Number |
+ // | Lithuania | `eu_vat` | European VAT Number |
+ // | Luxembourg | `eu_vat` | European VAT Number |
+ // | Malaysia | `my_frp` | Malaysian FRP Number |
+ // | Malaysia | `my_itn` | Malaysian ITN |
+ // | Malaysia | `my_sst` | Malaysian SST Number |
+ // | Malta | `eu_vat` | European VAT Number |
+ // | Mauritania | `mr_nif` | Mauritania Tax Identification Number (Número de Identificação Fiscal) |
+ // | Mexico | `mx_rfc` | Mexican RFC Number |
+ // | Moldova | `md_vat` | Moldova VAT Number |
+ // | Montenegro | `me_pib` | Montenegro PIB Number |
+ // | Morocco | `ma_vat` | Morocco VAT Number |
+ // | Nepal | `np_pan` | Nepal PAN Number |
+ // | Netherlands | `eu_vat` | European VAT Number |
+ // | New Zealand | `nz_gst` | New Zealand GST Number |
+ // | Nigeria | `ng_tin` | Nigerian Tax Identification Number |
+ // | North Macedonia | `mk_vat` | North Macedonia VAT Number |
+ // | Northern Ireland | `eu_vat` | Northern Ireland VAT Number |
+ // | Norway | `no_vat` | Norwegian VAT Number |
+ // | Norway | `no_voec` | Norwegian VAT on e-commerce Number |
+ // | Oman | `om_vat` | Omani VAT Number |
+ // | Peru | `pe_ruc` | Peruvian RUC Number |
+ // | Philippines | `ph_tin` | Philippines Tax Identification Number |
+ // | Poland | `eu_vat` | European VAT Number |
+ // | Portugal | `eu_vat` | European VAT Number |
+ // | Romania | `eu_vat` | European VAT Number |
+ // | Romania | `ro_tin` | Romanian Tax ID Number |
+ // | Russia | `ru_inn` | Russian INN |
+ // | Russia | `ru_kpp` | Russian KPP |
+ // | Saudi Arabia | `sa_vat` | Saudi Arabia VAT |
+ // | Senegal | `sn_ninea` | Senegal NINEA Number |
+ // | Serbia | `rs_pib` | Serbian PIB Number |
+ // | Singapore | `sg_gst` | Singaporean GST |
+ // | Singapore | `sg_uen` | Singaporean UEN |
+ // | Slovakia | `eu_vat` | European VAT Number |
+ // | Slovenia | `eu_vat` | European VAT Number |
+ // | Slovenia | `si_tin` | Slovenia Tax Number (davčna številka) |
+ // | South Africa | `za_vat` | South African VAT Number |
+ // | South Korea | `kr_brn` | Korean BRN |
+ // | Spain | `es_cif` | Spanish NIF Number (previously Spanish CIF Number) |
+ // | Spain | `eu_vat` | European VAT Number |
+ // | Suriname | `sr_fin` | Suriname FIN Number |
+ // | Sweden | `eu_vat` | European VAT Number |
+ // | Switzerland | `ch_uid` | Switzerland UID Number |
+ // | Switzerland | `ch_vat` | Switzerland VAT Number |
+ // | Taiwan | `tw_vat` | Taiwanese VAT |
+ // | Tajikistan | `tj_tin` | Tajikistan Tax Identification Number |
+ // | Tanzania | `tz_vat` | Tanzania VAT Number |
+ // | Thailand | `th_vat` | Thai VAT |
+ // | Turkey | `tr_tin` | Turkish Tax Identification Number |
+ // | Uganda | `ug_tin` | Uganda Tax Identification Number |
+ // | Ukraine | `ua_vat` | Ukrainian VAT |
+ // | United Arab Emirates | `ae_trn` | United Arab Emirates TRN |
+ // | United Kingdom | `gb_vat` | United Kingdom VAT Number |
+ // | United States | `us_ein` | United States EIN |
+ // | Uruguay | `uy_ruc` | Uruguayan RUC Number |
+ // | Uzbekistan | `uz_tin` | Uzbekistan TIN Number |
+ // | Uzbekistan | `uz_vat` | Uzbekistan VAT Number |
+ // | Venezuela | `ve_rif` | Venezuelan RIF Number |
+ // | Vietnam | `vn_tin` | Vietnamese Tax ID Number |
+ // | Zambia | `zm_tin` | Zambia Tax Identification Number |
+ // | Zimbabwe | `zw_tin` | Zimbabwe Tax Identification Number |
+ CustomerTaxID shared.CustomerTaxID `json:"customer_tax_id,required,nullable"`
+ // When the invoice payment is due. The due date is null if the invoice is not yet
+ // finalized.
+ DueDate time.Time `json:"due_date,required,nullable" format:"date-time"`
+ // If the invoice has a status of `draft`, this will be the time that the invoice
+ // will be eligible to be issued, otherwise it will be `null`. If `auto-issue` is
+ // true, the invoice will automatically begin issuing at this time.
+ EligibleToIssueAt time.Time `json:"eligible_to_issue_at,required,nullable" format:"date-time"`
+ // A URL for the customer-facing invoice portal. This URL expires 30 days after the
+ // invoice's due date, or 60 days after being re-generated through the UI.
+ HostedInvoiceURL string `json:"hosted_invoice_url,required,nullable"`
+ // The scheduled date of the invoice
+ InvoiceDate time.Time `json:"invoice_date,required" format:"date-time"`
+ // Automatically generated invoice number to help track and reconcile invoices.
+ // Invoice numbers have a prefix such as `RFOBWG`. These can be sequential per
+ // account or customer.
+ InvoiceNumber string `json:"invoice_number,required"`
+ // The link to download the PDF representation of the `Invoice`.
+ InvoicePdf string `json:"invoice_pdf,required,nullable"`
+ InvoiceSource InvoiceListSummaryResponseInvoiceSource `json:"invoice_source,required"`
+ // If the invoice failed to issue, this will be the last time it failed to issue
+ // (even if it is now in a different state.)
+ IssueFailedAt time.Time `json:"issue_failed_at,required,nullable" format:"date-time"`
+ // If the invoice has been issued, this will be the time it transitioned to
+ // `issued` (even if it is now in a different state.)
+ IssuedAt time.Time `json:"issued_at,required,nullable" format:"date-time"`
+ // Free-form text which is available on the invoice PDF and the Orb invoice portal.
+ Memo string `json:"memo,required,nullable"`
+ // User specified key-value pairs for the resource. If not present, this defaults
+ // to an empty dictionary. Individual keys can be removed by setting the value to
+ // `null`, and the entire metadata mapping can be cleared by setting `metadata` to
+ // `null`.
+ Metadata map[string]string `json:"metadata,required"`
+ // If the invoice has a status of `paid`, this gives a timestamp when the invoice
+ // was paid.
+ PaidAt time.Time `json:"paid_at,required,nullable" format:"date-time"`
+ // A list of payment attempts associated with the invoice
+ PaymentAttempts []InvoiceListSummaryResponsePaymentAttempt `json:"payment_attempts,required"`
+ // If payment was attempted on this invoice but failed, this will be the time of
+ // the most recent attempt.
+ PaymentFailedAt time.Time `json:"payment_failed_at,required,nullable" format:"date-time"`
+ // If payment was attempted on this invoice, this will be the start time of the
+ // most recent attempt. This field is especially useful for delayed-notification
+ // payment mechanisms (like bank transfers), where payment can take 3 days or more.
+ PaymentStartedAt time.Time `json:"payment_started_at,required,nullable" format:"date-time"`
+ // If the invoice is in draft, this timestamp will reflect when the invoice is
+ // scheduled to be issued.
+ ScheduledIssueAt time.Time `json:"scheduled_issue_at,required,nullable" format:"date-time"`
+ ShippingAddress shared.Address `json:"shipping_address,required,nullable"`
+ Status InvoiceListSummaryResponseStatus `json:"status,required"`
+ Subscription shared.SubscriptionMinified `json:"subscription,required,nullable"`
+ // If the invoice failed to sync, this will be the last time an external invoicing
+ // provider sync was attempted. This field will always be `null` for invoices using
+ // Orb Invoicing.
+ SyncFailedAt time.Time `json:"sync_failed_at,required,nullable" format:"date-time"`
+ // The total after any minimums and discounts have been applied.
+ Total string `json:"total,required"`
+ // If the invoice has a status of `void`, this gives a timestamp when the invoice
+ // was voided.
+ VoidedAt time.Time `json:"voided_at,required,nullable" format:"date-time"`
+ // This is true if the invoice will be automatically issued in the future, and
+ // false otherwise.
+ WillAutoIssue bool `json:"will_auto_issue,required"`
+ JSON invoiceListSummaryResponseJSON `json:"-"`
+}
+
+// invoiceListSummaryResponseJSON contains the JSON metadata for the struct
+// [InvoiceListSummaryResponse]
+type invoiceListSummaryResponseJSON struct {
+ ID apijson.Field
+ AmountDue apijson.Field
+ AutoCollection apijson.Field
+ BillingAddress apijson.Field
+ CreatedAt apijson.Field
+ CreditNotes apijson.Field
+ Currency apijson.Field
+ Customer apijson.Field
+ CustomerBalanceTransactions apijson.Field
+ CustomerTaxID apijson.Field
+ DueDate apijson.Field
+ EligibleToIssueAt apijson.Field
+ HostedInvoiceURL apijson.Field
+ InvoiceDate apijson.Field
+ InvoiceNumber apijson.Field
+ InvoicePdf apijson.Field
+ InvoiceSource apijson.Field
+ IssueFailedAt apijson.Field
+ IssuedAt apijson.Field
+ Memo apijson.Field
+ Metadata apijson.Field
+ PaidAt apijson.Field
+ PaymentAttempts apijson.Field
+ PaymentFailedAt apijson.Field
+ PaymentStartedAt apijson.Field
+ ScheduledIssueAt apijson.Field
+ ShippingAddress apijson.Field
+ Status apijson.Field
+ Subscription apijson.Field
+ SyncFailedAt apijson.Field
+ Total apijson.Field
+ VoidedAt apijson.Field
+ WillAutoIssue apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *InvoiceListSummaryResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r invoiceListSummaryResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type InvoiceListSummaryResponseAutoCollection struct {
+ // True only if auto-collection is enabled for this invoice.
+ Enabled bool `json:"enabled,required,nullable"`
+ // If the invoice is scheduled for auto-collection, this field will reflect when
+ // the next attempt will occur. If dunning has been exhausted, or auto-collection
+ // is not enabled for this invoice, this field will be `null`.
+ NextAttemptAt time.Time `json:"next_attempt_at,required,nullable" format:"date-time"`
+ // Number of auto-collection payment attempts.
+ NumAttempts int64 `json:"num_attempts,required,nullable"`
+ // If Orb has ever attempted payment auto-collection for this invoice, this field
+ // will reflect when that attempt occurred. In conjunction with `next_attempt_at`,
+ // this can be used to tell whether the invoice is currently in dunning (that is,
+ // `previously_attempted_at` is non-null, and `next_attempt_time` is non-null), or
+ // if dunning has been exhausted (`previously_attempted_at` is non-null, but
+ // `next_attempt_time` is null).
+ PreviouslyAttemptedAt time.Time `json:"previously_attempted_at,required,nullable" format:"date-time"`
+ JSON invoiceListSummaryResponseAutoCollectionJSON `json:"-"`
+}
+
+// invoiceListSummaryResponseAutoCollectionJSON contains the JSON metadata for the
+// struct [InvoiceListSummaryResponseAutoCollection]
+type invoiceListSummaryResponseAutoCollectionJSON struct {
+ Enabled apijson.Field
+ NextAttemptAt apijson.Field
+ NumAttempts apijson.Field
+ PreviouslyAttemptedAt apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *InvoiceListSummaryResponseAutoCollection) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r invoiceListSummaryResponseAutoCollectionJSON) RawJSON() string {
+ return r.raw
+}
+
+type InvoiceListSummaryResponseCreditNote struct {
+ ID string `json:"id,required"`
+ CreditNoteNumber string `json:"credit_note_number,required"`
+ // An optional memo supplied on the credit note.
+ Memo string `json:"memo,required,nullable"`
+ Reason string `json:"reason,required"`
+ Total string `json:"total,required"`
+ Type string `json:"type,required"`
+ // If the credit note has a status of `void`, this gives a timestamp when the
+ // credit note was voided.
+ VoidedAt time.Time `json:"voided_at,required,nullable" format:"date-time"`
+ JSON invoiceListSummaryResponseCreditNoteJSON `json:"-"`
+}
+
+// invoiceListSummaryResponseCreditNoteJSON contains the JSON metadata for the
+// struct [InvoiceListSummaryResponseCreditNote]
+type invoiceListSummaryResponseCreditNoteJSON struct {
+ ID apijson.Field
+ CreditNoteNumber apijson.Field
+ Memo apijson.Field
+ Reason apijson.Field
+ Total apijson.Field
+ Type apijson.Field
+ VoidedAt apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *InvoiceListSummaryResponseCreditNote) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r invoiceListSummaryResponseCreditNoteJSON) RawJSON() string {
+ return r.raw
+}
+
+type InvoiceListSummaryResponseCustomerBalanceTransaction struct {
+ // A unique id for this transaction.
+ ID string `json:"id,required"`
+ Action InvoiceListSummaryResponseCustomerBalanceTransactionsAction `json:"action,required"`
+ // The value of the amount changed in the transaction.
+ Amount string `json:"amount,required"`
+ // The creation time of this transaction.
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ CreditNote shared.CreditNoteTiny `json:"credit_note,required,nullable"`
+ // An optional description provided for manual customer balance adjustments.
+ Description string `json:"description,required,nullable"`
+ // The new value of the customer's balance prior to the transaction, in the
+ // customer's currency.
+ EndingBalance string `json:"ending_balance,required"`
+ Invoice shared.InvoiceTiny `json:"invoice,required,nullable"`
+ // The original value of the customer's balance prior to the transaction, in the
+ // customer's currency.
+ StartingBalance string `json:"starting_balance,required"`
+ Type InvoiceListSummaryResponseCustomerBalanceTransactionsType `json:"type,required"`
+ JSON invoiceListSummaryResponseCustomerBalanceTransactionJSON `json:"-"`
+}
+
+// invoiceListSummaryResponseCustomerBalanceTransactionJSON contains the JSON
+// metadata for the struct [InvoiceListSummaryResponseCustomerBalanceTransaction]
+type invoiceListSummaryResponseCustomerBalanceTransactionJSON struct {
+ ID apijson.Field
+ Action apijson.Field
+ Amount apijson.Field
+ CreatedAt apijson.Field
+ CreditNote apijson.Field
+ Description apijson.Field
+ EndingBalance apijson.Field
+ Invoice apijson.Field
+ StartingBalance apijson.Field
+ Type apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *InvoiceListSummaryResponseCustomerBalanceTransaction) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r invoiceListSummaryResponseCustomerBalanceTransactionJSON) RawJSON() string {
+ return r.raw
+}
+
+type InvoiceListSummaryResponseCustomerBalanceTransactionsAction string
+
+const (
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionAppliedToInvoice InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "applied_to_invoice"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionManualAdjustment InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "manual_adjustment"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionProratedRefund InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "prorated_refund"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionRevertProratedRefund InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "revert_prorated_refund"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionReturnFromVoiding InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "return_from_voiding"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionCreditNoteApplied InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "credit_note_applied"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionCreditNoteVoided InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "credit_note_voided"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionOverpaymentRefund InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "overpayment_refund"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionExternalPayment InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "external_payment"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsActionSmallInvoiceCarryover InvoiceListSummaryResponseCustomerBalanceTransactionsAction = "small_invoice_carryover"
+)
+
+func (r InvoiceListSummaryResponseCustomerBalanceTransactionsAction) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryResponseCustomerBalanceTransactionsActionAppliedToInvoice, InvoiceListSummaryResponseCustomerBalanceTransactionsActionManualAdjustment, InvoiceListSummaryResponseCustomerBalanceTransactionsActionProratedRefund, InvoiceListSummaryResponseCustomerBalanceTransactionsActionRevertProratedRefund, InvoiceListSummaryResponseCustomerBalanceTransactionsActionReturnFromVoiding, InvoiceListSummaryResponseCustomerBalanceTransactionsActionCreditNoteApplied, InvoiceListSummaryResponseCustomerBalanceTransactionsActionCreditNoteVoided, InvoiceListSummaryResponseCustomerBalanceTransactionsActionOverpaymentRefund, InvoiceListSummaryResponseCustomerBalanceTransactionsActionExternalPayment, InvoiceListSummaryResponseCustomerBalanceTransactionsActionSmallInvoiceCarryover:
+ return true
+ }
+ return false
+}
+
+type InvoiceListSummaryResponseCustomerBalanceTransactionsType string
+
+const (
+ InvoiceListSummaryResponseCustomerBalanceTransactionsTypeIncrement InvoiceListSummaryResponseCustomerBalanceTransactionsType = "increment"
+ InvoiceListSummaryResponseCustomerBalanceTransactionsTypeDecrement InvoiceListSummaryResponseCustomerBalanceTransactionsType = "decrement"
+)
+
+func (r InvoiceListSummaryResponseCustomerBalanceTransactionsType) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryResponseCustomerBalanceTransactionsTypeIncrement, InvoiceListSummaryResponseCustomerBalanceTransactionsTypeDecrement:
+ return true
+ }
+ return false
+}
+
+type InvoiceListSummaryResponseInvoiceSource string
+
+const (
+ InvoiceListSummaryResponseInvoiceSourceSubscription InvoiceListSummaryResponseInvoiceSource = "subscription"
+ InvoiceListSummaryResponseInvoiceSourcePartial InvoiceListSummaryResponseInvoiceSource = "partial"
+ InvoiceListSummaryResponseInvoiceSourceOneOff InvoiceListSummaryResponseInvoiceSource = "one_off"
+)
+
+func (r InvoiceListSummaryResponseInvoiceSource) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryResponseInvoiceSourceSubscription, InvoiceListSummaryResponseInvoiceSourcePartial, InvoiceListSummaryResponseInvoiceSourceOneOff:
+ return true
+ }
+ return false
+}
+
+type InvoiceListSummaryResponsePaymentAttempt struct {
+ // The ID of the payment attempt.
+ ID string `json:"id,required"`
+ // The amount of the payment attempt.
+ Amount string `json:"amount,required"`
+ // The time at which the payment attempt was created.
+ CreatedAt time.Time `json:"created_at,required" format:"date-time"`
+ // The payment provider that attempted to collect the payment.
+ PaymentProvider InvoiceListSummaryResponsePaymentAttemptsPaymentProvider `json:"payment_provider,required,nullable"`
+ // The ID of the payment attempt in the payment provider.
+ PaymentProviderID string `json:"payment_provider_id,required,nullable"`
+ // URL to the downloadable PDF version of the receipt. This field will be `null`
+ // for payment attempts that did not succeed.
+ ReceiptPdf string `json:"receipt_pdf,required,nullable"`
+ // Whether the payment attempt succeeded.
+ Succeeded bool `json:"succeeded,required"`
+ JSON invoiceListSummaryResponsePaymentAttemptJSON `json:"-"`
+}
+
+// invoiceListSummaryResponsePaymentAttemptJSON contains the JSON metadata for the
+// struct [InvoiceListSummaryResponsePaymentAttempt]
+type invoiceListSummaryResponsePaymentAttemptJSON struct {
+ ID apijson.Field
+ Amount apijson.Field
+ CreatedAt apijson.Field
+ PaymentProvider apijson.Field
+ PaymentProviderID apijson.Field
+ ReceiptPdf apijson.Field
+ Succeeded apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *InvoiceListSummaryResponsePaymentAttempt) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r invoiceListSummaryResponsePaymentAttemptJSON) RawJSON() string {
+ return r.raw
+}
+
+// The payment provider that attempted to collect the payment.
+type InvoiceListSummaryResponsePaymentAttemptsPaymentProvider string
+
+const (
+ InvoiceListSummaryResponsePaymentAttemptsPaymentProviderStripe InvoiceListSummaryResponsePaymentAttemptsPaymentProvider = "stripe"
+)
+
+func (r InvoiceListSummaryResponsePaymentAttemptsPaymentProvider) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryResponsePaymentAttemptsPaymentProviderStripe:
+ return true
+ }
+ return false
+}
+
+type InvoiceListSummaryResponseStatus string
+
+const (
+ InvoiceListSummaryResponseStatusIssued InvoiceListSummaryResponseStatus = "issued"
+ InvoiceListSummaryResponseStatusPaid InvoiceListSummaryResponseStatus = "paid"
+ InvoiceListSummaryResponseStatusSynced InvoiceListSummaryResponseStatus = "synced"
+ InvoiceListSummaryResponseStatusVoid InvoiceListSummaryResponseStatus = "void"
+ InvoiceListSummaryResponseStatusDraft InvoiceListSummaryResponseStatus = "draft"
+)
+
+func (r InvoiceListSummaryResponseStatus) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryResponseStatusIssued, InvoiceListSummaryResponseStatusPaid, InvoiceListSummaryResponseStatusSynced, InvoiceListSummaryResponseStatusVoid, InvoiceListSummaryResponseStatusDraft:
+ return true
+ }
+ return false
+}
+
+type InvoiceNewParams struct {
+ // An ISO 4217 currency string. Must be the same as the customer's currency if it
+ // is set.
+ Currency param.Field[string] `json:"currency,required"`
+ // Optional invoice date to set. Must be in the past, if not set, `invoice_date` is
+ // set to the current time in the customer's timezone.
+ InvoiceDate param.Field[time.Time] `json:"invoice_date,required" format:"date-time"`
+ LineItems param.Field[[]InvoiceNewParamsLineItem] `json:"line_items,required"`
+ // The id of the `Customer` to create this invoice for. One of `customer_id` and
+ // `external_customer_id` are required.
+ CustomerID param.Field[string] `json:"customer_id"`
+ // An optional discount to attach to the invoice.
+ Discount param.Field[shared.DiscountUnionParam] `json:"discount"`
+ // An optional custom due date for the invoice. If not set, the due date will be
+ // calculated based on the `net_terms` value.
+ DueDate param.Field[time.Time] `json:"due_date" format:"date-time"`
+ // The `external_customer_id` of the `Customer` to create this invoice for. One of
+ // `customer_id` and `external_customer_id` are required.
+ ExternalCustomerID param.Field[string] `json:"external_customer_id"`
+ // An optional memo to attach to the invoice. If no memo is provided, we will
+ // attach the default memo
+ Memo param.Field[string] `json:"memo"`
+ // User-specified key/value pairs for the resource. Individual keys can be removed
+ // by setting the value to `null`, and the entire metadata mapping can be cleared
+ // by setting `metadata` to `null`.
+ Metadata param.Field[map[string]string] `json:"metadata"`
+ // The net terms determines the due date of the invoice. Due date is calculated
+ // based on the invoice or issuance date, depending on the account's configured due
+ // date calculation method. A value of '0' here represents that the invoice is due
+ // on issue, whereas a value of '30' represents that the customer has 30 days to
+ // pay the invoice. Do not set this field if you want to set a custom due date.
+ NetTerms param.Field[int64] `json:"net_terms"`
+ // When true, this invoice will be submitted for issuance upon creation. When
+ // false, the resulting invoice will require manual review to issue. Defaulted to
+ // false.
+ WillAutoIssue param.Field[bool] `json:"will_auto_issue"`
+}
+
+func (r InvoiceNewParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type InvoiceNewParamsLineItem struct {
+ // A date string to specify the line item's end date in the customer's timezone.
+ EndDate param.Field[time.Time] `json:"end_date,required" format:"date"`
+ ItemID param.Field[string] `json:"item_id,required"`
+ ModelType param.Field[InvoiceNewParamsLineItemsModelType] `json:"model_type,required"`
+ // The name of the line item.
+ Name param.Field[string] `json:"name,required"`
+ // The number of units on the line item
+ Quantity param.Field[float64] `json:"quantity,required"`
+ // A date string to specify the line item's start date in the customer's timezone.
+ StartDate param.Field[time.Time] `json:"start_date,required" format:"date"`
+ // Configuration for unit pricing
+ UnitConfig param.Field[shared.UnitConfigParam] `json:"unit_config,required"`
+}
+
+func (r InvoiceNewParamsLineItem) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type InvoiceNewParamsLineItemsModelType string
+
+const (
+ InvoiceNewParamsLineItemsModelTypeUnit InvoiceNewParamsLineItemsModelType = "unit"
+)
+
+func (r InvoiceNewParamsLineItemsModelType) IsKnown() bool {
+ switch r {
+ case InvoiceNewParamsLineItemsModelTypeUnit:
+ return true
+ }
+ return false
+}
+
+type InvoiceUpdateParams struct {
+ // An optional custom due date for the invoice. If not set, the due date will be
+ // calculated based on the `net_terms` value.
+ DueDate param.Field[time.Time] `json:"due_date" format:"date-time"`
+ // The date of the invoice. Can only be modified for one-off draft invoices.
+ InvoiceDate param.Field[time.Time] `json:"invoice_date" format:"date-time"`
+ // User-specified key/value pairs for the resource. Individual keys can be removed
+ // by setting the value to `null`, and the entire metadata mapping can be cleared
+ // by setting `metadata` to `null`.
+ Metadata param.Field[map[string]string] `json:"metadata"`
+ // The net terms determines the due date of the invoice. Due date is calculated
+ // based on the invoice or issuance date, depending on the account's configured due
+ // date calculation method. A value of '0' here represents that the invoice is due
+ // on issue, whereas a value of '30' represents that the customer has 30 days to
+ // pay the invoice. Do not set this field if you want to set a custom due date.
+ NetTerms param.Field[int64] `json:"net_terms"`
+}
+
+func (r InvoiceUpdateParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type InvoiceListParams struct {
+ Amount param.Field[string] `query:"amount"`
+ AmountGt param.Field[string] `query:"amount[gt]"`
+ AmountLt param.Field[string] `query:"amount[lt]"`
+ // Cursor for pagination. This can be populated by the `next_cursor` value returned
+ // from the initial request.
+ Cursor param.Field[string] `query:"cursor"`
+ CustomerID param.Field[string] `query:"customer_id"`
+ DateType param.Field[InvoiceListParamsDateType] `query:"date_type"`
+ DueDate param.Field[time.Time] `query:"due_date" format:"date"`
+ // Filters invoices by their due dates within a specific time range in the past.
+ // Specify the range as a number followed by 'd' (days) or 'm' (months). For
+ // example, '7d' filters invoices due in the last 7 days, and '2m' filters those
+ // due in the last 2 months.
+ DueDateWindow param.Field[string] `query:"due_date_window"`
+ DueDateGt param.Field[time.Time] `query:"due_date[gt]" format:"date"`
+ DueDateLt param.Field[time.Time] `query:"due_date[lt]" format:"date"`
+ ExternalCustomerID param.Field[string] `query:"external_customer_id"`
+ InvoiceDateGt param.Field[time.Time] `query:"invoice_date[gt]" format:"date-time"`
+ InvoiceDateGte param.Field[time.Time] `query:"invoice_date[gte]" format:"date-time"`
+ InvoiceDateLt param.Field[time.Time] `query:"invoice_date[lt]" format:"date-time"`
+ InvoiceDateLte param.Field[time.Time] `query:"invoice_date[lte]" format:"date-time"`
+ IsRecurring param.Field[bool] `query:"is_recurring"`
+ // The number of items to fetch. Defaults to 20.
+ Limit param.Field[int64] `query:"limit"`
+ Status param.Field[[]InvoiceListParamsStatus] `query:"status"`
+ SubscriptionID param.Field[string] `query:"subscription_id"`
+}
+
+// URLQuery serializes [InvoiceListParams]'s query parameters as `url.Values`.
+func (r InvoiceListParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatBrackets,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type InvoiceListParamsDateType string
+
+const (
+ InvoiceListParamsDateTypeDueDate InvoiceListParamsDateType = "due_date"
+ InvoiceListParamsDateTypeInvoiceDate InvoiceListParamsDateType = "invoice_date"
+)
+
+func (r InvoiceListParamsDateType) IsKnown() bool {
+ switch r {
+ case InvoiceListParamsDateTypeDueDate, InvoiceListParamsDateTypeInvoiceDate:
+ return true
+ }
+ return false
+}
+
+type InvoiceListParamsStatus string
+
+const (
+ InvoiceListParamsStatusDraft InvoiceListParamsStatus = "draft"
+ InvoiceListParamsStatusIssued InvoiceListParamsStatus = "issued"
+ InvoiceListParamsStatusPaid InvoiceListParamsStatus = "paid"
+ InvoiceListParamsStatusSynced InvoiceListParamsStatus = "synced"
+ InvoiceListParamsStatusVoid InvoiceListParamsStatus = "void"
+)
+
+func (r InvoiceListParamsStatus) IsKnown() bool {
+ switch r {
+ case InvoiceListParamsStatusDraft, InvoiceListParamsStatusIssued, InvoiceListParamsStatusPaid, InvoiceListParamsStatusSynced, InvoiceListParamsStatusVoid:
+ return true
+ }
+ return false
+}
+
+type InvoiceFetchUpcomingParams struct {
+ SubscriptionID param.Field[string] `query:"subscription_id,required"`
+}
+
+// URLQuery serializes [InvoiceFetchUpcomingParams]'s query parameters as
+// `url.Values`.
+func (r InvoiceFetchUpcomingParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatBrackets,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type InvoiceIssueParams struct {
+ // If true, the invoice will be issued synchronously. If false, the invoice will be
+ // issued asynchronously. The synchronous option is only available for invoices
+ // that have no usage fees. If the invoice is configured to sync to an external
+ // provider, a successful response from this endpoint guarantees the invoice is
+ // present in the provider.
+ Synchronous param.Field[bool] `json:"synchronous"`
+}
+
+func (r InvoiceIssueParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+type InvoiceListSummaryParams struct {
+ Amount param.Field[string] `query:"amount"`
+ AmountGt param.Field[string] `query:"amount[gt]"`
+ AmountLt param.Field[string] `query:"amount[lt]"`
+ // Cursor for pagination. This can be populated by the `next_cursor` value returned
+ // from the initial request.
+ Cursor param.Field[string] `query:"cursor"`
+ CustomerID param.Field[string] `query:"customer_id"`
+ DateType param.Field[InvoiceListSummaryParamsDateType] `query:"date_type"`
+ DueDate param.Field[time.Time] `query:"due_date" format:"date"`
+ // Filters invoices by their due dates within a specific time range in the past.
+ // Specify the range as a number followed by 'd' (days) or 'm' (months). For
+ // example, '7d' filters invoices due in the last 7 days, and '2m' filters those
+ // due in the last 2 months.
+ DueDateWindow param.Field[string] `query:"due_date_window"`
+ DueDateGt param.Field[time.Time] `query:"due_date[gt]" format:"date"`
+ DueDateLt param.Field[time.Time] `query:"due_date[lt]" format:"date"`
+ ExternalCustomerID param.Field[string] `query:"external_customer_id"`
+ InvoiceDateGt param.Field[time.Time] `query:"invoice_date[gt]" format:"date-time"`
+ InvoiceDateGte param.Field[time.Time] `query:"invoice_date[gte]" format:"date-time"`
+ InvoiceDateLt param.Field[time.Time] `query:"invoice_date[lt]" format:"date-time"`
+ InvoiceDateLte param.Field[time.Time] `query:"invoice_date[lte]" format:"date-time"`
+ IsRecurring param.Field[bool] `query:"is_recurring"`
+ // The number of items to fetch. Defaults to 20.
+ Limit param.Field[int64] `query:"limit"`
+ Status param.Field[InvoiceListSummaryParamsStatus] `query:"status"`
+ SubscriptionID param.Field[string] `query:"subscription_id"`
+}
+
+// URLQuery serializes [InvoiceListSummaryParams]'s query parameters as
+// `url.Values`.
+func (r InvoiceListSummaryParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatBrackets,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type InvoiceListSummaryParamsDateType string
+
+const (
+ InvoiceListSummaryParamsDateTypeDueDate InvoiceListSummaryParamsDateType = "due_date"
+ InvoiceListSummaryParamsDateTypeInvoiceDate InvoiceListSummaryParamsDateType = "invoice_date"
+)
+
+func (r InvoiceListSummaryParamsDateType) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryParamsDateTypeDueDate, InvoiceListSummaryParamsDateTypeInvoiceDate:
+ return true
+ }
+ return false
+}
+
+type InvoiceListSummaryParamsStatus string
+
+const (
+ InvoiceListSummaryParamsStatusDraft InvoiceListSummaryParamsStatus = "draft"
+ InvoiceListSummaryParamsStatusIssued InvoiceListSummaryParamsStatus = "issued"
+ InvoiceListSummaryParamsStatusPaid InvoiceListSummaryParamsStatus = "paid"
+ InvoiceListSummaryParamsStatusSynced InvoiceListSummaryParamsStatus = "synced"
+ InvoiceListSummaryParamsStatusVoid InvoiceListSummaryParamsStatus = "void"
+)
+
+func (r InvoiceListSummaryParamsStatus) IsKnown() bool {
+ switch r {
+ case InvoiceListSummaryParamsStatusDraft, InvoiceListSummaryParamsStatusIssued, InvoiceListSummaryParamsStatusPaid, InvoiceListSummaryParamsStatusSynced, InvoiceListSummaryParamsStatusVoid:
+ return true
+ }
+ return false
}
type InvoiceMarkPaidParams struct {
diff --git a/invoice_test.go b/invoice_test.go
index 998b087..d9bea65 100644
--- a/invoice_test.go
+++ b/invoice_test.go
@@ -147,6 +147,32 @@ func TestInvoiceListWithOptionalParams(t *testing.T) {
}
}
+func TestInvoiceDeleteLineItem(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ err := client.Invoices.DeleteLineItem(
+ context.TODO(),
+ "invoice_id",
+ "line_item_id",
+ )
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
func TestInvoiceFetch(t *testing.T) {
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
@@ -221,6 +247,48 @@ func TestInvoiceIssueWithOptionalParams(t *testing.T) {
}
}
+func TestInvoiceListSummaryWithOptionalParams(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Invoices.ListSummary(context.TODO(), orb.InvoiceListSummaryParams{
+ Amount: orb.F("amount"),
+ AmountGt: orb.F("amount[gt]"),
+ AmountLt: orb.F("amount[lt]"),
+ Cursor: orb.F("cursor"),
+ CustomerID: orb.F("customer_id"),
+ DateType: orb.F(orb.InvoiceListSummaryParamsDateTypeDueDate),
+ DueDate: orb.F(time.Now()),
+ DueDateWindow: orb.F("due_date_window"),
+ DueDateGt: orb.F(time.Now()),
+ DueDateLt: orb.F(time.Now()),
+ ExternalCustomerID: orb.F("external_customer_id"),
+ InvoiceDateGt: orb.F(time.Now()),
+ InvoiceDateGte: orb.F(time.Now()),
+ InvoiceDateLt: orb.F(time.Now()),
+ InvoiceDateLte: orb.F(time.Now()),
+ IsRecurring: orb.F(true),
+ Limit: orb.F(int64(1)),
+ Status: orb.F(orb.InvoiceListSummaryParamsStatusDraft),
+ SubscriptionID: orb.F("subscription_id"),
+ })
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
func TestInvoiceMarkPaidWithOptionalParams(t *testing.T) {
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
diff --git a/plan.go b/plan.go
index e568f06..c391de0 100644
--- a/plan.go
+++ b/plan.go
@@ -31,6 +31,7 @@ import (
type PlanService struct {
Options []option.RequestOption
ExternalPlanID *PlanExternalPlanIDService
+ Migrations *PlanMigrationService
}
// NewPlanService generates a new service that applies the given options to each
@@ -40,6 +41,7 @@ func NewPlanService(opts ...option.RequestOption) (r *PlanService) {
r = &PlanService{}
r.Options = opts
r.ExternalPlanID = NewPlanExternalPlanIDService(opts...)
+ r.Migrations = NewPlanMigrationService(opts...)
return
}
diff --git a/planmigration.go b/planmigration.go
new file mode 100644
index 0000000..44c5328
--- /dev/null
+++ b/planmigration.go
@@ -0,0 +1,384 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package orb
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "net/http"
+ "net/url"
+ "reflect"
+ "slices"
+
+ "github.com/orbcorp/orb-go/internal/apijson"
+ "github.com/orbcorp/orb-go/internal/apiquery"
+ "github.com/orbcorp/orb-go/internal/param"
+ "github.com/orbcorp/orb-go/internal/requestconfig"
+ "github.com/orbcorp/orb-go/option"
+ "github.com/orbcorp/orb-go/packages/pagination"
+ "github.com/orbcorp/orb-go/shared"
+ "github.com/tidwall/gjson"
+)
+
+// PlanMigrationService contains methods and other services that help with
+// interacting with the orb API.
+//
+// Note, unlike clients, this service does not read variables from the environment
+// automatically. You should not instantiate this service directly, and instead use
+// the [NewPlanMigrationService] method instead.
+type PlanMigrationService struct {
+ Options []option.RequestOption
+}
+
+// NewPlanMigrationService generates a new service that applies the given options
+// to each request. These options are applied after the parent client's options (if
+// there is one), and before any request-specific options.
+func NewPlanMigrationService(opts ...option.RequestOption) (r *PlanMigrationService) {
+ r = &PlanMigrationService{}
+ r.Options = opts
+ return
+}
+
+// Fetch migration
+func (r *PlanMigrationService) Get(ctx context.Context, planID string, migrationID string, opts ...option.RequestOption) (res *PlanMigrationGetResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if planID == "" {
+ err = errors.New("missing required plan_id parameter")
+ return
+ }
+ if migrationID == "" {
+ err = errors.New("missing required migration_id parameter")
+ return
+ }
+ path := fmt.Sprintf("plans/%s/migrations/%s", planID, migrationID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return
+}
+
+// This endpoint returns a list of all migrations for a plan. The list of
+// migrations is ordered starting from the most recently created migration. The
+// response also includes pagination_metadata, which lets the caller retrieve the
+// next page of results if they exist.
+func (r *PlanMigrationService) List(ctx context.Context, planID string, query PlanMigrationListParams, opts ...option.RequestOption) (res *pagination.Page[PlanMigrationListResponse], err error) {
+ var raw *http.Response
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+ if planID == "" {
+ err = errors.New("missing required plan_id parameter")
+ return
+ }
+ path := fmt.Sprintf("plans/%s/migrations", planID)
+ cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
+ if err != nil {
+ return nil, err
+ }
+ err = cfg.Execute()
+ if err != nil {
+ return nil, err
+ }
+ res.SetPageConfig(cfg, raw)
+ return res, nil
+}
+
+// This endpoint returns a list of all migrations for a plan. The list of
+// migrations is ordered starting from the most recently created migration. The
+// response also includes pagination_metadata, which lets the caller retrieve the
+// next page of results if they exist.
+func (r *PlanMigrationService) ListAutoPaging(ctx context.Context, planID string, query PlanMigrationListParams, opts ...option.RequestOption) *pagination.PageAutoPager[PlanMigrationListResponse] {
+ return pagination.NewPageAutoPager(r.List(ctx, planID, query, opts...))
+}
+
+// This endpoint cancels a migration.
+func (r *PlanMigrationService) Cancel(ctx context.Context, planID string, migrationID string, opts ...option.RequestOption) (res *PlanMigrationCancelResponse, err error) {
+ opts = slices.Concat(r.Options, opts)
+ if planID == "" {
+ err = errors.New("missing required plan_id parameter")
+ return
+ }
+ if migrationID == "" {
+ err = errors.New("missing required migration_id parameter")
+ return
+ }
+ path := fmt.Sprintf("plans/%s/migrations/%s/cancel", planID, migrationID)
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...)
+ return
+}
+
+type PlanMigrationGetResponse struct {
+ ID string `json:"id,required"`
+ EffectiveTime PlanMigrationGetResponseEffectiveTimeUnion `json:"effective_time,required,nullable" format:"date"`
+ PlanID string `json:"plan_id,required"`
+ Status PlanMigrationGetResponseStatus `json:"status,required"`
+ JSON planMigrationGetResponseJSON `json:"-"`
+}
+
+// planMigrationGetResponseJSON contains the JSON metadata for the struct
+// [PlanMigrationGetResponse]
+type planMigrationGetResponseJSON struct {
+ ID apijson.Field
+ EffectiveTime apijson.Field
+ PlanID apijson.Field
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *PlanMigrationGetResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r planMigrationGetResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+// Union satisfied by [shared.UnionTime], [shared.UnionTime] or
+// [PlanMigrationGetResponseEffectiveTimeString].
+type PlanMigrationGetResponseEffectiveTimeUnion interface {
+ ImplementsPlanMigrationGetResponseEffectiveTimeUnion()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*PlanMigrationGetResponseEffectiveTimeUnion)(nil)).Elem(),
+ "",
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(PlanMigrationGetResponseEffectiveTimeString("")),
+ },
+ )
+}
+
+type PlanMigrationGetResponseEffectiveTimeString string
+
+const (
+ PlanMigrationGetResponseEffectiveTimeStringEndOfTerm PlanMigrationGetResponseEffectiveTimeString = "end_of_term"
+)
+
+func (r PlanMigrationGetResponseEffectiveTimeString) IsKnown() bool {
+ switch r {
+ case PlanMigrationGetResponseEffectiveTimeStringEndOfTerm:
+ return true
+ }
+ return false
+}
+
+func (r PlanMigrationGetResponseEffectiveTimeString) ImplementsPlanMigrationGetResponseEffectiveTimeUnion() {
+}
+
+type PlanMigrationGetResponseStatus string
+
+const (
+ PlanMigrationGetResponseStatusNotStarted PlanMigrationGetResponseStatus = "not_started"
+ PlanMigrationGetResponseStatusInProgress PlanMigrationGetResponseStatus = "in_progress"
+ PlanMigrationGetResponseStatusCompleted PlanMigrationGetResponseStatus = "completed"
+ PlanMigrationGetResponseStatusActionNeeded PlanMigrationGetResponseStatus = "action_needed"
+ PlanMigrationGetResponseStatusCanceled PlanMigrationGetResponseStatus = "canceled"
+)
+
+func (r PlanMigrationGetResponseStatus) IsKnown() bool {
+ switch r {
+ case PlanMigrationGetResponseStatusNotStarted, PlanMigrationGetResponseStatusInProgress, PlanMigrationGetResponseStatusCompleted, PlanMigrationGetResponseStatusActionNeeded, PlanMigrationGetResponseStatusCanceled:
+ return true
+ }
+ return false
+}
+
+type PlanMigrationListResponse struct {
+ ID string `json:"id,required"`
+ EffectiveTime PlanMigrationListResponseEffectiveTimeUnion `json:"effective_time,required,nullable" format:"date"`
+ PlanID string `json:"plan_id,required"`
+ Status PlanMigrationListResponseStatus `json:"status,required"`
+ JSON planMigrationListResponseJSON `json:"-"`
+}
+
+// planMigrationListResponseJSON contains the JSON metadata for the struct
+// [PlanMigrationListResponse]
+type planMigrationListResponseJSON struct {
+ ID apijson.Field
+ EffectiveTime apijson.Field
+ PlanID apijson.Field
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *PlanMigrationListResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r planMigrationListResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+// Union satisfied by [shared.UnionTime], [shared.UnionTime] or
+// [PlanMigrationListResponseEffectiveTimeString].
+type PlanMigrationListResponseEffectiveTimeUnion interface {
+ ImplementsPlanMigrationListResponseEffectiveTimeUnion()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*PlanMigrationListResponseEffectiveTimeUnion)(nil)).Elem(),
+ "",
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(PlanMigrationListResponseEffectiveTimeString("")),
+ },
+ )
+}
+
+type PlanMigrationListResponseEffectiveTimeString string
+
+const (
+ PlanMigrationListResponseEffectiveTimeStringEndOfTerm PlanMigrationListResponseEffectiveTimeString = "end_of_term"
+)
+
+func (r PlanMigrationListResponseEffectiveTimeString) IsKnown() bool {
+ switch r {
+ case PlanMigrationListResponseEffectiveTimeStringEndOfTerm:
+ return true
+ }
+ return false
+}
+
+func (r PlanMigrationListResponseEffectiveTimeString) ImplementsPlanMigrationListResponseEffectiveTimeUnion() {
+}
+
+type PlanMigrationListResponseStatus string
+
+const (
+ PlanMigrationListResponseStatusNotStarted PlanMigrationListResponseStatus = "not_started"
+ PlanMigrationListResponseStatusInProgress PlanMigrationListResponseStatus = "in_progress"
+ PlanMigrationListResponseStatusCompleted PlanMigrationListResponseStatus = "completed"
+ PlanMigrationListResponseStatusActionNeeded PlanMigrationListResponseStatus = "action_needed"
+ PlanMigrationListResponseStatusCanceled PlanMigrationListResponseStatus = "canceled"
+)
+
+func (r PlanMigrationListResponseStatus) IsKnown() bool {
+ switch r {
+ case PlanMigrationListResponseStatusNotStarted, PlanMigrationListResponseStatusInProgress, PlanMigrationListResponseStatusCompleted, PlanMigrationListResponseStatusActionNeeded, PlanMigrationListResponseStatusCanceled:
+ return true
+ }
+ return false
+}
+
+type PlanMigrationCancelResponse struct {
+ ID string `json:"id,required"`
+ EffectiveTime PlanMigrationCancelResponseEffectiveTimeUnion `json:"effective_time,required,nullable" format:"date"`
+ PlanID string `json:"plan_id,required"`
+ Status PlanMigrationCancelResponseStatus `json:"status,required"`
+ JSON planMigrationCancelResponseJSON `json:"-"`
+}
+
+// planMigrationCancelResponseJSON contains the JSON metadata for the struct
+// [PlanMigrationCancelResponse]
+type planMigrationCancelResponseJSON struct {
+ ID apijson.Field
+ EffectiveTime apijson.Field
+ PlanID apijson.Field
+ Status apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *PlanMigrationCancelResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r planMigrationCancelResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+// Union satisfied by [shared.UnionTime], [shared.UnionTime] or
+// [PlanMigrationCancelResponseEffectiveTimeString].
+type PlanMigrationCancelResponseEffectiveTimeUnion interface {
+ ImplementsPlanMigrationCancelResponseEffectiveTimeUnion()
+}
+
+func init() {
+ apijson.RegisterUnion(
+ reflect.TypeOf((*PlanMigrationCancelResponseEffectiveTimeUnion)(nil)).Elem(),
+ "",
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(shared.UnionTime(shared.UnionTime{})),
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.String,
+ Type: reflect.TypeOf(PlanMigrationCancelResponseEffectiveTimeString("")),
+ },
+ )
+}
+
+type PlanMigrationCancelResponseEffectiveTimeString string
+
+const (
+ PlanMigrationCancelResponseEffectiveTimeStringEndOfTerm PlanMigrationCancelResponseEffectiveTimeString = "end_of_term"
+)
+
+func (r PlanMigrationCancelResponseEffectiveTimeString) IsKnown() bool {
+ switch r {
+ case PlanMigrationCancelResponseEffectiveTimeStringEndOfTerm:
+ return true
+ }
+ return false
+}
+
+func (r PlanMigrationCancelResponseEffectiveTimeString) ImplementsPlanMigrationCancelResponseEffectiveTimeUnion() {
+}
+
+type PlanMigrationCancelResponseStatus string
+
+const (
+ PlanMigrationCancelResponseStatusNotStarted PlanMigrationCancelResponseStatus = "not_started"
+ PlanMigrationCancelResponseStatusInProgress PlanMigrationCancelResponseStatus = "in_progress"
+ PlanMigrationCancelResponseStatusCompleted PlanMigrationCancelResponseStatus = "completed"
+ PlanMigrationCancelResponseStatusActionNeeded PlanMigrationCancelResponseStatus = "action_needed"
+ PlanMigrationCancelResponseStatusCanceled PlanMigrationCancelResponseStatus = "canceled"
+)
+
+func (r PlanMigrationCancelResponseStatus) IsKnown() bool {
+ switch r {
+ case PlanMigrationCancelResponseStatusNotStarted, PlanMigrationCancelResponseStatusInProgress, PlanMigrationCancelResponseStatusCompleted, PlanMigrationCancelResponseStatusActionNeeded, PlanMigrationCancelResponseStatusCanceled:
+ return true
+ }
+ return false
+}
+
+type PlanMigrationListParams struct {
+ // Cursor for pagination. This can be populated by the `next_cursor` value returned
+ // from the initial request.
+ Cursor param.Field[string] `query:"cursor"`
+ // The number of items to fetch. Defaults to 20.
+ Limit param.Field[int64] `query:"limit"`
+}
+
+// URLQuery serializes [PlanMigrationListParams]'s query parameters as
+// `url.Values`.
+func (r PlanMigrationListParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatBrackets,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
diff --git a/planmigration_test.go b/planmigration_test.go
new file mode 100644
index 0000000..5aaeca8
--- /dev/null
+++ b/planmigration_test.go
@@ -0,0 +1,95 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package orb_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/orbcorp/orb-go"
+ "github.com/orbcorp/orb-go/internal/testutil"
+ "github.com/orbcorp/orb-go/option"
+)
+
+func TestPlanMigrationGet(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Plans.Migrations.Get(
+ context.TODO(),
+ "plan_id",
+ "migration_id",
+ )
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestPlanMigrationListWithOptionalParams(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Plans.Migrations.List(
+ context.TODO(),
+ "plan_id",
+ orb.PlanMigrationListParams{
+ Cursor: orb.F("cursor"),
+ Limit: orb.F(int64(1)),
+ },
+ )
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestPlanMigrationCancel(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Plans.Migrations.Cancel(
+ context.TODO(),
+ "plan_id",
+ "migration_id",
+ )
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/shared/union.go b/shared/union.go
index 98f6400..20c30f2 100644
--- a/shared/union.go
+++ b/shared/union.go
@@ -8,6 +8,9 @@ import (
type UnionTime time.Time
+func (UnionTime) ImplementsPlanMigrationGetResponseEffectiveTimeUnion() {}
+func (UnionTime) ImplementsPlanMigrationListResponseEffectiveTimeUnion() {}
+func (UnionTime) ImplementsPlanMigrationCancelResponseEffectiveTimeUnion() {}
func (UnionTime) ImplementsSubscriptionPriceIntervalsParamsAddStartDateUnion() {}
func (UnionTime) ImplementsSubscriptionPriceIntervalsParamsAddEndDateUnion() {}
func (UnionTime) ImplementsSubscriptionPriceIntervalsParamsAddAdjustmentsStartDateUnion() {}
diff --git a/subscriptionchange.go b/subscriptionchange.go
index f82fd7d..ef97ce0 100644
--- a/subscriptionchange.go
+++ b/subscriptionchange.go
@@ -7,14 +7,17 @@ import (
"errors"
"fmt"
"net/http"
+ "net/url"
"reflect"
"slices"
"time"
"github.com/orbcorp/orb-go/internal/apijson"
+ "github.com/orbcorp/orb-go/internal/apiquery"
"github.com/orbcorp/orb-go/internal/param"
"github.com/orbcorp/orb-go/internal/requestconfig"
"github.com/orbcorp/orb-go/option"
+ "github.com/orbcorp/orb-go/packages/pagination"
"github.com/orbcorp/orb-go/shared"
"github.com/tidwall/gjson"
)
@@ -58,6 +61,33 @@ func (r *SubscriptionChangeService) Get(ctx context.Context, subscriptionChangeI
return
}
+// This endpoint returns a list of pending subscription changes for a customer. Use
+// the [Fetch Subscription Change](fetch-subscription-change) endpoint to retrieve
+// the expected subscription state after the pending change is applied.
+func (r *SubscriptionChangeService) List(ctx context.Context, query SubscriptionChangeListParams, opts ...option.RequestOption) (res *pagination.Page[SubscriptionChangeListResponse], err error) {
+ var raw *http.Response
+ opts = slices.Concat(r.Options, opts)
+ opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...)
+ path := "subscription_changes"
+ cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...)
+ if err != nil {
+ return nil, err
+ }
+ err = cfg.Execute()
+ if err != nil {
+ return nil, err
+ }
+ res.SetPageConfig(cfg, raw)
+ return res, nil
+}
+
+// This endpoint returns a list of pending subscription changes for a customer. Use
+// the [Fetch Subscription Change](fetch-subscription-change) endpoint to retrieve
+// the expected subscription state after the pending change is applied.
+func (r *SubscriptionChangeService) ListAutoPaging(ctx context.Context, query SubscriptionChangeListParams, opts ...option.RequestOption) *pagination.PageAutoPager[SubscriptionChangeListResponse] {
+ return pagination.NewPageAutoPager(r.List(ctx, query, opts...))
+}
+
// Apply a subscription change to perform the intended action. If a positive amount
// is passed with a request to this endpoint, any eligible invoices that were
// created will be issued immediately if they only contain in-advance fees.
@@ -421,6 +451,56 @@ func (r SubscriptionChangeGetResponseStatus) IsKnown() bool {
return false
}
+type SubscriptionChangeListResponse struct {
+ ID string `json:"id,required"`
+ // Subscription change will be cancelled at this time and can no longer be applied.
+ ExpirationTime time.Time `json:"expiration_time,required" format:"date-time"`
+ Status SubscriptionChangeListResponseStatus `json:"status,required"`
+ SubscriptionID string `json:"subscription_id,required,nullable"`
+ // When this change was applied.
+ AppliedAt time.Time `json:"applied_at,nullable" format:"date-time"`
+ // When this change was cancelled.
+ CancelledAt time.Time `json:"cancelled_at,nullable" format:"date-time"`
+ JSON subscriptionChangeListResponseJSON `json:"-"`
+}
+
+// subscriptionChangeListResponseJSON contains the JSON metadata for the struct
+// [SubscriptionChangeListResponse]
+type subscriptionChangeListResponseJSON struct {
+ ID apijson.Field
+ ExpirationTime apijson.Field
+ Status apijson.Field
+ SubscriptionID apijson.Field
+ AppliedAt apijson.Field
+ CancelledAt apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SubscriptionChangeListResponse) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r subscriptionChangeListResponseJSON) RawJSON() string {
+ return r.raw
+}
+
+type SubscriptionChangeListResponseStatus string
+
+const (
+ SubscriptionChangeListResponseStatusPending SubscriptionChangeListResponseStatus = "pending"
+ SubscriptionChangeListResponseStatusApplied SubscriptionChangeListResponseStatus = "applied"
+ SubscriptionChangeListResponseStatusCancelled SubscriptionChangeListResponseStatus = "cancelled"
+)
+
+func (r SubscriptionChangeListResponseStatus) IsKnown() bool {
+ switch r {
+ case SubscriptionChangeListResponseStatusPending, SubscriptionChangeListResponseStatusApplied, SubscriptionChangeListResponseStatusCancelled:
+ return true
+ }
+ return false
+}
+
// A subscription change represents a desired new subscription / pending change to
// an existing subscription. It is a way to first preview the effects on the
// subscription as well as any changes/creation of invoices (see
@@ -561,6 +641,42 @@ func (r SubscriptionChangeCancelResponseStatus) IsKnown() bool {
return false
}
+type SubscriptionChangeListParams struct {
+ // Cursor for pagination. This can be populated by the `next_cursor` value returned
+ // from the initial request.
+ Cursor param.Field[string] `query:"cursor"`
+ CustomerID param.Field[string] `query:"customer_id"`
+ ExternalCustomerID param.Field[string] `query:"external_customer_id"`
+ // The number of items to fetch. Defaults to 20.
+ Limit param.Field[int64] `query:"limit"`
+ Status param.Field[SubscriptionChangeListParamsStatus] `query:"status"`
+}
+
+// URLQuery serializes [SubscriptionChangeListParams]'s query parameters as
+// `url.Values`.
+func (r SubscriptionChangeListParams) URLQuery() (v url.Values) {
+ return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
+ ArrayFormat: apiquery.ArrayQueryFormatBrackets,
+ NestedFormat: apiquery.NestedQueryFormatBrackets,
+ })
+}
+
+type SubscriptionChangeListParamsStatus string
+
+const (
+ SubscriptionChangeListParamsStatusPending SubscriptionChangeListParamsStatus = "pending"
+ SubscriptionChangeListParamsStatusApplied SubscriptionChangeListParamsStatus = "applied"
+ SubscriptionChangeListParamsStatusCancelled SubscriptionChangeListParamsStatus = "cancelled"
+)
+
+func (r SubscriptionChangeListParamsStatus) IsKnown() bool {
+ switch r {
+ case SubscriptionChangeListParamsStatusPending, SubscriptionChangeListParamsStatusApplied, SubscriptionChangeListParamsStatusCancelled:
+ return true
+ }
+ return false
+}
+
type SubscriptionChangeApplyParams struct {
// Description to apply to the balance transaction representing this credit.
Description param.Field[string] `json:"description"`
diff --git a/subscriptionchange_test.go b/subscriptionchange_test.go
index e63931c..355fb96 100644
--- a/subscriptionchange_test.go
+++ b/subscriptionchange_test.go
@@ -36,6 +36,34 @@ func TestSubscriptionChangeGet(t *testing.T) {
}
}
+func TestSubscriptionChangeListWithOptionalParams(t *testing.T) {
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := orb.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.SubscriptionChanges.List(context.TODO(), orb.SubscriptionChangeListParams{
+ Cursor: orb.F("cursor"),
+ CustomerID: orb.F("customer_id"),
+ ExternalCustomerID: orb.F("external_customer_id"),
+ Limit: orb.F(int64(1)),
+ Status: orb.F(orb.SubscriptionChangeListParamsStatusPending),
+ })
+ if err != nil {
+ var apierr *orb.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
func TestSubscriptionChangeApplyWithOptionalParams(t *testing.T) {
baseURL := "http://localhost:4010"
if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {