Repository: stripe/stripe-go
Pull request #1608 (2023-02-16 19:26:14)

API Updates for beta branch
Codegen for openapi v226.
cc @stripe/api-libraries

## Changelog
* Updated stable APIs to the latest version
* Add support for `CurrencyConversion` on `CheckoutSession`
* Add support for `Limits` on `FinancialConnectionsSessionParams` and `FinancialConnectionsSession`
* Remove support for `Enabled` on `FinancialConnectionsSessionManualEntryParams`
* Change type of `QuoteStatusDetailsCanceled` from `nullable(QuotesResourceStatusDetailsCanceledStatusDetails)` to `QuotesResourceStatusDetailsCanceledStatusDetails`
* Change type of `QuoteStatusDetailsStale` from `nullable(QuotesResourceStatusDetailsStaleStatusDetails)` to `QuotesResourceStatusDetailsStaleStatusDetails`
* Remove support for `Reference` on `TaxCalculationParams` and `TaxCalculation`
* Add support for `Reference` on `TaxTransactionParams`




Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2dffe377..0eef46f8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,6 +23,11 @@ jobs:
     steps:
       - uses: actions/checkout@master
 
+      - name: Setup go
+        uses: actions/setup-go@v1
+        with:
+          go-version: "1.19"
+
       - name: lint
         run: |
           go install honnef.co/go/tools/cmd/staticcheck@latest &&
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9a8d044..1e3d0ffe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -12,7 +12,6 @@
   * Add support for new value `ownership` on enums `InvoicePaymentSettingsPaymentMethodOptionsUsBankAccountFinancialConnectionsPermissions` and `SubscriptionPaymentSettingsPaymentMethodOptionsUsBankAccountFinancialConnectionsPermissions`
   * Add support for `AccountNumber` on `PaymentMethodUsBankAccount`
   * Remove support for `ID` on `QuoteLinesStartsAtLineEndsAtParams`
