diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 57726a4..b429f96 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.65.0"
+ ".": "0.66.0"
}
\ No newline at end of file
diff --git a/.stats.yml b/.stats.yml
index dcde96d..5ad6924 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 117
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-08c2d6a44f4cdcbfb6803a3043fdc1a3e33911dec4652cb3a870f01bc584421f.yml
-openapi_spec_hash: c816491451347eb93b793cddf6a78648
-config_hash: 9e45c27425021d49b5391f5cc980b046
+configured_endpoints: 119
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-e66c3f8aedccc39104386a3ec619f3fdcef7e8b00d9e5aa82e414a1b387351c2.yml
+openapi_spec_hash: afeddf18ebc3da1521b3e6f6739411fa
+config_hash: 80eef1b592110714ea55cd26c470fabb
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a63adb2..8510537 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,14 @@
# Changelog
+## 0.66.0 (2026-06-10)
+
+Full Changelog: [v0.65.0...v0.66.0](https://github.com/kernel/kernel-go-sdk/compare/v0.65.0...v0.66.0)
+
+### Features
+
+* Add org-level default per-project concurrency cap ([da8ea41](https://github.com/kernel/kernel-go-sdk/commit/da8ea416e8e2d00f38c7a811cbdd515053b37f89))
+* Support updating browser session name and tags via PATCH ([f530bfb](https://github.com/kernel/kernel-go-sdk/commit/f530bfb8b6822f3774eee1fb7bbe81fc4ce9fa41))
+
## 0.65.0 (2026-06-08)
Full Changelog: [v0.64.0...v0.65.0](https://github.com/kernel/kernel-go-sdk/compare/v0.64.0...v0.65.0)
diff --git a/README.md b/README.md
index 1530141..de19a92 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ Or to pin the version:
```sh
-go get -u 'github.com/kernel/kernel-go-sdk@v0.65.0'
+go get -u 'github.com/kernel/kernel-go-sdk@v0.66.0'
```
diff --git a/api.md b/api.md
index 9eb99c1..f4a6c67 100644
--- a/api.md
+++ b/api.md
@@ -400,6 +400,23 @@ Methods:
- client.Projects.Limits.Get(ctx context.Context, id string) (\*kernel.ProjectLimits, error)
- client.Projects.Limits.Update(ctx context.Context, id string, body kernel.ProjectLimitUpdateParams) (\*kernel.ProjectLimits, error)
+# Organization
+
+## Limits
+
+Params Types:
+
+- kernel.UpdateOrgLimitsRequestParam
+
+Response Types:
+
+- kernel.OrgLimits
+
+Methods:
+
+- client.Organization.Limits.Get(ctx context.Context) (\*kernel.OrgLimits, error)
+- client.Organization.Limits.Update(ctx context.Context, body kernel.OrganizationLimitUpdateParams) (\*kernel.OrgLimits, error)
+
# APIKeys
Response Types:
diff --git a/browser.go b/browser.go
index cfb8067..cc42ba4 100644
--- a/browser.go
+++ b/browser.go
@@ -676,8 +676,8 @@ type BrowserNewParams struct {
// view.
KioskMode param.Opt[bool] `json:"kiosk_mode,omitzero"`
// Optional human-readable name for the browser session, used to find it later in
- // the dashboard. Must be unique among active sessions within the project. Set at
- // creation time only.
+ // the dashboard. Must be unique among active sessions within the project. Can be
+ // changed later via PATCH /browsers/{id_or_name}.
Name param.Opt[string] `json:"name,omitzero"`
// Optional proxy to associate to the browser session. Must reference a proxy
// belonging to the caller's org.
@@ -713,7 +713,8 @@ type BrowserNewParams struct {
// Profiles must be created beforehand.
Profile shared.BrowserProfileParam `json:"profile,omitzero"`
// Optional user-defined key-value tags for the browser session, used to find and
- // group sessions later. Set at creation time only. Up to 50 pairs.
+ // group sessions later. Can be changed later via PATCH /browsers/{id_or_name}. Up
+ // to 50 pairs.
Tags Tags `json:"tags,omitzero"`
// Initial browser window size in pixels with optional refresh rate. If omitted,
// image defaults apply (1920x1080@25). For GPU images, the default is
@@ -781,6 +782,10 @@ func (r BrowserGetParams) URLQuery() (v url.Values, err error) {
}
type BrowserUpdateParams struct {
+ // Human-readable name for the browser session. Omit to leave unchanged, set to an
+ // empty string to clear the name. When set, must be unique among active sessions
+ // within the project.
+ Name param.Opt[string] `json:"name,omitzero"`
// ID of the proxy to use. Omit to leave unchanged, set to empty string to remove
// proxy.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
@@ -796,6 +801,10 @@ type BrowserUpdateParams struct {
// Profile to load into the browser session. Only allowed if the session does not
// already have a profile loaded.
Profile shared.BrowserProfileParam `json:"profile,omitzero"`
+ // User-defined key-value tags for the browser session. Omit to leave unchanged.
+ // Provide a map to replace the entire tag set (full replace, not a merge). Set to
+ // an empty object ({}) to clear all tags. Up to 50 pairs.
+ Tags Tags `json:"tags,omitzero"`
// Viewport configuration to apply to the browser session.
Viewport BrowserUpdateParamsViewport `json:"viewport,omitzero"`
paramObj
diff --git a/browser_test.go b/browser_test.go
index 245bdea..06ffaa3 100644
--- a/browser_test.go
+++ b/browser_test.go
@@ -149,12 +149,17 @@ func TestBrowserUpdateWithOptionalParams(t *testing.T) {
"htzv5orfit78e1m2biiifpbv",
kernel.BrowserUpdateParams{
DisableDefaultProxy: kernel.Bool(true),
+ Name: kernel.String("checkout-flow-1"),
Profile: shared.BrowserProfileParam{
ID: kernel.String("id"),
Name: kernel.String("name"),
SaveChanges: kernel.Bool(true),
},
ProxyID: kernel.String("proxy_id"),
+ Tags: kernel.Tags{
+ "team": "backend",
+ "env": "staging",
+ },
Telemetry: kernel.BrowserUpdateParamsTelemetry{
Browser: kernel.BrowserTelemetryCategoriesConfigParam{
Captcha: kernel.BrowserTelemetryCategoryConfigParam{
diff --git a/client.go b/client.go
index 5060e16..9f7b615 100644
--- a/client.go
+++ b/client.go
@@ -41,7 +41,8 @@ type Client struct {
// Create and manage credentials for authentication.
Credentials CredentialService
// Create and manage projects for resource isolation within an organization.
- Projects ProjectService
+ Projects ProjectService
+ Organization OrganizationService
// Create and manage API keys for organization and project-scoped access.
APIKeys APIKeyService
// Configure external credential providers like 1Password.
@@ -94,6 +95,7 @@ func NewClient(opts ...option.RequestOption) (r Client) {
r.BrowserPools = NewBrowserPoolService(opts...)
r.Credentials = NewCredentialService(opts...)
r.Projects = NewProjectService(opts...)
+ r.Organization = NewOrganizationService(opts...)
r.APIKeys = NewAPIKeyService(opts...)
r.CredentialProviders = NewCredentialProviderService(opts...)
diff --git a/internal/version.go b/internal/version.go
index 5d1e9f9..0ccbf2a 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.65.0" // x-release-please-version
+const PackageVersion = "0.66.0" // x-release-please-version
diff --git a/organization.go b/organization.go
new file mode 100644
index 0000000..39b22ce
--- /dev/null
+++ b/organization.go
@@ -0,0 +1,29 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "github.com/kernel/kernel-go-sdk/option"
+)
+
+// OrganizationService contains methods and other services that help with
+// interacting with the kernel 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 [NewOrganizationService] method instead.
+type OrganizationService struct {
+ Options []option.RequestOption
+ // Read and manage organization-level limits.
+ Limits OrganizationLimitService
+}
+
+// NewOrganizationService 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 NewOrganizationService(opts ...option.RequestOption) (r OrganizationService) {
+ r = OrganizationService{}
+ r.Options = opts
+ r.Limits = NewOrganizationLimitService(opts...)
+ return
+}
diff --git a/organizationlimit.go b/organizationlimit.go
new file mode 100644
index 0000000..0860565
--- /dev/null
+++ b/organizationlimit.go
@@ -0,0 +1,110 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel
+
+import (
+ "context"
+ "net/http"
+ "slices"
+
+ "github.com/kernel/kernel-go-sdk/internal/apijson"
+ shimjson "github.com/kernel/kernel-go-sdk/internal/encoding/json"
+ "github.com/kernel/kernel-go-sdk/internal/requestconfig"
+ "github.com/kernel/kernel-go-sdk/option"
+ "github.com/kernel/kernel-go-sdk/packages/param"
+ "github.com/kernel/kernel-go-sdk/packages/respjson"
+)
+
+// Read and manage organization-level limits.
+//
+// OrganizationLimitService contains methods and other services that help with
+// interacting with the kernel 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 [NewOrganizationLimitService] method instead.
+type OrganizationLimitService struct {
+ Options []option.RequestOption
+}
+
+// NewOrganizationLimitService 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 NewOrganizationLimitService(opts ...option.RequestOption) (r OrganizationLimitService) {
+ r = OrganizationLimitService{}
+ r.Options = opts
+ return
+}
+
+// Get the organization's concurrent session ceiling and the default per-project
+// concurrency cap applied to projects without an explicit override.
+func (r *OrganizationLimitService) Get(ctx context.Context, opts ...option.RequestOption) (res *OrgLimits, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "org/limits"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
+ return res, err
+}
+
+// Set the default per-project concurrency cap applied to projects without an
+// explicit override. Set the value to 0 to remove the default; omit to leave it
+// unchanged. The default cannot exceed the organization's concurrent session
+// ceiling.
+func (r *OrganizationLimitService) Update(ctx context.Context, body OrganizationLimitUpdateParams, opts ...option.RequestOption) (res *OrgLimits, err error) {
+ opts = slices.Concat(r.Options, opts)
+ path := "org/limits"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...)
+ return res, err
+}
+
+type OrgLimits struct {
+ // Default maximum concurrent browser sessions applied to every project that has no
+ // explicit per-project override. Null means no org-level default, so such projects
+ // are uncapped (only the org-wide limit applies). Applies to existing and newly
+ // created projects.
+ DefaultProjectMaxConcurrentSessions int64 `json:"default_project_max_concurrent_sessions" api:"nullable"`
+ // The organization's effective concurrent browser session ceiling, from its plan
+ // or an override. Read-only and shared across all projects in the org; a
+ // per-project default cannot exceed it.
+ MaxConcurrentSessions int64 `json:"max_concurrent_sessions"`
+ // JSON contains metadata for fields, check presence with [respjson.Field.Valid].
+ JSON struct {
+ DefaultProjectMaxConcurrentSessions respjson.Field
+ MaxConcurrentSessions respjson.Field
+ ExtraFields map[string]respjson.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r OrgLimits) RawJSON() string { return r.JSON.raw }
+func (r *OrgLimits) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type UpdateOrgLimitsRequestParam struct {
+ // Default maximum concurrent browser sessions for projects without an explicit
+ // override. Set to 0 to remove the default; omit to leave unchanged. Cannot exceed
+ // the organization's concurrent session ceiling.
+ DefaultProjectMaxConcurrentSessions param.Opt[int64] `json:"default_project_max_concurrent_sessions,omitzero"`
+ paramObj
+}
+
+func (r UpdateOrgLimitsRequestParam) MarshalJSON() (data []byte, err error) {
+ type shadow UpdateOrgLimitsRequestParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+func (r *UpdateOrgLimitsRequestParam) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+type OrganizationLimitUpdateParams struct {
+ UpdateOrgLimitsRequest UpdateOrgLimitsRequestParam
+ paramObj
+}
+
+func (r OrganizationLimitUpdateParams) MarshalJSON() (data []byte, err error) {
+ return shimjson.Marshal(r.UpdateOrgLimitsRequest)
+}
+func (r *OrganizationLimitUpdateParams) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
diff --git a/organizationlimit_test.go b/organizationlimit_test.go
new file mode 100644
index 0000000..b52399e
--- /dev/null
+++ b/organizationlimit_test.go
@@ -0,0 +1,64 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+package kernel_test
+
+import (
+ "context"
+ "errors"
+ "os"
+ "testing"
+
+ "github.com/kernel/kernel-go-sdk"
+ "github.com/kernel/kernel-go-sdk/internal/testutil"
+ "github.com/kernel/kernel-go-sdk/option"
+)
+
+func TestOrganizationLimitGet(t *testing.T) {
+ t.Skip("Mock server tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Organization.Limits.Get(context.TODO())
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
+
+func TestOrganizationLimitUpdateWithOptionalParams(t *testing.T) {
+ t.Skip("Mock server tests are disabled")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := kernel.NewClient(
+ option.WithBaseURL(baseURL),
+ option.WithAPIKey("My API Key"),
+ )
+ _, err := client.Organization.Limits.Update(context.TODO(), kernel.OrganizationLimitUpdateParams{
+ UpdateOrgLimitsRequest: kernel.UpdateOrgLimitsRequestParam{
+ DefaultProjectMaxConcurrentSessions: kernel.Int(0),
+ },
+ })
+ if err != nil {
+ var apierr *kernel.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}