-  
 
 ## 74.7.0 - 2023-02-02
 * [#1600](https://github.com/stripe/stripe-go/pull/1600) API Updates
diff --git a/OPENAPI_VERSION b/OPENAPI_VERSION
index 4e134f2a..72a2ee91 100644
--- a/OPENAPI_VERSION
+++ b/OPENAPI_VERSION
@@ -1,1 +1,1 @@
-v223
\ No newline at end of file
+v226
\ No newline at end of file
diff --git a/README.md b/README.md
index 5e10a9ec..cada732f 100644
--- a/README.md
+++ b/README.md
@@ -471,6 +471,54 @@ config := &stripe.BackendConfig{
 }
 ```
 
+### Mocking clients for unit tests
+
+To mock a Stripe client for a unit tests using [GoMock](https://github.com/golang/mock):
+
+1. Generate a `Backend` type mock.
+```
+mockgen -destination=mocks/backend.go -package=mocks github.com/stripe/stripe-go/v74 Backend
+```
+2. Use the `Backend` mock to initialize and call methods on the client.
+```go
+
+import (
+	"example/hello/mocks"
+	"testing"
+
+	"github.com/golang/mock/gomock"
+	"github.com/stretchr/testify/assert"
+	"github.com/stripe/stripe-go/v74"
+	"github.com/stripe/stripe-go/v74/account"
+)
+
+func UseMockedStripeClient(t *testing.T) {
+	// Create a mock controller
+	mockCtrl := gomock.NewController(t)
+	defer mockCtrl.Finish()
+	// Create a mock stripe backend
+	mockBackend := mocks.NewMockBackend(mockCtrl)
+	client := account.Client{B: mockBackend, Key: "key_123"}
+
+	// Set up a mock call
+	mockBackend.EXPECT().Call("GET", "/v1/accounts/acc_123", gomock.Any(), gomock.Any(), gomock.Any()).
+		// Return nil error
+		Return(nil).
+		Do(func(method string, path string, key string, params stripe.ParamsContainer, v *stripe.Account) {
+			// Set the return value for the method
+			*v = stripe.Account{
+				ID: "acc_123",
+			}
+		}).Times(1)
+
+	// Call the client method
+	acc, _ := client.GetByID("acc_123", nil)
+
+	// Asset the result
+	assert.Equal(t, acc.ID, "acc_123")
+}
+```
+
 ### Beta SDKs
 
 Stripe has features in the beta phase that can be accessed via the beta version of this package.
diff --git a/account.go b/account.go
index 19077ca1..faa53adb 100644
--- a/account.go
+++ b/account.go
@@ -1256,11 +1256,13 @@ type AccountTOSAcceptance struct {
 }
 
 // This is an object representing a Stripe account. You can retrieve it to see
-// properties on the account like its current e-mail address or if the account is
-// enabled yet to make live charges.
+// properties on the account like its current requirements or if the account is
+// enabled to make live charges or receive payouts.
 //
-// Some properties, marked below, are available only to platforms that want to
-// [create and manage Express or Custom accounts](https://stripe.com/docs/connect/accounts).
+// For Custom accounts, the properties below are always returned. For other accounts, some properties are returned until that
+// account has started to go through Connect Onboarding. Once you create an [Account Link](https://stripe.com/docs/api/account_links)
+// for a Standard or Express account, some parameters are no longer returned. These are marked as **Custom Only** or **Custom and Express**
+// below. Learn about the differences [between accounts](https://stripe.com/docs/connect/accounts).
 type Account struct {
 	APIResource
 	// Business information about the account.
diff --git a/billingportal_configuration.go b/billingportal_configuration.go
index f5ac2972..4f015c4f 100644
--- a/billingportal_configuration.go
+++ b/billingportal_configuration.go
@@ -15,6 +15,7 @@ type BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate string
 const (
 	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdateAddress  BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "address"
 	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdateEmail    BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "email"
+	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdateName     BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "name"
 	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdatePhone    BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "phone"
 	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdateShipping BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "shipping"
 	BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdateTaxID    BillingPortalConfigurationFeaturesCustomerUpdateAllowedUpdate = "tax_id"
diff --git a/billingportal_session.go b/billingportal_session.go
index 38368123..7b67cd93 100644
--- a/billingportal_session.go
+++ b/billingportal_session.go
@@ -53,7 +53,7 @@ type BillingPortalSessionFlowDataSubscriptionCancelParams struct {
 	Subscription *string `form:"subscription"`
 }
 
-// Information about a specific flow for the customer to go through.
+// Information about a specific flow for the customer to go through. See the [docs](https://stripe.com/docs/customer-management/portal-deep-links) to learn more about using customer portal deep links and flows.
 type BillingPortalSessionFlowDataParams struct {
 	// Behavior after the flow is completed.
 	AfterCompletion *BillingPortalSessionFlowDataAfterCompletionParams `form:"after_completion"`
@@ -70,7 +70,7 @@ type BillingPortalSessionParams struct {
 	Configuration *string `form:"configuration"`
 	// The ID of an existing customer.
 	Customer *string `form:"customer"`
-	// Information about a specific flow for the customer to go through.
+	// Information about a specific flow for the customer to go through. See the [docs](https://stripe.com/docs/customer-management/portal-deep-links) to learn more about using customer portal deep links and flows.
 	FlowData *BillingPortalSessionFlowDataParams `form:"flow_data"`
 	// The IETF language tag of the locale Customer Portal is displayed in. If blank or auto, the customer's `preferred_locales` or browser's locale is used.
 	Locale *string `form:"locale"`
@@ -106,7 +106,7 @@ type BillingPortalSessionFlowSubscriptionCancel struct {
 	Subscription string `json:"subscription"`
 }
 
-// Information about a specific flow for the customer to go through.
+// Information about a specific flow for the customer to go through. See the [docs](https://stripe.com/docs/customer-management/portal-deep-links) to learn more about using customer portal deep links and flows.
 type BillingPortalSessionFlow struct {
 	AfterCompletion *BillingPortalSessionFlowAfterCompletion `json:"after_completion"`
 	// Configuration when `flow.type=subscription_cancel`.
@@ -137,7 +137,7 @@ type BillingPortalSession struct {
 	Created int64 `json:"created"`
 	// The ID of the customer for this session.
 	Customer string `json:"customer"`
-	// Information about a specific flow for the customer to go through.
+	// Information about a specific flow for the customer to go through. See the [docs](https://stripe.com/docs/customer-management/portal-deep-links) to learn more about using customer portal deep links and flows.
 	Flow *BillingPortalSessionFlow `json:"flow"`
 	// Unique identifier for the object.
 	ID string `json:"id"`
diff --git a/checkout_session.go b/checkout_session.go
index a479d7d0..acc115ab 100644
--- a/checkout_session.go
+++ b/checkout_session.go
@@ -63,6 +63,24 @@ const (
 	CheckoutSessionConsentCollectionTermsOfServiceRequired CheckoutSessionConsentCollectionTermsOfService = "required"
 )
 
+// The type of the label.
+type CheckoutSessionCustomFieldLabelType string
+
+// List of values that CheckoutSessionCustomFieldLabelType can take
+const (
+	CheckoutSessionCustomFieldLabelTypeCustom CheckoutSessionCustomFieldLabelType = "custom"
+)
+
+// The type of the field.
+type CheckoutSessionCustomFieldType string
+
+// List of values that CheckoutSessionCustomFieldType can take
+const (
+	CheckoutSessionCustomFieldTypeDropdown CheckoutSessionCustomFieldType = "dropdown"
+	CheckoutSessionCustomFieldTypeNumeric  CheckoutSessionCustomFieldType = "numeric"
+	CheckoutSessionCustomFieldTypeText     CheckoutSessionCustomFieldType = "text"
+)
+
 // Configure whether a Checkout Session creates a Customer when the Checkout Session completes.
 type CheckoutSessionCustomerCreation string
 
@@ -641,6 +659,42 @@ type CheckoutSessionConsentCollectionParams struct {
 	TermsOfService *string `form:"terms_of_service"`
 }
 
+// The options available for the customer to select. Up to 200 options allowed.
+type CheckoutSessionCustomFieldDropdownOptionParams struct {
+	// The label for the option, displayed to the customer. Up to 100 characters.
+	Label *string `form:"label"`
+	// The value for this option, not displayed to the customer, used by your integration to reconcile the option selected by the customer. Must be unique to this option, alphanumeric, and up to 100 characters.
+	Value *string `form:"value"`
+}
+
+// Configuration for `type=dropdown` fields.
+type CheckoutSessionCustomFieldDropdownParams struct {
+	// The options available for the customer to select. Up to 200 options allowed.
+	Options []*CheckoutSessionCustomFieldDropdownOptionParams `form:"options"`
+}
+
+// The label for the field, displayed to the customer.
+type CheckoutSessionCustomFieldLabelParams struct {
+	// Custom text for the label, displayed to the customer. Up to 50 characters.
+	Custom *string `form:"custom"`
+	// The type of the label.
+	Type *string `form:"type"`
+}
+
+// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+type CheckoutSessionCustomFieldParams struct {
+	// Configuration for `type=dropdown` fields.
+	Dropdown *CheckoutSessionCustomFieldDropdownParams `form:"dropdown"`
+	// String of your choice that your integration can use to reconcile this field. Must be unique to this field, alphanumeric, and up to 200 characters.
+	Key *string `form:"key"`
+	// The label for the field, displayed to the customer.
+	Label *CheckoutSessionCustomFieldLabelParams `form:"label"`
+	// Whether the customer is required to complete the field before completing the Checkout Session. Defaults to `false`.
+	Optional *bool `form:"optional"`
+	// The type of the field.
+	Type *string `form:"type"`
+}
+
 // Custom text that should be displayed alongside shipping address collection.
 type CheckoutSessionCustomTextShippingAddressParams struct {
 	// Text may be up to 1000 characters in length.
@@ -1447,6 +1501,8 @@ type CheckoutSessionParams struct {
 	CustomerEmail *string `form:"customer_email"`
 	// Controls what fields on Customer can be updated by the Checkout Session. Can only be provided when `customer` is provided.
 	CustomerUpdate *CheckoutSessionCustomerUpdateParams `form:"customer_update"`
+	// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+	CustomFields []*CheckoutSessionCustomFieldParams `form:"custom_fields"`
 	// Display additional text for your customers using custom text.
 	CustomText *CheckoutSessionCustomTextParams `form:"custom_text"`
 	// The coupon or promotion code to apply to this Session. Currently, only up to one may be specified.
@@ -1575,6 +1631,67 @@ type CheckoutSessionConsentCollection struct {
 	TermsOfService CheckoutSessionConsentCollectionTermsOfService `json:"terms_of_service"`
 }
 
+// Currency conversion details for automatic currency conversion sessions
+type CheckoutSessionCurrencyConversion struct {
+	// Total of all items in source currency before discounts or taxes are applied.
+	AmountSubtotal int64 `json:"amount_subtotal"`
+	// Total of all items in source currency after discounts and taxes are applied.
+	AmountTotal int64 `json:"amount_total"`
+	// Creation currency of the CheckoutSession before localization
+	SourceCurrency Currency `json:"source_currency"`
+}
+
+// The options available for the customer to select. Up to 200 options allowed.
+type CheckoutSessionCustomFieldDropdownOption struct {
+	// The label for the option, displayed to the customer. Up to 100 characters.
+	Label string `json:"label"`
+	// The value for this option, not displayed to the customer, used by your integration to reconcile the option selected by the customer. Must be unique to this option, alphanumeric, and up to 100 characters.
+	Value string `json:"value"`
+}
+
+// Configuration for `type=dropdown` fields.
+type CheckoutSessionCustomFieldDropdown struct {
+	// The options available for the customer to select. Up to 200 options allowed.
+	Options []*CheckoutSessionCustomFieldDropdownOption `json:"options"`
+	// The option selected by the customer. This will be the `value` for the option.
+	Value string `json:"value"`
+}
+type CheckoutSessionCustomFieldLabel struct {
+	// Custom text for the label, displayed to the customer. Up to 50 characters.
+	Custom string `json:"custom"`
+	// The type of the label.
+	Type CheckoutSessionCustomFieldLabelType `json:"type"`
+}
+
+// Configuration for `type=numeric` fields.
+type CheckoutSessionCustomFieldNumeric struct {
+	// The value entered by the customer, containing only digits.
+	Value string `json:"value"`
+}
+
+// Configuration for `type=text` fields.
+type CheckoutSessionCustomFieldText struct {
+	// The value entered by the customer.
+	Value string `json:"value"`
+}
+
+// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+type CheckoutSessionCustomField struct {
+	// Configuration for `type=dropdown` fields.
+	Dropdown *CheckoutSessionCustomFieldDropdown `json:"dropdown"`
+	// String of your choice that your integration can use to reconcile this field. Must be unique to this field, alphanumeric, and up to 200 characters.
+	Key   string                           `json:"key"`
+	Label *CheckoutSessionCustomFieldLabel `json:"label"`
+	// Configuration for `type=numeric` fields.
+	Numeric *CheckoutSessionCustomFieldNumeric `json:"numeric"`
+	// Whether the customer is required to complete the field before completing the Checkout Session. Defaults to `false`.
+	Optional bool `json:"optional"`
+	// Configuration for `type=text` fields.
+	Text *CheckoutSessionCustomFieldText `json:"text"`
+	// The type of the field.
+	Type CheckoutSessionCustomFieldType `json:"type"`
+}
+
 // Custom text that should be displayed alongside shipping address collection.
 type CheckoutSessionCustomTextShippingAddress struct {
 	// Text may be up to 1000 characters in length.
@@ -2022,8 +2139,8 @@ type CheckoutSessionTotalDetails struct {
 // [PaymentIntent](https://stripe.com/docs/api/payment_intents) or an active
 // [Subscription](https://stripe.com/docs/api/subscriptions).
 //
-// You can create a Checkout Session on your server and pass its ID to the
-// client to begin Checkout.
+// You can create a Checkout Session on your server and redirect to its URL
+// to begin Checkout.
 //
 // Related guide: [Checkout Quickstart](https://stripe.com/docs/checkout/quickstart).
 type CheckoutSession struct {
@@ -2053,6 +2170,8 @@ type CheckoutSession struct {
 	Created int64 `json:"created"`
 	// Three-letter [ISO currency code](https://www.iso.org/iso-4217-currency-codes.html), in lowercase. Must be a [supported currency](https://stripe.com/docs/currencies).
 	Currency Currency `json:"currency"`
+	// Currency conversion details for automatic currency conversion sessions
+	CurrencyConversion *CheckoutSessionCurrencyConversion `json:"currency_conversion"`
 	// The ID of the customer for this Session.
 	// For Checkout Sessions in `payment` or `subscription` mode, Checkout
 	// will create a new customer object based on information provided
@@ -2068,12 +2187,13 @@ type CheckoutSession struct {
 	// Use this parameter to prefill customer data if you already have an email
 	// on file. To access information about the customer once the payment flow is
 	// complete, use the `customer` attribute.
-	CustomerEmail string                     `json:"customer_email"`
-	CustomText    *CheckoutSessionCustomText `json:"custom_text"`
+	CustomerEmail string `json:"customer_email"`
+	// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+	CustomFields []*CheckoutSessionCustomField `json:"custom_fields"`
+	CustomText   *CheckoutSessionCustomText    `json:"custom_text"`
 	// The timestamp at which the Checkout Session will expire.
 	ExpiresAt int64 `json:"expires_at"`
-	// Unique identifier for the object. Used to pass to `redirectToCheckout`
-	// in Stripe.js.
+	// Unique identifier for the object.
 	ID string `json:"id"`
 	// ID of the invoice created by the Checkout Session, if it exists.
 	Invoice *Invoice `json:"invoice"`
diff --git a/financialconnections_session.go b/financialconnections_session.go
index 9b22d9b9..9d07215f 100644
--- a/financialconnections_session.go
+++ b/financialconnections_session.go
@@ -73,10 +73,14 @@ type FinancialConnectionsSessionFiltersParams struct {
 	Countries []*string `form:"countries"`
 }
 
+// Settings for configuring Session-specific limits.
+type FinancialConnectionsSessionLimitsParams struct {
+	// The number of accounts that can be linked in this Session.
+	Accounts *int64 `form:"accounts"`
+}
+
 // Settings for configuring manual entry of account details for this Session.
 type FinancialConnectionsSessionManualEntryParams struct {
-	// Whether manual entry will be allowed on this Session.
-	Enabled *bool `form:"enabled"`
 	// Whether manual entry will be handled by Stripe during the Session.
 	Mode *string `form:"mode"`
 }
@@ -88,6 +92,8 @@ type FinancialConnectionsSessionParams struct {
 	AccountHolder *FinancialConnectionsSessionAccountHolderParams `form:"account_holder"`
 	// Filters to restrict the kinds of accounts to collect.
 	Filters *FinancialConnectionsSessionFiltersParams `form:"filters"`
+	// Settings for configuring Session-specific limits.
+	Limits *FinancialConnectionsSessionLimitsParams `form:"limits"`
 	// Settings for configuring manual entry of account details for this Session.
 	ManualEntry *FinancialConnectionsSessionManualEntryParams `form:"manual_entry"`
 	// List of data features that you would like to request access to.
@@ -113,6 +119,10 @@ type FinancialConnectionsSessionFilters struct {
 	// List of countries from which to filter accounts.
 	Countries []string `json:"countries"`
 }
+type FinancialConnectionsSessionLimits struct {
+	// The number of accounts that can be linked in this Session.
+	Accounts int64 `json:"accounts"`
+}
 type FinancialConnectionsSessionManualEntry struct{}
 type FinancialConnectionsSessionStatusDetailsCancelled struct {
 	// The reason for the Session being cancelled.
@@ -133,7 +143,8 @@ type FinancialConnectionsSession struct {
 	ClientSecret string                              `json:"client_secret"`
 	Filters      *FinancialConnectionsSessionFilters `json:"filters"`
 	// Unique identifier for the object.
-	ID string `json:"id"`
+	ID     string                             `json:"id"`
+	Limits *FinancialConnectionsSessionLimits `json:"limits"`
 	// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
 	Livemode    bool                                    `json:"livemode"`
 	ManualEntry *FinancialConnectionsSessionManualEntry `json:"manual_entry"`
diff --git a/form/form.go b/form/form.go
index 0a96b723..e29e3766 100644
--- a/form/form.go
+++ b/form/form.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"net/url"
 	"reflect"
+	"sort"
 	"strconv"
 	"strings"
 	"sync"
@@ -338,16 +339,24 @@ func isAppender(t reflect.Type) bool {
 }
 
 func mapEncoder(values *Values, v reflect.Value, keyParts []string, _ bool, _ *formOptions) {
+	keys := make([]string, 0, v.Len())
 	for _, keyVal := range v.MapKeys() {
-		if Strict && keyVal.Kind() != reflect.String {
-			panic("Don't support serializing maps with non-string keys")
+		if keyVal.Kind() != reflect.String {
+			if Strict {
+				panic("Don't support serializing maps with non-string keys")
+			}
+			// otherwise keyVal.String() will panic later
+			continue
 		}
-
+		keys = append(keys, keyVal.String())
+	}
+	sort.Strings(keys)
+	for _, key := range keys {
 		// Unlike a property on a struct which will contain a zero value even
 		// if never set, any value found in a map has been explicitly set, so
 		// we always make an effort to encode them, even if a zero value
 		// (that's why we pass through `true` here).
-		reflectValue(values, v.MapIndex(keyVal), true, append(keyParts, keyVal.String()))
+		reflectValue(values, v.MapIndex(reflect.ValueOf(key)), true, append(keyParts, key))
 	}
 }
 
diff --git a/invoice.go b/invoice.go
index c507d0e6..3a206ab7 100644
--- a/invoice.go
+++ b/invoice.go
@@ -866,7 +866,7 @@ type InvoiceUpcomingLinesInvoiceItemParams struct {
 
 // Define thresholds at which an invoice will be sent, and the subscription advanced to a new billing period. When updating, pass an empty string to remove previously-defined thresholds.
 type InvoiceUpcomingLinesSubscriptionItemBillingThresholdsParams struct {
-	// Usage threshold that triggers the subscription to advance to a new billing period
+	// Number of units that meets the billing threshold to advance the subscription to a new billing period (e.g., it takes 10 $5 units to meet a $50 [monetary threshold](https://stripe.com/docs/api/subscriptions/update#update_subscription-billing_thresholds-amount_gte))
 	UsageGTE *int64 `form:"usage_gte"`
 }
 
@@ -1363,7 +1363,7 @@ type Invoice struct {
 	LastFinalizationError *Error `json:"last_finalization_error"`
 	// The ID of the most recent non-draft revision of this invoice
 	LatestRevision *Invoice `json:"latest_revision"`
-	// The individual line items that make up the invoice. `lines` is sorted as follows: invoice items in reverse chronological order, followed by the subscription, if any.
+	// The individual line items that make up the invoice. `lines` is sorted as follows: (1) pending invoice items (including prorations) in reverse chronological order, (2) subscription items in reverse chronological order, and (3) invoice items added after invoice creation in chronological order.
 	Lines *InvoiceLineItemList `json:"lines"`
 	// Has the value `true` if the object exists in live mode or the value `false` if the object exists in test mode.
 	Livemode bool `json:"livemode"`
diff --git a/invoiceitem.go b/invoiceitem.go
index c75588d1..f9871fc6 100644
--- a/invoiceitem.go
+++ b/invoiceitem.go
@@ -108,13 +108,17 @@ type InvoiceItemParams struct {
 	UnitAmountDecimal *float64 `form:"unit_amount_decimal,high_precision"`
 }
 
-// Sometimes you want to add a charge or credit to a customer, but actually
-// charge or credit the customer's card only at the end of a regular billing
-// cycle. This is useful for combining several charges (to minimize
-// per-transaction fees), or for having Stripe tabulate your usage-based billing
-// totals.
+// Invoice Items represent the component lines of an [invoice](https://stripe.com/docs/api/invoices). An invoice item is added to an
+// invoice by creating or updating it with an `invoice` field, at which point it will be included as
+// [an invoice line item](https://stripe.com/docs/api/invoices/line_item) within
+// [invoice.lines](https://stripe.com/docs/api/invoices/object#invoice_object-lines).
 //
-// Related guide: [Subscription Invoices](https://stripe.com/docs/billing/invoices/subscription#adding-upcoming-invoice-items).
+// Invoice Items can be created before you are ready to actually send the invoice. This can be particularly useful when combined
+// with a [subscription](https://stripe.com/docs/api/subscriptions). Sometimes you want to add a charge or credit to a customer, but actually charge
+// or credit the customer's card only at the end of a regular billing cycle. This is useful for combining several charges
+// (to minimize per-transaction fees), or for having Stripe tabulate your usage-based billing totals.
+//
+// Related guides: [Integrate with the Invoicing API](https://stripe.com/docs/invoicing/integration), [Subscription Invoices](https://stripe.com/docs/billing/invoices/subscription#adding-upcoming-invoice-items).
 type InvoiceItem struct {
 	APIResource
 	// Amount (in the `currency` specified) of the invoice item. This should always be equal to `unit_amount * quantity`.
diff --git a/invoicelineitem.go b/invoicelineitem.go
index b5787fb3..b8a02418 100644
--- a/invoicelineitem.go
+++ b/invoicelineitem.go
@@ -93,7 +93,7 @@ type InvoiceLineItem struct {
 	Quantity int64 `json:"quantity"`
 	// The subscription that the invoice item pertains to, if any.
 	Subscription string `json:"subscription"`
-	// The subscription item that generated this invoice item. Left empty if the line item is not an explicit result of a subscription.
+	// The subscription item that generated this line item. Left empty if the line item is not an explicit result of a subscription.
 	SubscriptionItem string `json:"subscription_item"`
 	// The amount of tax calculated per tax rate for this line item
 	TaxAmounts []*InvoiceTotalTaxAmount `json:"tax_amounts"`
diff --git a/paymentlink.go b/paymentlink.go
index 95ba773a..e03c53ef 100644
--- a/paymentlink.go
+++ b/paymentlink.go
@@ -44,6 +44,24 @@ const (
 	PaymentLinkConsentCollectionTermsOfServiceRequired PaymentLinkConsentCollectionTermsOfService = "required"
 )
 
+// The type of the label.
+type PaymentLinkCustomFieldLabelType string
+
+// List of values that PaymentLinkCustomFieldLabelType can take
+const (
+	PaymentLinkCustomFieldLabelTypeCustom PaymentLinkCustomFieldLabelType = "custom"
+)
+
+// The type of the field.
+type PaymentLinkCustomFieldType string
+
+// List of values that PaymentLinkCustomFieldType can take
+const (
+	PaymentLinkCustomFieldTypeDropdown PaymentLinkCustomFieldType = "dropdown"
+	PaymentLinkCustomFieldTypeNumeric  PaymentLinkCustomFieldType = "numeric"
+	PaymentLinkCustomFieldTypeText     PaymentLinkCustomFieldType = "text"
+)
+
 // Configuration for Customer creation during checkout.
 type PaymentLinkCustomerCreation string
 
@@ -170,6 +188,42 @@ type PaymentLinkConsentCollectionParams struct {
 	TermsOfService *string `form:"terms_of_service"`
 }
 
+// The options available for the customer to select. Up to 200 options allowed.
+type PaymentLinkCustomFieldDropdownOptionParams struct {
+	// The label for the option, displayed to the customer. Up to 100 characters.
+	Label *string `form:"label"`
+	// The value for this option, not displayed to the customer, used by your integration to reconcile the option selected by the customer. Must be unique to this option, alphanumeric, and up to 100 characters.
+	Value *string `form:"value"`
+}
+
+// Configuration for `type=dropdown` fields.
+type PaymentLinkCustomFieldDropdownParams struct {
+	// The options available for the customer to select. Up to 200 options allowed.
+	Options []*PaymentLinkCustomFieldDropdownOptionParams `form:"options"`
+}
+
+// The label for the field, displayed to the customer.
+type PaymentLinkCustomFieldLabelParams struct {
+	// Custom text for the label, displayed to the customer. Up to 50 characters.
+	Custom *string `form:"custom"`
+	// The type of the label.
+	Type *string `form:"type"`
+}
+
+// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+type PaymentLinkCustomFieldParams struct {
+	// Configuration for `type=dropdown` fields.
+	Dropdown *PaymentLinkCustomFieldDropdownParams `form:"dropdown"`
+	// String of your choice that your integration can use to reconcile this field. Must be unique to this field, alphanumeric, and up to 200 characters.
+	Key *string `form:"key"`
+	// The label for the field, displayed to the customer.
+	Label *PaymentLinkCustomFieldLabelParams `form:"label"`
+	// Whether the customer is required to complete the field before completing the Checkout Session. Defaults to `false`.
+	Optional *bool `form:"optional"`
+	// The type of the field.
+	Type *string `form:"type"`
+}
+
 // Custom text that should be displayed alongside shipping address collection.
 type PaymentLinkCustomTextShippingAddressParams struct {
 	// Text may be up to 1000 characters in length.
@@ -337,6 +391,8 @@ type PaymentLinkParams struct {
 	Currency *string `form:"currency"`
 	// Configures whether [checkout sessions](https://stripe.com/docs/api/checkout/sessions) created by this payment link create a [Customer](https://stripe.com/docs/api/customers).
 	CustomerCreation *string `form:"customer_creation"`
+	// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+	CustomFields []*PaymentLinkCustomFieldParams `form:"custom_fields"`
 	// Display additional text for your customers using custom text.
 	CustomText *PaymentLinkCustomTextParams `form:"custom_text"`
 	// Generate a post-purchase Invoice for one-time payments.
@@ -405,6 +461,39 @@ type PaymentLinkConsentCollection struct {
 	TermsOfService PaymentLinkConsentCollectionTermsOfService `json:"terms_of_service"`
 }
 
+// The options available for the customer to select. Up to 200 options allowed.
+type PaymentLinkCustomFieldDropdownOption struct {
+	// The label for the option, displayed to the customer. Up to 100 characters.
+	Label string `json:"label"`
+	// The value for this option, not displayed to the customer, used by your integration to reconcile the option selected by the customer. Must be unique to this option, alphanumeric, and up to 100 characters.
+	Value string `json:"value"`
+}
+
+// Configuration for `type=dropdown` fields.
+type PaymentLinkCustomFieldDropdown struct {
+	// The options available for the customer to select. Up to 200 options allowed.
+	Options []*PaymentLinkCustomFieldDropdownOption `json:"options"`
+}
+type PaymentLinkCustomFieldLabel struct {
+	// Custom text for the label, displayed to the customer. Up to 50 characters.
+	Custom string `json:"custom"`
+	// The type of the label.
+	Type PaymentLinkCustomFieldLabelType `json:"type"`
+}
+
+// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+type PaymentLinkCustomField struct {
+	// Configuration for `type=dropdown` fields.
+	Dropdown *PaymentLinkCustomFieldDropdown `json:"dropdown"`
+	// String of your choice that your integration can use to reconcile this field. Must be unique to this field, alphanumeric, and up to 200 characters.
+	Key   string                       `json:"key"`
+	Label *PaymentLinkCustomFieldLabel `json:"label"`
+	// Whether the customer is required to complete the field before completing the Checkout Session. Defaults to `false`.
+	Optional bool `json:"optional"`
+	// The type of the field.
+	Type PaymentLinkCustomFieldType `json:"type"`
+}
+
 // Custom text that should be displayed alongside shipping address collection.
 type PaymentLinkCustomTextShippingAddress struct {
 	// Text may be up to 1000 characters in length.
@@ -532,7 +621,9 @@ type PaymentLink struct {
 	Currency Currency `json:"currency"`
 	// Configuration for Customer creation during checkout.
 	CustomerCreation PaymentLinkCustomerCreation `json:"customer_creation"`
-	CustomText       *PaymentLinkCustomText      `json:"custom_text"`
+	// Collect additional information from your customer using custom fields. Up to 2 fields are supported.
+	CustomFields []*PaymentLinkCustomField `json:"custom_fields"`
+	CustomText   *PaymentLinkCustomText    `json:"custom_text"`
 	// Unique identifier for the object.
 	ID string `json:"id"`
 	// Configuration for creating invoice for payment mode payment links.
diff --git a/quote.go b/quote.go
index 67f47151..9bb38ace 100644
--- a/quote.go
+++ b/quote.go
@@ -1044,7 +1044,7 @@ type QuotePreviewSubscriptionSchedulesParams struct {
 	Quote      *string `form:"-"` // Included in URL
 }
 
-// When retrieving a quote, there is an includable lines property containing the first handful of those items. There is also a URL where you can retrieve the full (paginated) list of lines.
+// Retrieves a paginated list of lines for a quote. These lines describe changes that will be used to create new subscription schedules or update existing subscription schedules when the quote is accepted.
 type QuoteListLinesParams struct {
 	ListParams `form:"*"`
 	Quote      *string `form:"-"` // Included in URL
@@ -1175,8 +1175,6 @@ type QuoteInvoiceSettings struct {
 	// Number of days within which a customer must pay invoices generated by this quote. This value will be `null` for quotes where `collection_method=charge_automatically`.
 	DaysUntilDue int64 `json:"days_until_due"`
 }
-
-// Details on when and why a quote has been marked as canceled.
 type QuoteStatusDetailsCanceled struct {
 	// The reason this quote was marked as canceled.
 	Reason QuoteStatusDetailsCanceledReason `json:"reason"`
@@ -1209,8 +1207,6 @@ type QuoteStatusDetailsStaleLastReason struct {
 	// The reason the quote was marked as stale.
 	Type QuoteStatusDetailsStaleLastReasonType `json:"type"`
 }
-
-// Details on when and why a quote has been marked as stale.
 type QuoteStatusDetailsStale struct {
 	// Time at which the quote expires. Measured in seconds since the Unix epoch.
 	ExpiresAt int64 `json:"expires_at"`
@@ -1224,10 +1220,8 @@ type QuoteStatusDetailsStale struct {
 
 // Details on when and why a quote has been marked as stale or canceled.
 type QuoteStatusDetails struct {
-	// Details on when and why a quote has been marked as canceled.
 	Canceled *QuoteStatusDetailsCanceled `json:"canceled"`
-	// Details on when and why a quote has been marked as stale.
-	Stale *QuoteStatusDetailsStale `json:"stale"`
+	Stale    *QuoteStatusDetailsStale    `json:"stale"`
 }
 type QuoteStatusTransitions struct {
 	// The time that the quote was accepted. Measured in seconds since Unix epoch.
diff --git a/refund.go b/refund.go
index a637c974..bf16906a 100644
--- a/refund.go
+++ b/refund.go
@@ -8,7 +8,7 @@ package stripe
 
 import "encoding/json"
 
-// If the refund failed, the reason for refund failure if known. Possible values are `lost_or_stolen_card`, `expired_or_canceled_card`, or `unknown`.
+// If the refund failed, the reason for refund failure if known. Possible values are `lost_or_stolen_card`, `expired_or_canceled_card`, `charge_for_pending_refund_disputed`, `insufficient_funds`, `declined`, `merchant_request` or `unknown`.
 type RefundFailureReason string
 
 // List of values that RefundFailureReason can take
@@ -119,7 +119,7 @@ type Refund struct {
 	Description string `json:"description"`
 	// If the refund failed, this balance transaction describes the adjustment made on your account balance that reverses the initial balance transaction.
 	FailureBalanceTransaction *BalanceTransaction `json:"failure_balance_transaction"`
-	// If the refund failed, the reason for refund failure if known. Possible values are `lost_or_stolen_card`, `expired_or_canceled_card`, or `unknown`.
+	// If the refund failed, the reason for refund failure if known. Possible values are `lost_or_stolen_card`, `expired_or_canceled_card`, `charge_for_pending_refund_disputed`, `insufficient_funds`, `declined`, `merchant_request` or `unknown`.
 	FailureReason RefundFailureReason `json:"failure_reason"`
 	// Unique identifier for the object.
 	ID string `json:"id"`
diff --git a/reporting_reportrun.go b/reporting_reportrun.go
index 692f8dd0..1bbbc0cc 100644
--- a/reporting_reportrun.go
+++ b/reporting_reportrun.go
@@ -61,9 +61,9 @@ type ReportingReportRunParameters struct {
 	ConnectedAccount string `json:"connected_account"`
 	// Currency of objects to be included in the report run.
 	Currency Currency `json:"currency"`
-	// Ending timestamp of data to be included in the report run (exclusive).
+	// Ending timestamp of data to be included in the report run. Can be any UTC timestamp between 1 second after the user specified `interval_start` and 1 second before this report's last `data_available_end` value.
 	IntervalEnd int64 `json:"interval_end"`
-	// Starting timestamp of data to be included in the report run.
+	// Starting timestamp of data to be included in the report run. Can be any UTC timestamp between 1 second after this report's `data_available_start` and 1 second before the user specified `interval_end` value.
 	IntervalStart int64 `json:"interval_start"`
 	// Payout ID by which to filter the report run.
 	Payout string `json:"payout"`
diff --git a/subscriptionitem.go b/subscriptionitem.go
index 740af097..6b294792 100644
--- a/subscriptionitem.go
+++ b/subscriptionitem.go
@@ -23,7 +23,7 @@ type SubscriptionItemListParams struct {
 
 // Define thresholds at which an invoice will be sent, and the subscription advanced to a new billing period. When updating, pass an empty string to remove previously-defined thresholds.
 type SubscriptionItemBillingThresholdsParams struct {
-	// Usage threshold that triggers the subscription to advance to a new billing period
+	// Number of units that meets the billing threshold to advance the subscription to a new billing period (e.g., it takes 10 $5 units to meet a $50 [monetary threshold](https://stripe.com/docs/api/subscriptions/update#update_subscription-billing_thresholds-amount_gte))
 	UsageGTE *int64 `form:"usage_gte"`
 }
 
diff --git a/tax_calculation.go b/tax_calculation.go
index 8eff4b8a..c11fba94 100644
--- a/tax_calculation.go
+++ b/tax_calculation.go
@@ -138,8 +138,6 @@ type TaxCalculationParams struct {
 	LineItems []*TaxCalculationLineItemParams `form:"line_items"`
 	// The boolean value that indicates if the calculation is a preview. If true, the calculation is not stored. If false, the calculation is stored for 48 hours. Defaults to true.
 	Preview *bool `form:"preview"`
-	// A custom order or sale identifier, such as 'myOrder_123'.
-	Reference *string `form:"reference"`
 	// Timestamp of date at which the tax rules and rates in effect applies for the calculation. Measured in seconds since the Unix epoch.
 	TaxDate *int64 `form:"tax_date"`
 }
@@ -209,8 +207,6 @@ type TaxCalculation struct {
 	Livemode bool `json:"livemode"`
 	// String representing the object's type. Objects of the same type share the same value.
 	Object string `json:"object"`
-	// A custom unique identifier, such as 'myOrder_123'.
-	Reference string `json:"reference"`
 	// The amount of tax to be collected on top of the line item prices.
 	TaxAmountExclusive int64 `json:"tax_amount_exclusive"`
 	// The amount of tax already included in the line item prices.
diff --git a/tax_transaction.go b/tax_transaction.go
index a79477da..27c7e8fd 100644
--- a/tax_transaction.go
+++ b/tax_transaction.go
@@ -88,6 +88,8 @@ type TaxTransactionParams struct {
 	Params `form:"*"`
 	// Tax Calculation ID to be used as input when creating the transaction.
 	FromCalculation *string `form:"from_calculation"`
+	// A custom order or sale identifier, such as 'myOrder_123'.
+	Reference *string `form:"reference"`
 }
 
 // Lists Tax Transaction objects.


Test patch:
diff --git a/example/generated_examples_test.go b/example/generated_examples_test.go
index f0ade6af..fc42ae56 100644
--- a/example/generated_examples_test.go
+++ b/example/generated_examples_test.go
@@ -619,15 +619,6 @@ func TestCapabilityUpdate(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
-func TestSubscriptionResume(t *testing.T) {
-	params := &stripe.SubscriptionResumeParams{
-		ProrationDate:     stripe.Int64(1675400000),
-		ProrationBehavior: stripe.String("always_invoice"),
-	}
-	result, _ := subscription.Resume("sub_xxxxxxxxxxxxx", params)
-	assert.NotNil(t, result)
-}
-
 func TestPersonList(t *testing.T) {
 	params := &stripe.PersonListParams{
 		Account: stripe.String("acct_xxxxxxxxxxxxx"),
@@ -654,6 +645,18 @@ func TestPersonUpdate(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
+func TestAppsSecretList2(t *testing.T) {
+	params := &stripe.AppsSecretListParams{
+		Scope: &stripe.AppsSecretListScopeParams{
+			Type: stripe.String(string(stripe.AppsSecretScopeTypeAccount)),
+		},
+	}
+	params.Limit = stripe.Int64(2)
+	result := apps_secret.List(params)
+	assert.NotNil(t, result)
+	assert.Nil(t, result.Err())
+}
+
 func TestAppsSecretCreate2(t *testing.T) {
 	params := &stripe.AppsSecretParams{
 		Name:    stripe.String("my-api-key"),
@@ -750,7 +753,7 @@ func TestChargeCreate(t *testing.T) {
 		Amount:      stripe.Int64(2000),
 		Currency:    stripe.String(string(stripe.CurrencyUSD)),
 		Source:      &stripe.PaymentSourceSourceParams{Token: stripe.String("tok_xxxx")},
-		Description: stripe.String("My First Test Charge (created for API docs)"),
+		Description: stripe.String("My First Test Charge (created for API docs at https://www.stripe.com/docs/api)"),
 	}
 	result, _ := charge.New(params)
 	assert.NotNil(t, result)
@@ -875,7 +878,7 @@ func TestCustomerList2(t *testing.T) {
 
 func TestCustomerCreate(t *testing.T) {
 	params := &stripe.CustomerParams{
-		Description: stripe.String("My First Test Customer (created for API docs)"),
+		Description: stripe.String("My First Test Customer (created for API docs at https://www.stripe.com/docs/api)"),
 	}
 	result, _ := customer.New(params)
 	assert.NotNil(t, result)
@@ -1060,6 +1063,15 @@ func TestFinancialConnectionsAccountRetrieve2(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
+func TestFinancialConnectionsAccountDisconnect2(t *testing.T) {
+	params := &stripe.FinancialConnectionsAccountDisconnectParams{}
+	result, _ := financialconnections_account.Disconnect(
+		"fca_xxxxxxxxxxxxx",
+		params,
+	)
+	assert.NotNil(t, result)
+}
+
 func TestFinancialConnectionsAccountListOwners2(t *testing.T) {
 	params := &stripe.FinancialConnectionsAccountListOwnersParams{
 		Ownership: stripe.String("fcaowns_xxxxxxxxxxxxx"),
@@ -1437,9 +1449,11 @@ func TestPaymentIntentList(t *testing.T) {
 
 func TestPaymentIntentCreate2(t *testing.T) {
 	params := &stripe.PaymentIntentParams{
-		Amount:             stripe.Int64(2000),
-		Currency:           stripe.String(string(stripe.CurrencyUSD)),
-		PaymentMethodTypes: []*string{stripe.String("card")},
+		Amount:   stripe.Int64(2000),
+		Currency: stripe.String(string(stripe.CurrencyUSD)),
+		AutomaticPaymentMethods: &stripe.PaymentIntentAutomaticPaymentMethodsParams{
+			Enabled: stripe.Bool(true),
+		},
 	}
 	result, _ := paymentintent.New(params)
 	assert.NotNil(t, result)
@@ -1492,6 +1506,14 @@ func TestPaymentIntentIncrementAuthorization(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
+func TestPaymentIntentVerifyMicrodeposits2(t *testing.T) {
+	params := &stripe.PaymentIntentVerifyMicrodepositsParams{
+		Amounts: []*int64{stripe.Int64(32), stripe.Int64(45)},
+	}
+	result, _ := paymentintent.VerifyMicrodeposits("pi_xxxxxxxxxxxxx", params)
+	assert.NotNil(t, result)
+}
+
 func TestPaymentIntentSearch(t *testing.T) {
 	params := &stripe.PaymentIntentSearchParams{
 		SearchParams: stripe.SearchParams{
@@ -1932,6 +1954,14 @@ func TestSetupIntentConfirm(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
+func TestSetupIntentVerifyMicrodeposits2(t *testing.T) {
+	params := &stripe.SetupIntentVerifyMicrodepositsParams{
+		Amounts: []*int64{stripe.Int64(32), stripe.Int64(45)},
+	}
+	result, _ := setupintent.VerifyMicrodeposits("seti_xxxxxxxxxxxxx", params)
+	assert.NotNil(t, result)
+}
+
 func TestShippingRateList2(t *testing.T) {
 	params := &stripe.ShippingRateListParams{}
 	params.Limit = stripe.Int64(3)
@@ -2067,7 +2097,7 @@ func TestSubscriptionScheduleList(t *testing.T) {
 func TestSubscriptionScheduleCreate(t *testing.T) {
 	params := &stripe.SubscriptionScheduleParams{
 		Customer:    stripe.String("cus_xxxxxxxxxxxxx"),
-		StartDate:   stripe.Int64(1652909005),
+		StartDate:   stripe.Int64(1676070661),
 		EndBehavior: stripe.String(string(stripe.SubscriptionScheduleEndBehaviorRelease)),
 		Phases: []*stripe.SubscriptionSchedulePhaseParams{
 			&stripe.SubscriptionSchedulePhaseParams{
@@ -2268,8 +2298,9 @@ func TestTerminalLocationCreate(t *testing.T) {
 		Address: &stripe.AddressParams{
 			Line1:      stripe.String("1234 Main Street"),
 			City:       stripe.String("San Francisco"),
-			Country:    stripe.String("US"),
 			PostalCode: stripe.String("94111"),
+			State:      stripe.String("CA"),
+			Country:    stripe.String("US"),
 		},
 	}
 	result, _ := terminal_location.New(params)
@@ -2343,6 +2374,15 @@ func TestTerminalReaderProcessPaymentIntent(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
+func TestTerminalReaderProcessSetupIntent(t *testing.T) {
+	params := &stripe.TerminalReaderProcessSetupIntentParams{
+		SetupIntent:              stripe.String("seti_xxxxxxxxxxxxx"),
+		CustomerConsentCollected: stripe.Bool(true),
+	}
+	result, _ := terminal_reader.ProcessSetupIntent("tmr_xxxxxxxxxxxxx", params)
+	assert.NotNil(t, result)
+}
+
 func TestTestHelpersTestClockList2(t *testing.T) {
 	params := &stripe.TestHelpersTestClockListParams{}
 	params.Limit = stripe.Int64(3)
@@ -2373,7 +2413,7 @@ func TestTestHelpersTestClockRetrieve2(t *testing.T) {
 
 func TestTestHelpersTestClockAdvance2(t *testing.T) {
 	params := &stripe.TestHelpersTestClockAdvanceParams{
-		FrozenTime: stripe.Int64(1652390605),
+		FrozenTime: stripe.Int64(1675552261),
 	}
 	result, _ := testhelpers_testclock.Advance("clock_xxxxxxxxxxxxx", params)
 	assert.NotNil(t, result)
@@ -2555,19 +2595,6 @@ func TestTreasuryFinancialAccountRetrieveFeatures(t *testing.T) {
 	assert.NotNil(t, result)
 }
 
-func TestTreasuryFinancialAccountUpdateFeatures(t *testing.T) {
-	params := &stripe.TreasuryFinancialAccountUpdateFeaturesParams{
-		CardIssuing: &stripe.TreasuryFinancialAccountUpdateFeaturesCardIssuingParams{
-			Requested: stripe.Bool(false),
-		},
-	}
-	result, _ := treasury_financialaccount.UpdateFeatures(
-		"fa_xxxxxxxxxxxxx",
-		params,
-	)
-	assert.NotNil(t, result)
-}
-
 func TestTreasuryInboundTransferList(t *testing.T) {
 	params := &stripe.TreasuryInboundTransferListParams{
 		FinancialAccount: stripe.String("fa_xxxxxxxxxxxxx"),
@@ -2617,7 +2644,7 @@ func TestTreasuryOutboundPaymentCreate(t *testing.T) {
 		FinancialAccount:         stripe.String("fa_xxxxxxxxxxxxx"),
 		Amount:                   stripe.Int64(10000),
 		Currency:                 stripe.String(string(stripe.CurrencyUSD)),
-		Customer:                 stripe.String("cu_xxxxxxxxxxxxx"),
+		Customer:                 stripe.String("cus_xxxxxxxxxxxxx"),
 		DestinationPaymentMethod: stripe.String("pm_xxxxxxxxxxxxx"),
 		Description:              stripe.String("OutboundPayment to a 3rd party"),
 	}
@@ -2627,13 +2654,13 @@ func TestTreasuryOutboundPaymentCreate(t *testing.T) {
 
 func TestTreasuryOutboundPaymentRetrieve(t *testing.T) {
 	params := &stripe.TreasuryOutboundPaymentParams{}
-	result, _ := treasury_outboundpayment.Get("obp_xxxxxxxxxxxxx", params)
+	result, _ := treasury_outboundpayment.Get("bot_xxxxxxxxxxxxx", params)
 	assert.NotNil(t, result)
 }
 
 func TestTreasuryOutboundPaymentCancel(t *testing.T) {
 	params := &stripe.TreasuryOutboundPaymentCancelParams{}
-	result, _ := treasury_outboundpayment.Cancel("obp_xxxxxxxxxxxxx", params)
+	result, _ := treasury_outboundpayment.Cancel("bot_xxxxxxxxxxxxx", params)
 	assert.NotNil(t, result)
 }
 
diff --git a/form/form_test.go b/form/form_test.go
index 5e152d97..66c7ecb9 100644
--- a/form/form_test.go
+++ b/form/form_test.go
@@ -379,6 +379,43 @@ func TestAppendToPrefixed(t *testing.T) {
 	assert.Equal(t, []string{"foo"}, form.Get("prefix[string]"))
 }
 
+func TestEncode(t *testing.T) {
+	form := &Values{}
+	form.Add("foo", "bar")
+	form.Add("foo[bar]", "baz")
+	assert.Equal(t, "foo=bar&foo[bar]=baz", form.Encode())
+}
+
+func TestEncodeDeterministically(t *testing.T) {
+	data := map[string]string{
+		"first":  "foo",
+		"second": "bar",
+	}
+	initialForm := &Values{}
+	AppendTo(initialForm, data)
+	encoded := initialForm.Encode()
+
+	for i := 0; i < 100; i++ {
+		form := &Values{}
+		AppendTo(form, data)
+		assert.Equal(t, encoded, form.Encode(), "iteration %d", i)
+	}
+}
+
+func TestEncodeMapNonStringKey(t *testing.T) {
+	// Disable strict mode for this test, so the non-string key is ignored.
+	Strict = false
+	defer func() {
+		Strict = true
+	}()
+
+	form := &Values{}
+	assert.NotPanics(t, func() {
+		AppendTo(form, map[int]string{1: "foo"})
+	})
+	assert.Len(t, form.values, 0)
+}
+
 func TestFormatKey(t *testing.T) {
 	assert.Equal(t, "param", FormatKey([]string{"param"}))
 	assert.Equal(t, "param[key]", FormatKey([]string{"param", "key"}))