From 3e66239fb546d493ce19ff52a583aac447c40edb Mon Sep 17 00:00:00 2001 From: "workos-sdk-automation[bot]" <255426317+workos-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:28:27 +0000 Subject: [PATCH 1/5] feat(agents): Add parameter `AgentsSessions.list.organization_id` --- .../DataIntegrationsListResponseData.php | 4 ++-- tests/Fixtures/list_authkit_oauth_resource.json | 16 ++++++++++++++++ tests/Fixtures/list_data_integration.json | 1 + 3 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 tests/Fixtures/list_authkit_oauth_resource.json diff --git a/lib/Resource/DataIntegrationsListResponseData.php b/lib/Resource/DataIntegrationsListResponseData.php index b7957cdd..3ec4770d 100644 --- a/lib/Resource/DataIntegrationsListResponseData.php +++ b/lib/Resource/DataIntegrationsListResponseData.php @@ -36,10 +36,10 @@ public function __construct( public string $createdAt, /** The timestamp when the provider was last updated. */ public string $updatedAt, - /** The user's [connected account](https://workos.com/docs/reference/pipes/connected-account) for this provider, or `null` if the user has not connected. */ + /** The user's compatibility [connected account](https://workos.com/docs/reference/pipes/connected-account) for this provider, or `null` when the compatibility slot is empty. This legacy field never selects a standard connection. */ public ?DataIntegrationsListResponseDataConnectedAccount $connectedAccount, /** - * The user's connected accounts for this provider in the requested ownership context. + * The user's connected accounts for this provider in the requested ownership context. This contains only the compatibility connection unless `supports_multiple_connections` is `true`. * @var array<\WorkOS\Resource\DataIntegrationsListResponseDataConnectedAccount> */ public array $connectedAccounts, diff --git a/tests/Fixtures/list_authkit_oauth_resource.json b/tests/Fixtures/list_authkit_oauth_resource.json new file mode 100644 index 00000000..4d79551c --- /dev/null +++ b/tests/Fixtures/list_authkit_oauth_resource.json @@ -0,0 +1,16 @@ +{ + "data": [ + { + "object": "authkit_oauth_resource", + "id": "authkit_oauth_resource_01EHZNVPK3SFK441A1RGBFSHRT", + "uri": "https://api.example.com", + "default": false, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" + } + ], + "list_metadata": { + "before": null, + "after": null + } +} diff --git a/tests/Fixtures/list_data_integration.json b/tests/Fixtures/list_data_integration.json index d41b44b8..b6860c1b 100644 --- a/tests/Fixtures/list_data_integration.json +++ b/tests/Fixtures/list_data_integration.json @@ -5,6 +5,7 @@ "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", "slug": "github", "integration_type": "github", + "ownership": "user", "description": "Production GitHub app", "enabled": true, "state": "valid", From ac6690efd5ee73a71a322fd93c5eac24ca9d0467 Mon Sep 17 00:00:00 2001 From: "workos-sdk-automation[bot]" <255426317+workos-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:28:27 +0000 Subject: [PATCH 2/5] feat(pipes): Update Pipes API surface --- .../DataIntegrationsGetUserTokenRequest.php | 12 +- lib/Resource/PipesOwnership.php | 13 ++ lib/Service/Pipes.php | 149 ++++++++++++++++-- lib/Service/UserManagement.php | 80 ++++++++++ ...a_integrations_get_user_token_request.json | 4 +- tests/Service/PipesTest.php | 40 ++++- tests/Service/UserManagementTest.php | 46 +++++- 7 files changed, 323 insertions(+), 21 deletions(-) create mode 100644 lib/Resource/PipesOwnership.php diff --git a/lib/Resource/DataIntegrationsGetUserTokenRequest.php b/lib/Resource/DataIntegrationsGetUserTokenRequest.php index f9a0ec8f..463c8096 100644 --- a/lib/Resource/DataIntegrationsGetUserTokenRequest.php +++ b/lib/Resource/DataIntegrationsGetUserTokenRequest.php @@ -11,12 +11,16 @@ use JsonSerializableTrait; public function __construct( - /** A [User](https://workos.com/docs/reference/authkit/user) identifier. */ + /** A [User](https://workos.com/docs/reference/authkit/user) identifier. When `connection_owner` is `organization`, this is the user the credentials are vended on behalf of; they must be an active member of the organization. */ public string $userId, - /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. */ + /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. */ public ?string $organizationId = null, /** A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select a specific connection when the user has several for this provider. */ public ?string $connectedAccountId = null, + /** Which connection to vend from. `user` (the default) vends the user's own connection and requires `user_id`. `organization` vends the organization's shared connection and requires `organization_id`. */ + public ?PipesOwnership $connectionOwner = null, + /** Set to `true` to use the plural connection contract. If no `connected_account_id` is supplied and several connections match, the request returns `account_selection_required`. When omitted or `false`, only the compatibility connection is considered. */ + public ?bool $supportsMultipleConnections = null, ) { } @@ -26,6 +30,8 @@ public static function fromArray(array $data): self userId: $data['user_id'], organizationId: $data['organization_id'] ?? null, connectedAccountId: $data['connected_account_id'] ?? null, + connectionOwner: isset($data['connection_owner']) ? PipesOwnership::from($data['connection_owner']) : null, + supportsMultipleConnections: $data['supports_multiple_connections'] ?? null, ); } @@ -35,6 +41,8 @@ public function toArray(): array 'user_id' => $this->userId, 'organization_id' => $this->organizationId, 'connected_account_id' => $this->connectedAccountId, + 'connection_owner' => $this->connectionOwner?->value, + 'supports_multiple_connections' => $this->supportsMultipleConnections, ]; } } diff --git a/lib/Resource/PipesOwnership.php b/lib/Resource/PipesOwnership.php new file mode 100644 index 00000000..7404be53 --- /dev/null +++ b/lib/Resource/PipesOwnership.php @@ -0,0 +1,13 @@ + * @throws \WorkOS\Exception\WorkOSException */ @@ -36,6 +37,7 @@ public function listDataIntegrations( ?string $after = null, ?int $limit = null, \WorkOS\Resource\PaginationOrder $order = \WorkOS\Resource\PaginationOrder::Desc, + ?\WorkOS\Resource\PipesOwnership $ownership = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\PaginatedResponse { $query = array_filter([ @@ -43,6 +45,7 @@ public function listDataIntegrations( 'after' => $after, 'limit' => $limit, 'order' => $order->value, + 'ownership' => $ownership?->value, ], fn ($v) => $v !== null); return $this->client->requestPage( method: 'GET', @@ -56,8 +59,9 @@ public function listDataIntegrations( /** * Create a data integration * - * Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials or `organization` to have each organization supply its own. Set `auth_methods` to `["api_key"]` to create an API key integration; you may optionally supply an `api_key` block to install a first tenant in the same call. Set `auth_methods` to `["client_credentials"]` to create a client-credentials integration; client credentials are installed per-tenant afterwards. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition. + * Creates a data integration for a provider. Set `credentials.type` to `custom` to use your own OAuth app credentials or `organization` to have each organization supply its own. Set `auth_methods` to `["api_key"]` to create an API key integration; you may optionally supply an `api_key` block to install a first tenant in the same call. Set `auth_methods` to `["client_credentials"]` to create a client-credentials integration; client credentials are installed per-tenant afterwards. Set `ownership` to `organization` to create the integration organizations connect to instead of the default user-owned one; a provider may have one of each. For a built-in provider, pass its slug as `provider`. For a custom provider, pass a new slug plus a `custom_provider` definition, or the slug of an existing custom provider (without `custom_provider`) to add the other ownership. * @param string $provider The provider to create a Data Integration for. For a built-in provider use its slug (e.g. `github`, `slack`). For a custom provider, this is the new provider slug and `custom_provider` must be supplied. A custom provider slug cannot shadow an existing global provider slug. + * @param \WorkOS\Resource\PipesOwnership|null $ownership Who owns the Data Integration. `user` (the default) creates the integration users connect their own accounts to; `organization` creates the root organizations connect to. Ownership is fixed at creation, and one integration of each ownership may exist per provider. Independent of `credentials.type`. * @param string|null $description An optional description of the Data Integration. * @param bool|null $enabled Whether the Data Integration is enabled. Defaults to `false`. * @param array|null $scopes The OAuth scopes to request for the Data Integration. Defaults to the provider's configured scopes when omitted. @@ -71,6 +75,7 @@ public function listDataIntegrations( */ public function createDataIntegration( string $provider, + ?\WorkOS\Resource\PipesOwnership $ownership = null, ?string $description = null, ?bool $enabled = null, ?array $scopes = null, @@ -83,6 +88,7 @@ public function createDataIntegration( ): \WorkOS\Resource\DataIntegration { $body = array_filter([ 'provider' => $provider, + 'ownership' => $ownership?->value, 'description' => $description, 'enabled' => $enabled, 'scopes' => $scopes, @@ -104,7 +110,7 @@ public function createDataIntegration( /** * Get a data integration * - * Retrieves a data integration by its slug. + * Retrieves the user-owned data integration by its slug. * @param string $slug The slug identifier of the data integration. * @return \WorkOS\Resource\DataIntegration * @throws \WorkOS\Exception\WorkOSException @@ -124,7 +130,7 @@ public function getDataIntegration( /** * Update a data integration * - * Updates the description, enabled state, or custom credentials of a data integration. For custom providers, `custom_provider` updates the OAuth definition. + * Updates the description, enabled state, or custom credentials of the user-owned data integration. For custom providers, `custom_provider` updates the OAuth definition. * @param string $slug The slug identifier of the data integration. * @param string|null $description An optional description of the Data Integration. * @param bool|null $enabled Whether the Data Integration is enabled. @@ -165,7 +171,7 @@ public function updateDataIntegration( /** * Delete a data integration * - * Deletes a data integration and all of its connected installations. For a custom provider, also deletes the custom provider definition. + * Deletes the user-owned data integration and all of its connected installations. For a custom provider, the provider definition is deleted once no organization-owned root references it either. * @param string $slug The slug identifier of the data integration. * @return void * @throws \WorkOS\Exception\WorkOSException @@ -184,10 +190,12 @@ public function deleteDataIntegration( /** * Upsert an API key for a connected account * - * Creates or updates an API-key-based installation for the specified integration and user. If an installation already exists, the stored API key is rotated to the new value. + * Creates or updates an API-key-based installation for the specified integration, owned by the user or, when `connection_owner` is `organization`, shared by the organization. If an installation already exists, the stored API key is rotated to the new value. * @param string $slug The identifier of the integration. * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. - * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. + * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. + * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to rotate a specific existing connection. + * @param \WorkOS\Resource\PipesOwnership|null $connectionOwner Whose connection to create or rotate. `user` (the default) addresses the connection owned by `user_id`. `organization` addresses the connection shared by every member of `organization_id`; `user_id` then identifies the member performing the request and must be an active member of the organization. * @param string $secret The API key secret to store for this integration. * @return \WorkOS\Resource\ConnectedAccount * @throws \WorkOS\Exception\WorkOSException @@ -197,11 +205,15 @@ public function updateDataIntegrationApiKey( string $userId, string $secret, ?string $organizationId = null, + ?string $connectedAccountId = null, + ?\WorkOS\Resource\PipesOwnership $connectionOwner = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\ConnectedAccount { $body = array_filter([ 'user_id' => $userId, 'organization_id' => $organizationId, + 'connected_account_id' => $connectedAccountId, + 'connection_owner' => $connectionOwner?->value, 'secret' => $secret, ], fn ($v) => $v !== null); $response = $this->client->request( @@ -251,10 +263,12 @@ public function authorizeDataIntegration( /** * Upsert client credentials for a connected account * - * Creates or updates a client-credentials-based installation for the specified integration and user. If an installation already exists, the stored client credentials are rotated to the new values. + * Creates or updates a client-credentials-based installation for the specified integration, owned by the user or, when `connection_owner` is `organization`, shared by the organization. If an installation already exists, the stored client credentials are rotated to the new values. * @param string $slug The identifier of the integration. * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. - * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. + * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. + * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to rotate a specific existing connection. + * @param \WorkOS\Resource\PipesOwnership|null $connectionOwner Whose connection to create or rotate. `user` (the default) addresses the connection owned by `user_id`. `organization` addresses the connection shared by every member of `organization_id`; `user_id` then identifies the member performing the request and must be an active member of the organization. * @param string $clientId The OAuth client ID to store for this integration. * @param string $clientSecret The OAuth client secret to store for this integration. * @param array|null $config Provider-specific configuration values collected for this installation, keyed by the provider's config field descriptors. @@ -267,12 +281,16 @@ public function updateDataIntegrationClientCredentials( string $clientId, string $clientSecret, ?string $organizationId = null, + ?string $connectedAccountId = null, + ?\WorkOS\Resource\PipesOwnership $connectionOwner = null, ?array $config = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\ConnectedAccount { $body = array_filter([ 'user_id' => $userId, 'organization_id' => $organizationId, + 'connected_account_id' => $connectedAccountId, + 'connection_owner' => $connectionOwner?->value, 'client_id' => $clientId, 'client_secret' => $clientSecret, 'config' => $config, @@ -291,9 +309,11 @@ public function updateDataIntegrationClientCredentials( * * Returns credentials for a user's connected account. Branches on the installation's `auth_method`: OAuth installations return an access token (refreshed if needed); API-key installations return the stored secret. * @param string $slug The identifier of the integration. - * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. - * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. + * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. When `connection_owner` is `organization`, this is the user the credentials are vended on behalf of; they must be an active member of the organization. + * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select a specific connection when the user has several for this provider. + * @param \WorkOS\Resource\PipesOwnership|null $connectionOwner Which connection to vend from. `user` (the default) vends the user's own connection and requires `user_id`. `organization` vends the organization's shared connection and requires `organization_id`. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. If no `connected_account_id` is supplied and several connections match, the request returns `account_selection_required`. When omitted or `false`, only the compatibility connection is considered. * @return \WorkOS\Resource\DataIntegrationCredentialsResponse * @throws \WorkOS\Exception\WorkOSException */ @@ -302,12 +322,16 @@ public function createDataIntegrationCredential( string $userId, ?string $organizationId = null, ?string $connectedAccountId = null, + ?\WorkOS\Resource\PipesOwnership $connectionOwner = null, + ?bool $supportsMultipleConnections = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\DataIntegrationCredentialsResponse { $body = array_filter([ 'user_id' => $userId, 'organization_id' => $organizationId, 'connected_account_id' => $connectedAccountId, + 'connection_owner' => $connectionOwner?->value, + 'supports_multiple_connections' => $supportsMultipleConnections, ], fn ($v) => $v !== null); $response = $this->client->request( method: 'POST', @@ -318,14 +342,96 @@ public function createDataIntegrationCredential( return DataIntegrationCredentialsResponse::fromArray($response); } + /** + * Get an organization-owned data integration + * + * Retrieves the organization-owned data integration for a provider by its slug. The `/organization` suffix selects the environment-level organization-owned root for the provider; it does not name a particular organization. + * @param string $slug The slug identifier of the data integration. + * @return \WorkOS\Resource\DataIntegration + * @throws \WorkOS\Exception\WorkOSException + */ + public function listDataIntegrationOrganization( + string $slug, + ?\WorkOS\RequestOptions $options = null, + ): \WorkOS\Resource\DataIntegration { + $response = $this->client->request( + method: 'GET', + path: 'data-integrations/' . rawurlencode($slug) . '/organization', + options: $options, + ); + return DataIntegration::fromArray($response); + } + + /** + * Update an organization-owned data integration + * + * Updates the description, enabled state, or custom credentials of the organization-owned data integration for a provider. For custom providers, `custom_provider` updates the OAuth definition, which is shared with the user-owned root. The `/organization` suffix selects the environment-level organization-owned root for the provider; it does not name a particular organization. + * @param string $slug The slug identifier of the data integration. + * @param string|null $description An optional description of the Data Integration. + * @param bool|null $enabled Whether the Data Integration is enabled. + * @param array|null $scopes The OAuth scopes to request for the Data Integration. Pass `null` to reset to the provider's configured scopes. + * @param \WorkOS\Resource\DataIntegrationCredentialsInput|null $credentials New OAuth credentials for the Data Integration. When provided, rotates the stored client secret. Mutually exclusive with `api_key`. + * @param \WorkOS\Resource\ApiKeyInstallation|null $apiKey An API key to install or rotate for a tenant on an `api_key` integration. Upserts the tenant installation identified by `user_id` (and optional `organization_id`). + * @param \WorkOS\Resource\UpdateCustomProviderDefinition|null $customProvider Updates to a custom provider's OAuth definition. Only valid for custom-provider integrations. + * @return \WorkOS\Resource\DataIntegration + * @throws \WorkOS\Exception\WorkOSException + */ + public function updateDataIntegrationOrganization( + string $slug, + ?string $description = null, + ?bool $enabled = null, + ?array $scopes = null, + ?\WorkOS\Resource\DataIntegrationCredentialsInput $credentials = null, + ?\WorkOS\Resource\ApiKeyInstallation $apiKey = null, + ?\WorkOS\Resource\UpdateCustomProviderDefinition $customProvider = null, + ?\WorkOS\RequestOptions $options = null, + ): \WorkOS\Resource\DataIntegration { + $body = array_filter([ + 'description' => $description, + 'enabled' => $enabled, + 'scopes' => $scopes, + 'credentials' => $credentials, + 'api_key' => $apiKey, + 'custom_provider' => $customProvider, + ], fn ($v) => $v !== null); + $response = $this->client->request( + method: 'PUT', + path: 'data-integrations/' . rawurlencode($slug) . '/organization', + body: $body, + options: $options, + ); + return DataIntegration::fromArray($response); + } + + /** + * Delete an organization-owned data integration + * + * Deletes the organization-owned data integration for a provider and all of its connected installations. For a custom provider, the provider definition is deleted once no user-owned root references it either. The `/organization` suffix selects the environment-level organization-owned root for the provider; it does not name a particular organization. + * @param string $slug The slug identifier of the data integration. + * @return void + * @throws \WorkOS\Exception\WorkOSException + */ + public function deleteDataIntegrationOrganization( + string $slug, + ?\WorkOS\RequestOptions $options = null, + ): void { + $this->client->request( + method: 'DELETE', + path: 'data-integrations/' . rawurlencode($slug) . '/organization', + options: $options, + ); + } + /** * Get an access token for a connected account * * Fetches a valid OAuth access token for a user's connected account. WorkOS automatically handles token refresh, ensuring you always receive a valid, non-expired token. * @param string $provider The identifier of the integration. - * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. - * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. + * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. When `connection_owner` is `organization`, this is the user the credentials are vended on behalf of; they must be an active member of the organization. + * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select a specific connection when the user has several for this provider. + * @param \WorkOS\Resource\PipesOwnership|null $connectionOwner Which connection to vend from. `user` (the default) vends the user's own connection and requires `user_id`. `organization` vends the organization's shared connection and requires `organization_id`. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. If no `connected_account_id` is supplied and several connections match, the request returns `account_selection_required`. When omitted or `false`, only the compatibility connection is considered. * @return \WorkOS\Resource\DataIntegrationAccessTokenResponse * @throws \WorkOS\Exception\WorkOSException */ @@ -334,12 +440,16 @@ public function getAccessToken( string $userId, ?string $organizationId = null, ?string $connectedAccountId = null, + ?\WorkOS\Resource\PipesOwnership $connectionOwner = null, + ?bool $supportsMultipleConnections = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\DataIntegrationAccessTokenResponse { $body = array_filter([ 'user_id' => $userId, 'organization_id' => $organizationId, 'connected_account_id' => $connectedAccountId, + 'connection_owner' => $connectionOwner?->value, + 'supports_multiple_connections' => $supportsMultipleConnections, ], fn ($v) => $v !== null); $response = $this->client->request( method: 'POST', @@ -357,6 +467,7 @@ public function getAccessToken( * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. * @param string $slug The slug identifier of the provider (e.g., `github`, `slack`, `notion`). * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter if the connection is scoped to an organization. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. When omitted or `false`, only the compatibility connection is considered. * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select a specific connection when the user has several for this provider. * @return \WorkOS\Resource\ConnectedAccount * @throws \WorkOS\Exception\WorkOSException @@ -365,11 +476,13 @@ public function getUserConnectedAccount( string $userId, string $slug, ?string $organizationId = null, + ?bool $supportsMultipleConnections = null, ?string $connectedAccountId = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\ConnectedAccount { $query = array_filter([ 'organization_id' => $organizationId, + 'supports_multiple_connections' => $supportsMultipleConnections, 'connected_account_id' => $connectedAccountId, ], fn ($v) => $v !== null); $response = $this->client->request( @@ -435,6 +548,7 @@ public function createUserConnectedAccount( * @param array|null $scopes The OAuth scopes granted for this connection. * @param \WorkOS\Resource\PipeConnectedAccountState|null $state Explicitly set the state of the connected account. When omitted, the state is derived from the token combination provided. * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter if the connection is scoped to an organization. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. When omitted or `false`, only the compatibility connection is considered. * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select the connection to update. * @return \WorkOS\Resource\ConnectedAccount * @throws \WorkOS\Exception\WorkOSException @@ -448,6 +562,7 @@ public function updateUserConnectedAccount( ?array $scopes = null, ?\WorkOS\Resource\PipeConnectedAccountState $state = null, ?string $organizationId = null, + ?bool $supportsMultipleConnections = null, ?string $connectedAccountId = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\ConnectedAccount { @@ -470,10 +585,11 @@ public function updateUserConnectedAccount( /** * Delete a connected account * - * Disconnects WorkOS's account for the user, including removing any stored access and refresh tokens. The user will need to reauthorize if they want to reconnect. This does not revoke access on the provider side. + * Disconnects WorkOS's account for the user, including removing any stored access and refresh tokens. The user will need to reauthorize if they want to reconnect. Access is not revoked on the provider side, except for the WorkOS OAuth provider, whose underlying AuthKit grant is revoked. * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier. * @param string $slug The slug identifier of the provider (e.g., `github`, `slack`, `notion`). * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter if the connection is scoped to an organization. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. When omitted or `false`, only the compatibility connection is considered. * @param string|null $connectedAccountId A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select the connection to delete. * @return void * @throws \WorkOS\Exception\WorkOSException @@ -482,11 +598,13 @@ public function deleteUserConnectedAccount( string $userId, string $slug, ?string $organizationId = null, + ?bool $supportsMultipleConnections = null, ?string $connectedAccountId = null, ?\WorkOS\RequestOptions $options = null, ): void { $query = array_filter([ 'organization_id' => $organizationId, + 'supports_multiple_connections' => $supportsMultipleConnections, 'connected_account_id' => $connectedAccountId, ], fn ($v) => $v !== null); $this->client->request( @@ -503,16 +621,19 @@ public function deleteUserConnectedAccount( * Retrieves a list of available providers and the user's connection status for each. Returns all providers configured for your environment, along with the user's [connected account](https://workos.com/docs/reference/pipes/connected-account) information where applicable. * @param string $userId A [User](https://workos.com/docs/reference/authkit/user) identifier to list providers and connected accounts for. * @param string|null $organizationId An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to filter connections for a specific organization. + * @param bool|null $supportsMultipleConnections Set to `true` to use the plural connection contract. When omitted or `false`, only the compatibility connection is considered. * @return \WorkOS\Resource\DataIntegrationsListResponse * @throws \WorkOS\Exception\WorkOSException */ public function listUserDataProviders( string $userId, ?string $organizationId = null, + ?bool $supportsMultipleConnections = null, ?\WorkOS\RequestOptions $options = null, ): \WorkOS\Resource\DataIntegrationsListResponse { $query = array_filter([ 'organization_id' => $organizationId, + 'supports_multiple_connections' => $supportsMultipleConnections, ], fn ($v) => $v !== null); $response = $this->client->request( method: 'GET', diff --git a/lib/Service/UserManagement.php b/lib/Service/UserManagement.php index 65627db8..532aef70 100644 --- a/lib/Service/UserManagement.php +++ b/lib/Service/UserManagement.php @@ -7,6 +7,7 @@ namespace WorkOS\Service; use WorkOS\Resource\AuthenticateResponse; +use WorkOS\Resource\AuthkitOAuthResource; use WorkOS\Resource\AuthorizedConnectApplicationListData; use WorkOS\Resource\CORSOriginResponse; use WorkOS\Resource\DeviceAuthorizationResponse; @@ -647,6 +648,85 @@ public function revokeSession( return $response; } + /** + * List MCP resource indicators + * + * Lists the MCP resource indicators configured for an environment. + * @param string|null $before An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. + * @param string|null $after An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. + * @param int|null $limit Upper limit on the number of objects to return, between `1` and `100`. Defaults to 10. + * @param \WorkOS\Resource\PaginationOrder $order Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to "desc". + * @return \WorkOS\PaginatedResponse<\WorkOS\Resource\AuthkitOAuthResource> + * @throws \WorkOS\Exception\WorkOSException + */ + public function listAuthkitOAuthResources( + ?string $before = null, + ?string $after = null, + ?int $limit = null, + \WorkOS\Resource\PaginationOrder $order = \WorkOS\Resource\PaginationOrder::Desc, + ?\WorkOS\RequestOptions $options = null, + ): \WorkOS\PaginatedResponse { + $query = array_filter([ + 'before' => $before, + 'after' => $after, + 'limit' => $limit, + 'order' => $order->value, + ], fn ($v) => $v !== null); + return $this->client->requestPage( + method: 'GET', + path: 'user_management/authkit_oauth_resources', + query: $query, + modelClass: AuthkitOAuthResource::class, + options: $options, + ); + } + + /** + * Create an MCP resource indicator + * + * Adds an MCP resource indicator (RFC 8707) to an environment, leaving any others in place. + * @param string $uri The resource URI. May be a wildcard pattern with a single `*` in the leftmost hostname label, where enabled for the environment. + * @param bool|null $default Whether the resource being created becomes the environment default, clearing any previous default. Applies at creation only — this API has no update endpoint yet, so changing the default on an existing resource is done from the dashboard. A wildcard pattern cannot be the default. + * @return \WorkOS\Resource\AuthkitOAuthResource + * @throws \WorkOS\Exception\WorkOSException + */ + public function createAuthkitOAuthResource( + string $uri, + ?bool $default = null, + ?\WorkOS\RequestOptions $options = null, + ): \WorkOS\Resource\AuthkitOAuthResource { + $body = array_filter([ + 'uri' => $uri, + 'default' => $default, + ], fn ($v) => $v !== null); + $response = $this->client->request( + method: 'POST', + path: 'user_management/authkit_oauth_resources', + body: $body, + options: $options, + ); + return AuthkitOAuthResource::fromArray($response); + } + + /** + * Delete an MCP resource indicator + * + * Removes an MCP resource indicator from an environment. Any application consents granted against it are removed too. + * @param string $id The ID of the MCP resource indicator to delete. + * @return void + * @throws \WorkOS\Exception\WorkOSException + */ + public function deleteAuthkitOAuthResource( + string $id, + ?\WorkOS\RequestOptions $options = null, + ): void { + $this->client->request( + method: 'DELETE', + path: 'user_management/authkit_oauth_resources/' . rawurlencode($id), + options: $options, + ); + } + /** * List CORS origins * diff --git a/tests/Fixtures/data_integrations_get_user_token_request.json b/tests/Fixtures/data_integrations_get_user_token_request.json index 66f0412e..9b96a12f 100644 --- a/tests/Fixtures/data_integrations_get_user_token_request.json +++ b/tests/Fixtures/data_integrations_get_user_token_request.json @@ -1,5 +1,7 @@ { "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", - "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT" + "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "connection_owner": "user", + "supports_multiple_connections": true } diff --git a/tests/Service/PipesTest.php b/tests/Service/PipesTest.php index 6fa26357..006b7fbd 100644 --- a/tests/Service/PipesTest.php +++ b/tests/Service/PipesTest.php @@ -17,7 +17,7 @@ public function testListDataIntegrations(): void { $fixture = $this->loadFixture('list_data_integration'); $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); - $result = $client->pipes()->listDataIntegrations(before: 'test_value', after: 'test_value', limit: 1, order: \WorkOS\Resource\PaginationOrder::Normal); + $result = $client->pipes()->listDataIntegrations(before: 'test_value', after: 'test_value', limit: 1, order: \WorkOS\Resource\PaginationOrder::Normal, ownership: \WorkOS\Resource\PipesOwnership::User); $this->assertInstanceOf(\WorkOS\PaginatedResponse::class, $result); $request = $this->getLastRequest(); $this->assertSame('GET', $request->getMethod()); @@ -27,6 +27,7 @@ public function testListDataIntegrations(): void $this->assertSame('test_value', $query['after']); $this->assertArrayHasKey('limit', $query); $this->assertSame('normal', $query['order']); + $this->assertSame('user', $query['ownership']); } public function testCreateDataIntegration(): void @@ -146,6 +147,43 @@ public function testCreateDataIntegrationCredential(): void $this->assertSame('test_value', $body['user_id']); } + public function testListDataIntegrationOrganization(): void + { + $fixture = $this->loadFixture('data_integration'); + $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); + $result = $client->pipes()->listDataIntegrationOrganization('test_slug'); + $this->assertInstanceOf(\WorkOS\Resource\DataIntegration::class, $result); + $this->assertSame($fixture['id'], $result->id); + $this->assertSame($fixture['slug'], $result->slug); + $this->assertIsArray($result->toArray()); + $request = $this->getLastRequest(); + $this->assertSame('GET', $request->getMethod()); + $this->assertStringEndsWith('data-integrations/test_slug/organization', $request->getUri()->getPath()); + } + + public function testUpdateDataIntegrationOrganization(): void + { + $fixture = $this->loadFixture('data_integration'); + $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); + $result = $client->pipes()->updateDataIntegrationOrganization('test_slug'); + $this->assertInstanceOf(\WorkOS\Resource\DataIntegration::class, $result); + $this->assertSame($fixture['id'], $result->id); + $this->assertSame($fixture['slug'], $result->slug); + $this->assertIsArray($result->toArray()); + $request = $this->getLastRequest(); + $this->assertSame('PUT', $request->getMethod()); + $this->assertStringEndsWith('data-integrations/test_slug/organization', $request->getUri()->getPath()); + } + + public function testDeleteDataIntegrationOrganization(): void + { + $client = $this->createMockClient([['status' => 204]]); + $client->pipes()->deleteDataIntegrationOrganization('test_slug'); + $request = $this->getLastRequest(); + $this->assertSame('DELETE', $request->getMethod()); + $this->assertStringEndsWith('data-integrations/test_slug/organization', $request->getUri()->getPath()); + } + public function testGetAccessToken(): void { $fixture = $this->loadFixture('data_integration_access_token_response'); diff --git a/tests/Service/UserManagementTest.php b/tests/Service/UserManagementTest.php index e5e755e4..1fbb8fd5 100644 --- a/tests/Service/UserManagementTest.php +++ b/tests/Service/UserManagementTest.php @@ -54,7 +54,6 @@ public function testCreateDevice(): void $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); $result = $client->userManagement()->createDevice(clientId: 'test_value'); $this->assertInstanceOf(\WorkOS\Resource\DeviceAuthorizationResponse::class, $result); - $this->assertSame($fixture['device_code'], $result->deviceCode); $this->assertIsArray($result->toArray()); $request = $this->getLastRequest(); $this->assertSame('POST', $request->getMethod()); @@ -114,6 +113,47 @@ public function testRevokeSession(): void $this->assertStringEndsWith('user_management/sessions/revoke', $request->getUri()->getPath()); } + public function testListAuthkitOAuthResources(): void + { + $fixture = $this->loadFixture('list_authkit_oauth_resource'); + $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); + $result = $client->userManagement()->listAuthkitOAuthResources(before: 'test_value', after: 'test_value', limit: 1, order: \WorkOS\Resource\PaginationOrder::Normal); + $this->assertInstanceOf(\WorkOS\PaginatedResponse::class, $result); + $request = $this->getLastRequest(); + $this->assertSame('GET', $request->getMethod()); + $this->assertStringEndsWith('user_management/authkit_oauth_resources', $request->getUri()->getPath()); + parse_str($request->getUri()->getQuery(), $query); + $this->assertSame('test_value', $query['before']); + $this->assertSame('test_value', $query['after']); + $this->assertArrayHasKey('limit', $query); + $this->assertSame('normal', $query['order']); + } + + public function testCreateAuthkitOAuthResource(): void + { + $fixture = $this->loadFixture('authkit_oauth_resource'); + $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); + $result = $client->userManagement()->createAuthkitOAuthResource(uri: 'test_value'); + $this->assertInstanceOf(\WorkOS\Resource\AuthkitOAuthResource::class, $result); + $this->assertSame($fixture['id'], $result->id); + $this->assertSame($fixture['uri'], $result->uri); + $this->assertIsArray($result->toArray()); + $request = $this->getLastRequest(); + $this->assertSame('POST', $request->getMethod()); + $this->assertStringEndsWith('user_management/authkit_oauth_resources', $request->getUri()->getPath()); + $body = json_decode((string) $request->getBody(), true); + $this->assertSame('test_value', $body['uri']); + } + + public function testDeleteAuthkitOAuthResource(): void + { + $client = $this->createMockClient([['status' => 204]]); + $client->userManagement()->deleteAuthkitOAuthResource('test_id'); + $request = $this->getLastRequest(); + $this->assertSame('DELETE', $request->getMethod()); + $this->assertStringEndsWith('user_management/authkit_oauth_resources/test_id', $request->getUri()->getPath()); + } + public function testListCorsOrigins(): void { $fixture = $this->loadFixture('list_cors_origin_response'); @@ -815,12 +855,12 @@ public function testAuthenticateWithRadarSmsChallenge(): void public function testPaginationBoundary(): void { - $fixture = $this->loadFixture('list_cors_origin_response'); + $fixture = $this->loadFixture('list_authkit_oauth_resource'); // Ensure cursors are null (first/last page boundary) $fixture['list_metadata']['before'] = null; $fixture['list_metadata']['after'] = null; $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); - $result = $client->userManagement()->listCorsOrigins(); + $result = $client->userManagement()->listAuthkitOAuthResources(); $this->assertInstanceOf(\WorkOS\PaginatedResponse::class, $result); // Verify cursors are null on boundary page $this->assertNull($result->listMetadata['before']); From 7b60f8394ef0a3d3ca4574e8211dc022c895caf8 Mon Sep 17 00:00:00 2001 From: "workos-sdk-automation[bot]" <255426317+workos-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:28:27 +0000 Subject: [PATCH 3/5] feat(user_management): Add user management API surface --- lib/Resource/AuthkitOAuthResource.php | 52 +++++++++++++++++++ lib/Resource/CreateAuthkitOAuthResource.php | 36 +++++++++++++ tests/Fixtures/authkit_oauth_resource.json | 8 +++ .../create_authkit_oauth_resource.json | 4 ++ 4 files changed, 100 insertions(+) create mode 100644 lib/Resource/AuthkitOAuthResource.php create mode 100644 lib/Resource/CreateAuthkitOAuthResource.php create mode 100644 tests/Fixtures/authkit_oauth_resource.json create mode 100644 tests/Fixtures/create_authkit_oauth_resource.json diff --git a/lib/Resource/AuthkitOAuthResource.php b/lib/Resource/AuthkitOAuthResource.php new file mode 100644 index 00000000..879d516f --- /dev/null +++ b/lib/Resource/AuthkitOAuthResource.php @@ -0,0 +1,52 @@ + $this->object, + 'id' => $this->id, + 'uri' => $this->uri, + 'default' => $this->default, + 'created_at' => $this->createdAt, + 'updated_at' => $this->updatedAt, + ]; + } +} diff --git a/lib/Resource/CreateAuthkitOAuthResource.php b/lib/Resource/CreateAuthkitOAuthResource.php new file mode 100644 index 00000000..1a50e100 --- /dev/null +++ b/lib/Resource/CreateAuthkitOAuthResource.php @@ -0,0 +1,36 @@ + $this->uri, + 'default' => $this->default, + ]; + } +} diff --git a/tests/Fixtures/authkit_oauth_resource.json b/tests/Fixtures/authkit_oauth_resource.json new file mode 100644 index 00000000..34219a5d --- /dev/null +++ b/tests/Fixtures/authkit_oauth_resource.json @@ -0,0 +1,8 @@ +{ + "object": "authkit_oauth_resource", + "id": "authkit_oauth_resource_01EHZNVPK3SFK441A1RGBFSHRT", + "uri": "https://api.example.com", + "default": false, + "created_at": "2026-01-15T12:00:00.000Z", + "updated_at": "2026-01-15T12:00:00.000Z" +} diff --git a/tests/Fixtures/create_authkit_oauth_resource.json b/tests/Fixtures/create_authkit_oauth_resource.json new file mode 100644 index 00000000..29d4f9d8 --- /dev/null +++ b/tests/Fixtures/create_authkit_oauth_resource.json @@ -0,0 +1,4 @@ +{ + "uri": "https://api.example.com", + "default": false +} From 2a7602e0e9940d664ce419da40a580159550adde Mon Sep 17 00:00:00 2001 From: "workos-sdk-automation[bot]" <255426317+workos-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:28:27 +0000 Subject: [PATCH 4/5] chore(generated): regenerate shared files for AdminPortal, Agents, ApiKeys, AuditLogs, Authorization, ClientApi, Connect, DirectorySync, Events, FeatureFlags, Groups, MultiFactorAuth, OrganizationDomains, OrganizationMembership, Organizations, Pipes, PipesProvider, PlatformTeams, Radar, SSO, UserManagement, Vault, Webhooks, Widgets --- .last-synced-sha | 2 +- .oagen-manifest.json | 32 +++++++++++++++++ .../AccountSelectionRequiredError.php | 36 +++++++++++++++++++ lib/Resource/AuditLogsRetention.php | 2 +- lib/Resource/CreateDataIntegration.php | 4 +++ lib/Resource/DataIntegration.php | 4 +++ lib/Resource/DataIntegrationInstallation.php | 8 ++--- .../DataIntegrationsUpsertApiKeyRequest.php | 10 +++++- ...grationsUpsertClientCredentialsRequest.php | 10 +++++- ...DataIntegrationsVendCredentialsRequest.php | 12 +++++-- lib/Resource/GenerateLink.php | 4 +-- .../ResourceExportFailedDataResourceType.php | 1 + lib/Service/AdminPortal.php | 4 +-- lib/Service/Agents.php | 3 ++ .../account_selection_required_error.json | 4 +++ tests/Fixtures/create_data_integration.json | 1 + tests/Fixtures/data_integration.json | 1 + ...a_integrations_upsert_api_key_request.json | 2 ++ ...ons_upsert_client_credentials_request.json | 2 ++ ...integrations_vend_credentials_request.json | 4 ++- tests/Service/AdminPortalTest.php | 1 - tests/Service/AgentsTest.php | 4 +-- tests/Service/SSOTest.php | 2 +- 23 files changed, 134 insertions(+), 19 deletions(-) create mode 100644 lib/Resource/AccountSelectionRequiredError.php create mode 100644 tests/Fixtures/account_selection_required_error.json diff --git a/.last-synced-sha b/.last-synced-sha index 2f412fd3..1c2b758d 100644 --- a/.last-synced-sha +++ b/.last-synced-sha @@ -1 +1 @@ -6fba233c50a5b651b2df7b859b75bfe715bc825a +d3fa61120f8b9e73972b9dc5f4b5ea2bc0526636 diff --git a/.oagen-manifest.json b/.oagen-manifest.json index 0c3c5de5..657ad3b3 100644 --- a/.oagen-manifest.json +++ b/.oagen-manifest.json @@ -3,6 +3,7 @@ "language": "php", "files": [ "lib/Resource/AccessTokenAgentRegistrationCredentialIssuedDataDetail.php", + "lib/Resource/AccountSelectionRequiredError.php", "lib/Resource/ActionAuthenticationDenied.php", "lib/Resource/ActionAuthenticationDeniedData.php", "lib/Resource/ActionUserRegistrationDenied.php", @@ -182,6 +183,7 @@ "lib/Resource/AuthenticationSSOTimedOutData.php", "lib/Resource/AuthenticationSSOTimedOutDataError.php", "lib/Resource/AuthenticationSSOTimedOutDataSSO.php", + "lib/Resource/AuthkitOAuthResource.php", "lib/Resource/AuthorizationAssignment.php", "lib/Resource/AuthorizationCheck.php", "lib/Resource/AuthorizationCodeSessionAuthenticateRequest.php", @@ -231,6 +233,7 @@ "lib/Resource/ConnectionType.php", "lib/Resource/ConnectionsConnectionType.php", "lib/Resource/CreateApplicationSecret.php", + "lib/Resource/CreateAuthkitOAuthResource.php", "lib/Resource/CreateAuthorizationPermission.php", "lib/Resource/CreateAuthorizationResource.php", "lib/Resource/CreateCORSOrigin.php", @@ -514,6 +517,7 @@ "lib/Resource/PipesConnectedAccountConnectionFailedData.php", "lib/Resource/PipesConnectedAccountDisconnected.php", "lib/Resource/PipesConnectedAccountReauthorizationNeeded.php", + "lib/Resource/PipesOwnership.php", "lib/Resource/PortalLinkResponse.php", "lib/Resource/Profile.php", "lib/Resource/RadarChallenge.php", @@ -724,6 +728,7 @@ "lib/WorkOS.php", "tests/ClientTest.php", "tests/Fixtures/access_token_agent_registration_credential_issued_data_detail.json", + "tests/Fixtures/account_selection_required_error.json", "tests/Fixtures/action_authentication_denied.json", "tests/Fixtures/action_authentication_denied_data.json", "tests/Fixtures/action_user_registration_denied.json", @@ -888,6 +893,7 @@ "tests/Fixtures/authentication_sso_timed_out_data.json", "tests/Fixtures/authentication_sso_timed_out_data_error.json", "tests/Fixtures/authentication_sso_timed_out_data_sso.json", + "tests/Fixtures/authkit_oauth_resource.json", "tests/Fixtures/authorization_check.json", "tests/Fixtures/authorization_code_session_authenticate_request.json", "tests/Fixtures/authorization_permission.json", @@ -927,6 +933,7 @@ "tests/Fixtures/connection_saml_certificate_renewed_data_connection.json", "tests/Fixtures/cors_origin_response.json", "tests/Fixtures/create_application_secret.json", + "tests/Fixtures/create_authkit_oauth_resource.json", "tests/Fixtures/create_authorization_permission.json", "tests/Fixtures/create_authorization_resource.json", "tests/Fixtures/create_connection.json", @@ -1104,6 +1111,7 @@ "tests/Fixtures/list_audit_log_action.json", "tests/Fixtures/list_audit_log_schema.json", "tests/Fixtures/list_authentication_factor.json", + "tests/Fixtures/list_authkit_oauth_resource.json", "tests/Fixtures/list_authorization_permission.json", "tests/Fixtures/list_authorization_resource.json", "tests/Fixtures/list_authorized_connect_application_list_data.json", @@ -2379,6 +2387,30 @@ "POST /agents/blueprints/{agent_blueprint_id}/tokens/validate": { "sdkMethod": "validateBlueprintToken", "service": "agents" + }, + "GET /data-integrations/{slug}/organization": { + "sdkMethod": "listDataIntegrationOrganization", + "service": "pipes" + }, + "PUT /data-integrations/{slug}/organization": { + "sdkMethod": "updateDataIntegrationOrganization", + "service": "pipes" + }, + "DELETE /data-integrations/{slug}/organization": { + "sdkMethod": "deleteDataIntegrationOrganization", + "service": "pipes" + }, + "GET /user_management/authkit_oauth_resources": { + "sdkMethod": "listAuthkitOAuthResources", + "service": "userManagement" + }, + "POST /user_management/authkit_oauth_resources": { + "sdkMethod": "createAuthkitOAuthResource", + "service": "userManagement" + }, + "DELETE /user_management/authkit_oauth_resources/{id}": { + "sdkMethod": "deleteAuthkitOAuthResource", + "service": "userManagement" } } } diff --git a/lib/Resource/AccountSelectionRequiredError.php b/lib/Resource/AccountSelectionRequiredError.php new file mode 100644 index 00000000..b9139bc0 --- /dev/null +++ b/lib/Resource/AccountSelectionRequiredError.php @@ -0,0 +1,36 @@ + $this->code, + 'message' => $this->message, + ]; + } +} diff --git a/lib/Resource/AuditLogsRetention.php b/lib/Resource/AuditLogsRetention.php index 9304590d..5ca0ea82 100644 --- a/lib/Resource/AuditLogsRetention.php +++ b/lib/Resource/AuditLogsRetention.php @@ -11,7 +11,7 @@ use JsonSerializableTrait; public function __construct( - /** The number of days Audit Log events will be retained before being permanently deleted. Valid values are 30 and 365. */ + /** The number of days Audit Log events will be retained before being permanently deleted. Valid values are 30 through 330 in 30-day increments and 365 through 3650 in 365-day increments. */ public ?int $retentionPeriodInDays, ) { } diff --git a/lib/Resource/CreateDataIntegration.php b/lib/Resource/CreateDataIntegration.php index 14016a21..3b1cb14f 100644 --- a/lib/Resource/CreateDataIntegration.php +++ b/lib/Resource/CreateDataIntegration.php @@ -13,6 +13,8 @@ public function __construct( /** The provider to create a Data Integration for. For a built-in provider use its slug (e.g. `github`, `slack`). For a custom provider, this is the new provider slug and `custom_provider` must be supplied. A custom provider slug cannot shadow an existing global provider slug. */ public string $provider, + /** Who owns the Data Integration. `user` (the default) creates the integration users connect their own accounts to; `organization` creates the root organizations connect to. Ownership is fixed at creation, and one integration of each ownership may exist per provider. Independent of `credentials.type`. */ + public ?PipesOwnership $ownership = null, /** An optional description of the Data Integration. */ public ?string $description = null, /** Whether the Data Integration is enabled. Defaults to `false`. */ @@ -45,6 +47,7 @@ public static function fromArray(array $data): self { return new self( provider: $data['provider'], + ownership: isset($data['ownership']) ? PipesOwnership::from($data['ownership']) : null, description: $data['description'] ?? null, enabled: $data['enabled'] ?? null, scopes: $data['scopes'] ?? null, @@ -60,6 +63,7 @@ public function toArray(): array { return [ 'provider' => $this->provider, + 'ownership' => $this->ownership?->value, 'description' => $this->description, 'enabled' => $this->enabled, 'scopes' => $this->scopes, diff --git a/lib/Resource/DataIntegration.php b/lib/Resource/DataIntegration.php index 37ba266d..b43e0b05 100644 --- a/lib/Resource/DataIntegration.php +++ b/lib/Resource/DataIntegration.php @@ -19,6 +19,8 @@ public function __construct( public string $slug, /** The integration type derived from the provider. */ public string $integrationType, + /** Who owns the Data Integration: `user` when users connect their own accounts, `organization` when organizations connect. Fixed at creation. */ + public PipesOwnership $ownership, /** An optional description of the Data Integration. */ public ?string $description, /** Whether the Data Integration is enabled. */ @@ -62,6 +64,7 @@ public static function fromArray(array $data): self id: $data['id'], slug: $data['slug'], integrationType: $data['integration_type'], + ownership: PipesOwnership::from($data['ownership']), description: $data['description'] ?? null, enabled: $data['enabled'], state: DataIntegrationState::from($data['state']), @@ -84,6 +87,7 @@ public function toArray(): array 'id' => $this->id, 'slug' => $this->slug, 'integration_type' => $this->integrationType, + 'ownership' => $this->ownership->value, 'description' => $this->description, 'enabled' => $this->enabled, 'state' => $this->state->value, diff --git a/lib/Resource/DataIntegrationInstallation.php b/lib/Resource/DataIntegrationInstallation.php index f650fca9..28c6ad8d 100644 --- a/lib/Resource/DataIntegrationInstallation.php +++ b/lib/Resource/DataIntegrationInstallation.php @@ -13,9 +13,9 @@ public function __construct( /** Unique identifier of the installation. */ public string $id, - /** The User the API key was installed for. */ - public string $userId, - /** The Organization the installation is scoped to, or null when unscoped. */ + /** The User the API key was installed for. Null on an `organization`-owned integration, whose installations belong to the organization. */ + public ?string $userId, + /** The Organization the installation is scoped to (or owned by, on an `organization`-owned integration), or null when unscoped. */ public ?string $organizationId, /** The last four characters of the stored API key. The full key is never returned. */ public ?string $apiKeyLast4, @@ -26,7 +26,7 @@ public static function fromArray(array $data): self { return new self( id: $data['id'], - userId: $data['user_id'], + userId: $data['user_id'] ?? null, organizationId: $data['organization_id'] ?? null, apiKeyLast4: $data['api_key_last_4'] ?? null, ); diff --git a/lib/Resource/DataIntegrationsUpsertApiKeyRequest.php b/lib/Resource/DataIntegrationsUpsertApiKeyRequest.php index 1d7705c0..376bee75 100644 --- a/lib/Resource/DataIntegrationsUpsertApiKeyRequest.php +++ b/lib/Resource/DataIntegrationsUpsertApiKeyRequest.php @@ -15,8 +15,12 @@ public function __construct( public string $userId, /** The API key secret to store for this integration. */ public string $secret, - /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. */ + /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. */ public ?string $organizationId = null, + /** A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to rotate a specific existing connection. */ + public ?string $connectedAccountId = null, + /** Whose connection to create or rotate. `user` (the default) addresses the connection owned by `user_id`. `organization` addresses the connection shared by every member of `organization_id`; `user_id` then identifies the member performing the request and must be an active member of the organization. */ + public ?PipesOwnership $connectionOwner = null, ) { } @@ -26,6 +30,8 @@ public static function fromArray(array $data): self userId: $data['user_id'], secret: $data['secret'], organizationId: $data['organization_id'] ?? null, + connectedAccountId: $data['connected_account_id'] ?? null, + connectionOwner: isset($data['connection_owner']) ? PipesOwnership::from($data['connection_owner']) : null, ); } @@ -35,6 +41,8 @@ public function toArray(): array 'user_id' => $this->userId, 'secret' => $this->secret, 'organization_id' => $this->organizationId, + 'connected_account_id' => $this->connectedAccountId, + 'connection_owner' => $this->connectionOwner?->value, ]; } } diff --git a/lib/Resource/DataIntegrationsUpsertClientCredentialsRequest.php b/lib/Resource/DataIntegrationsUpsertClientCredentialsRequest.php index 570dba28..222c492c 100644 --- a/lib/Resource/DataIntegrationsUpsertClientCredentialsRequest.php +++ b/lib/Resource/DataIntegrationsUpsertClientCredentialsRequest.php @@ -17,8 +17,12 @@ public function __construct( public string $clientId, /** The OAuth client secret to store for this integration. */ public string $clientSecret, - /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. */ + /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. */ public ?string $organizationId = null, + /** A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to rotate a specific existing connection. */ + public ?string $connectedAccountId = null, + /** Whose connection to create or rotate. `user` (the default) addresses the connection owned by `user_id`. `organization` addresses the connection shared by every member of `organization_id`; `user_id` then identifies the member performing the request and must be an active member of the organization. */ + public ?PipesOwnership $connectionOwner = null, /** * Provider-specific configuration values collected for this installation, keyed by the provider's config field descriptors. * @var array|null @@ -34,6 +38,8 @@ public static function fromArray(array $data): self clientId: $data['client_id'], clientSecret: $data['client_secret'], organizationId: $data['organization_id'] ?? null, + connectedAccountId: $data['connected_account_id'] ?? null, + connectionOwner: isset($data['connection_owner']) ? PipesOwnership::from($data['connection_owner']) : null, config: $data['config'] ?? null, ); } @@ -45,6 +51,8 @@ public function toArray(): array 'client_id' => $this->clientId, 'client_secret' => $this->clientSecret, 'organization_id' => $this->organizationId, + 'connected_account_id' => $this->connectedAccountId, + 'connection_owner' => $this->connectionOwner?->value, 'config' => $this->config, ]; } diff --git a/lib/Resource/DataIntegrationsVendCredentialsRequest.php b/lib/Resource/DataIntegrationsVendCredentialsRequest.php index f6fe9d98..3cba3032 100644 --- a/lib/Resource/DataIntegrationsVendCredentialsRequest.php +++ b/lib/Resource/DataIntegrationsVendCredentialsRequest.php @@ -11,12 +11,16 @@ use JsonSerializableTrait; public function __construct( - /** A [User](https://workos.com/docs/reference/authkit/user) identifier. */ + /** A [User](https://workos.com/docs/reference/authkit/user) identifier. When `connection_owner` is `organization`, this is the user the credentials are vended on behalf of; they must be an active member of the organization. */ public string $userId, - /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. */ + /** An [Organization](https://workos.com/docs/reference/organization) identifier. Optional parameter to scope the connection to a specific organization. Required when `connection_owner` is `organization`. */ public ?string $organizationId = null, /** A [connected account](https://workos.com/docs/reference/pipes/connected-account) identifier. Use this to select a specific connection when the user has several for this provider. */ public ?string $connectedAccountId = null, + /** Which connection to vend from. `user` (the default) vends the user's own connection and requires `user_id`. `organization` vends the organization's shared connection and requires `organization_id`. */ + public ?PipesOwnership $connectionOwner = null, + /** Set to `true` to use the plural connection contract. If no `connected_account_id` is supplied and several connections match, the request returns `account_selection_required`. When omitted or `false`, only the compatibility connection is considered. */ + public ?bool $supportsMultipleConnections = null, ) { } @@ -26,6 +30,8 @@ public static function fromArray(array $data): self userId: $data['user_id'], organizationId: $data['organization_id'] ?? null, connectedAccountId: $data['connected_account_id'] ?? null, + connectionOwner: isset($data['connection_owner']) ? PipesOwnership::from($data['connection_owner']) : null, + supportsMultipleConnections: $data['supports_multiple_connections'] ?? null, ); } @@ -35,6 +41,8 @@ public function toArray(): array 'user_id' => $this->userId, 'organization_id' => $this->organizationId, 'connected_account_id' => $this->connectedAccountId, + 'connection_owner' => $this->connectionOwner?->value, + 'supports_multiple_connections' => $this->supportsMultipleConnections, ]; } } diff --git a/lib/Resource/GenerateLink.php b/lib/Resource/GenerateLink.php index 5970b0b8..d1bacff4 100644 --- a/lib/Resource/GenerateLink.php +++ b/lib/Resource/GenerateLink.php @@ -13,9 +13,9 @@ public function __construct( /** An [Organization](https://workos.com/docs/reference/organization) identifier. */ public string $organization, - /** The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ + /** The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Admin Portal](https://dashboard.workos.com/admin-portal) page will be used. */ public ?string $returnUrl = null, - /** The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. */ + /** The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Admin Portal](https://dashboard.workos.com/admin-portal) page will be used. */ public ?string $successUrl = null, /** * diff --git a/lib/Resource/ResourceExportFailedDataResourceType.php b/lib/Resource/ResourceExportFailedDataResourceType.php index d2e206c8..4be74e21 100644 --- a/lib/Resource/ResourceExportFailedDataResourceType.php +++ b/lib/Resource/ResourceExportFailedDataResourceType.php @@ -13,4 +13,5 @@ enum ResourceExportFailedDataResourceType: string case Events = 'events'; case Sessions = 'sessions'; case AuditLogEvents = 'auditLogEvents'; + case Connections = 'connections'; } diff --git a/lib/Service/AdminPortal.php b/lib/Service/AdminPortal.php index ff399d8f..54790b93 100644 --- a/lib/Service/AdminPortal.php +++ b/lib/Service/AdminPortal.php @@ -19,8 +19,8 @@ public function __construct( * Generate a Portal Link * * Generate a Portal Link scoped to an Organization. - * @param string|null $returnUrl The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. - * @param string|null $successUrl The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Redirects](https://dashboard.workos.com/redirects) page will be used. + * @param string|null $returnUrl The URL to go to when an admin clicks on your logo in the Admin Portal. If not specified, the return URL configured on the [Admin Portal](https://dashboard.workos.com/admin-portal) page will be used. + * @param string|null $successUrl The URL to redirect the admin to when they finish setup. If not specified, the success URL configured on the [Admin Portal](https://dashboard.workos.com/admin-portal) page will be used. * @param string $organization An [Organization](https://workos.com/docs/reference/organization) identifier. * @param \WorkOS\Resource\GenerateLinkIntent|null $intent * The intent of the Admin Portal. diff --git a/lib/Service/Agents.php b/lib/Service/Agents.php index eb486c52..bac1fa48 100644 --- a/lib/Service/Agents.php +++ b/lib/Service/Agents.php @@ -404,6 +404,7 @@ public function deleteInstance( * @param string|null $after An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. * @param int|null $limit Upper limit on the number of objects to return, between `1` and `100`. Defaults to 10. * @param \WorkOS\Resource\PaginationOrder $order Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to "desc". + * @param string|null $organizationId Only return sessions of instances acting within this organization. * @param string|null $agentBlueprintId Only return sessions of instances minted from this blueprint. * @param string|null $agentInstanceId Only return sessions belonging to this agent instance. * @return \WorkOS\PaginatedResponse<\WorkOS\Resource\AgentInstanceSession> @@ -414,6 +415,7 @@ public function listSessions( ?string $after = null, ?int $limit = null, \WorkOS\Resource\PaginationOrder $order = \WorkOS\Resource\PaginationOrder::Desc, + ?string $organizationId = null, ?string $agentBlueprintId = null, ?string $agentInstanceId = null, ?\WorkOS\RequestOptions $options = null, @@ -423,6 +425,7 @@ public function listSessions( 'after' => $after, 'limit' => $limit, 'order' => $order->value, + 'organization_id' => $organizationId, 'agent_blueprint_id' => $agentBlueprintId, 'agent_instance_id' => $agentInstanceId, ], fn ($v) => $v !== null); diff --git a/tests/Fixtures/account_selection_required_error.json b/tests/Fixtures/account_selection_required_error.json new file mode 100644 index 00000000..f946d293 --- /dev/null +++ b/tests/Fixtures/account_selection_required_error.json @@ -0,0 +1,4 @@ +{ + "code": "account_selection_required", + "message": "Several connected accounts match this user for this provider. Name one with a connected account id." +} diff --git a/tests/Fixtures/create_data_integration.json b/tests/Fixtures/create_data_integration.json index 311643a1..019066f2 100644 --- a/tests/Fixtures/create_data_integration.json +++ b/tests/Fixtures/create_data_integration.json @@ -1,5 +1,6 @@ { "provider": "github", + "ownership": "user", "description": "Production GitHub app", "enabled": true, "scopes": [ diff --git a/tests/Fixtures/data_integration.json b/tests/Fixtures/data_integration.json index 5a4a1532..c61f861f 100644 --- a/tests/Fixtures/data_integration.json +++ b/tests/Fixtures/data_integration.json @@ -3,6 +3,7 @@ "id": "data_integration_01EHZNVPK3SFK441A1RGBFSHRT", "slug": "github", "integration_type": "github", + "ownership": "user", "description": "Production GitHub app", "enabled": true, "state": "valid", diff --git a/tests/Fixtures/data_integrations_upsert_api_key_request.json b/tests/Fixtures/data_integrations_upsert_api_key_request.json index bf0bd81b..45952523 100644 --- a/tests/Fixtures/data_integrations_upsert_api_key_request.json +++ b/tests/Fixtures/data_integrations_upsert_api_key_request.json @@ -1,5 +1,7 @@ { "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "connection_owner": "user", "secret": "sk-1234567890abcdef" } diff --git a/tests/Fixtures/data_integrations_upsert_client_credentials_request.json b/tests/Fixtures/data_integrations_upsert_client_credentials_request.json index 1dc0fac0..9497d49c 100644 --- a/tests/Fixtures/data_integrations_upsert_client_credentials_request.json +++ b/tests/Fixtures/data_integrations_upsert_client_credentials_request.json @@ -1,6 +1,8 @@ { "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", + "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "connection_owner": "user", "client_id": "3MVG9...", "client_secret": "shhh-secret", "config": { diff --git a/tests/Fixtures/data_integrations_vend_credentials_request.json b/tests/Fixtures/data_integrations_vend_credentials_request.json index 66f0412e..9b96a12f 100644 --- a/tests/Fixtures/data_integrations_vend_credentials_request.json +++ b/tests/Fixtures/data_integrations_vend_credentials_request.json @@ -1,5 +1,7 @@ { "user_id": "user_01EHZNVPK3SFK441A1RGBFSHRT", "organization_id": "org_01EHZNVPK3SFK441A1RGBFSHRT", - "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT" + "connected_account_id": "data_installation_01EHZNVPK3SFK441A1RGBFSHRT", + "connection_owner": "user", + "supports_multiple_connections": true } diff --git a/tests/Service/AdminPortalTest.php b/tests/Service/AdminPortalTest.php index 90d75260..7c99482b 100644 --- a/tests/Service/AdminPortalTest.php +++ b/tests/Service/AdminPortalTest.php @@ -19,7 +19,6 @@ public function testGenerateLink(): void $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); $result = $client->adminPortal()->generateLink(organization: 'test_value'); $this->assertInstanceOf(\WorkOS\Resource\PortalLinkResponse::class, $result); - $this->assertSame($fixture['link'], $result->link); $this->assertIsArray($result->toArray()); $request = $this->getLastRequest(); $this->assertSame('POST', $request->getMethod()); diff --git a/tests/Service/AgentsTest.php b/tests/Service/AgentsTest.php index 2e3a08d3..ff1f9d1d 100644 --- a/tests/Service/AgentsTest.php +++ b/tests/Service/AgentsTest.php @@ -117,7 +117,6 @@ public function testUpdateAttempts(): void $result = $client->agents()->updateAttempts(type: 'test_value', claimAttemptToken: 'test_value', user: \WorkOS\Resource\AgentAdminLinkClaimAttemptToExternalUserRequestUser::fromArray($this->loadFixture('agent_admin_link_claim_attempt_to_external_user_request_user'))); $this->assertInstanceOf(\WorkOS\Resource\ClaimViewResponse::class, $result); $this->assertSame($fixture['id'], $result->id); - $this->assertSame($fixture['user_code'], $result->userCode); $this->assertIsArray($result->toArray()); $request = $this->getLastRequest(); $this->assertSame('PATCH', $request->getMethod()); @@ -200,7 +199,7 @@ public function testListSessions(): void { $fixture = $this->loadFixture('list_agent_instance_session'); $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); - $result = $client->agents()->listSessions(before: 'test_value', after: 'test_value', limit: 1, order: \WorkOS\Resource\PaginationOrder::Normal, agentBlueprintId: 'test_value', agentInstanceId: 'test_value'); + $result = $client->agents()->listSessions(before: 'test_value', after: 'test_value', limit: 1, order: \WorkOS\Resource\PaginationOrder::Normal, organizationId: 'test_value', agentBlueprintId: 'test_value', agentInstanceId: 'test_value'); $this->assertInstanceOf(\WorkOS\PaginatedResponse::class, $result); $request = $this->getLastRequest(); $this->assertSame('GET', $request->getMethod()); @@ -210,6 +209,7 @@ public function testListSessions(): void $this->assertSame('test_value', $query['after']); $this->assertArrayHasKey('limit', $query); $this->assertSame('normal', $query['order']); + $this->assertSame('test_value', $query['organization_id']); $this->assertSame('test_value', $query['agent_blueprint_id']); $this->assertSame('test_value', $query['agent_instance_id']); } diff --git a/tests/Service/SSOTest.php b/tests/Service/SSOTest.php index 48d27ba5..726e9680 100644 --- a/tests/Service/SSOTest.php +++ b/tests/Service/SSOTest.php @@ -231,7 +231,7 @@ public function testAuthorizeLogout(): void $client = $this->createMockClient([['status' => 200, 'body' => $fixture]]); $result = $client->sso()->authorizeLogout(profileId: 'test_value'); $this->assertInstanceOf(\WorkOS\Resource\SSOLogoutAuthorizeResponse::class, $result); - $this->assertSame($fixture['logout_url'], $result->logoutUrl); + $this->assertSame($fixture['logout_token'], $result->logoutToken); $this->assertIsArray($result->toArray()); $request = $this->getLastRequest(); $this->assertSame('POST', $request->getMethod()); From 31864d0893d41b977b3741a160264497b90678a3 Mon Sep 17 00:00:00 2001 From: "workos-sdk-automation[bot]" <255426317+workos-sdk-automation[bot]@users.noreply.github.com> Date: Mon, 14 Sep 2026 13:28:35 +0000 Subject: [PATCH 5/5] chore(generated): add release notes fragment --- ...b4d419df1198eced531b9867bfbfdee80433fe2.md | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 .changelog-pending/2026-09-14T13-28-35-0b4d419df1198eced531b9867bfbfdee80433fe2.md diff --git a/.changelog-pending/2026-09-14T13-28-35-0b4d419df1198eced531b9867bfbfdee80433fe2.md b/.changelog-pending/2026-09-14T13-28-35-0b4d419df1198eced531b9867bfbfdee80433fe2.md new file mode 100644 index 00000000..d273fe83 --- /dev/null +++ b/.changelog-pending/2026-09-14T13-28-35-0b4d419df1198eced531b9867bfbfdee80433fe2.md @@ -0,0 +1,102 @@ +* [#443](https://github.com/workos/workos-php/pull/443) feat(generated): regenerate from spec (4 changes) + + **Features** + * **[admin_portal](https://workos.com/docs/reference/admin-portal)**: + * Changed the format of `PortalLinkResponse.link` + * **[agents](https://workos.com/docs/reference/agents)**: + * Added parameter `AgentsSessions.list.organization_id` + * Changed the format of `ClaimViewResponse.user_code` + * Changed the format of `AgentAdminValidateCredentialRequest.credential` + * **[api_keys](https://workos.com/docs/reference/authkit/api-keys)**: + * Changed the format of `ValidateApiKey.value` + * Changed the format of `OrganizationApiKeyWithValue.value` + * Changed the format of `UserApiKeyWithValue.value` + * **[multi_factor_auth](https://workos.com/docs/reference/authkit/mfa)**: + * Changed the format of `AuthenticationChallenge.code` + * Changed the format of `AuthenticationFactorEnrolledTotp.secret` + * Changed the format of `AuthenticationFactorEnrolledTotp.qr_code` + * Changed the format of `AuthenticationFactorEnrolledTotp.uri` + * Changed the format of `AuthenticationChallengesVerifyRequest.code` + * **[pipes](https://workos.com/docs/reference/pipes)**: + * Added `supports_multiple_connections` to `DataIntegrationsVendCredentialsRequest` + * Added `supports_multiple_connections` to `DataIntegrationsGetUserTokenRequest` + * Added parameter `UserManagementDataProviders.getUserDataInstallation.supports_multiple_connections` + * Added parameter `UserManagementDataProviders.updateUserDataInstallation.supports_multiple_connections` + * Added parameter `UserManagementDataProviders.deleteUserDataInstallation.supports_multiple_connections` + * Added parameter `UserManagementDataProviders.getUserDataIntegrations.supports_multiple_connections` + * Added enum `PipesOwnership` + * Added `user` to `CreateDataIntegrationOwnership` + * Added `user` to `DataIntegrationOwnership` + * Added endpoint `GET /data-integrations/{slug}/organization` + * Added endpoint `PUT /data-integrations/{slug}/organization` + * Added endpoint `DELETE /data-integrations/{slug}/organization` + * Added parameter `Pipes.listDataIntegrations.ownership` + * Changed errors for endpoint `GET /data-integrations` + * Changed errors for endpoint `PUT /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed errors for endpoint `DELETE /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed the format of `DataIntegrationCredentialsResponseCredential.value` + * Added `connection_owner` to `DataIntegrationsUpsertApiKeyRequest` + * Added `connection_owner` to `DataIntegrationsUpsertClientCredentialsRequest` + * Added enum `DataIntegrationsUpsertApiKeyRequestConnectionOwner` + * Added enum `DataIntegrationsUpsertClientCredentialsRequestConnectionOwner` + * Added model `AccountSelectionRequiredError` + * Added `connected_account_id` to `DataIntegrationsUpsertApiKeyRequest` + * Added `connected_account_id` to `DataIntegrationsUpsertClientCredentialsRequest` + * Added `ownership` to `CreateDataIntegration` + * Added `ownership` to `DataIntegration` + * Added `connection_owner` to `DataIntegrationsVendCredentialsRequest` + * Added `connection_owner` to `DataIntegrationsGetUserTokenRequest` + * Added enum `CreateDataIntegrationOwnership` + * Added enum `DataIntegrationOwnership` + * Added enum `DataIntegrationsVendCredentialsRequestConnectionOwner` + * Added enum `DataIntegrationsGetUserTokenRequestConnectionOwner` + * Changed errors for endpoint `POST /data-integrations/{slug}/credentials` + * Changed errors for endpoint `POST /data-integrations/{provider}/token` + * **[sso](https://workos.com/docs/reference/sso)**: + * Changed the format of `CreateConnectionKeyPair.key` + * Changed the format of `TokenQuery.code` + * Changed the format of `SSOLogoutAuthorizeResponse.logout_url` + * **[user_management](https://workos.com/docs/reference/authkit/user)**: + * Added model `CreateAuthkitOAuthResource` + * Added model `AuthkitOAuthResource` + * Added service `UserManagementAuthkitOAuthResources` + * Changed the format of `DeviceAuthorizationResponse.verification_uri_complete` + * Changed the format of `VerifyEmailAddress.code` + * Changed the format of `ConfirmEmailChange.code` + * Changed the format of `MagicAuth.code` + * Changed the format of `UserInvite.accept_invitation_url` + * Changed the format of `EmailVerification.code` + * Changed the format of `PasswordReset.password_reset_url` + * Changed the format of `AuthenticateResponse.authkit_authorization_code` + * Changed the format of `DeviceAuthorizationResponse.device_code` + * Changed the format of `DeviceAuthorizationResponse.user_code` + * Changed the format of `AuthorizationCodeSessionAuthenticateRequest.code` + * Changed the format of `AuthorizationCodeSessionAuthenticateRequest.code_verifier` + * Changed the format of `MagicAuthCodeSessionAuthenticateRequest.code` + * Changed the format of `EmailVerificationCodeSessionAuthenticateRequest.code` + * Changed the format of `MfaTotpSessionAuthenticateRequest.code` + * Changed the format of `RadarEmailChallengeCodeSessionAuthenticateRequest.code` + * Changed the format of `RadarSmsChallengeCodeSessionAuthenticateRequest.code` + * Changed the format of `DeviceCodeSessionAuthenticateRequest.device_code` + * Changed the format of `Invitation.accept_invitation_url` + * Changed the format of `MagicAuthSendMagicAuthCodeAndReturnResponse.code` + * **[radar](https://workos.com/docs/reference/radar)**: + * Changed the format of `RadarChallenge.code` + * **[vault](https://workos.com/docs/reference/vault)**: + * Changed the format of `CreateObjectRequest.value` + * Changed the format of `VaultObject.value` + * Changed the format of `UpdateObjectRequest.value` + + **Fixes** + * **[pipes](https://workos.com/docs/reference/pipes)**: + * Removed `userland_user` from `CreateDataIntegrationOwnership` + * Removed `userland_user` from `DataIntegrationOwnership` + * Changed errors for endpoint `POST /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed errors for endpoint `PUT /data-integrations/{slug}/api-key` + * Changed errors for endpoint `PUT /data-integrations/{slug}/client-credentials` + * Changed errors for endpoint `POST /data-integrations/{slug}/credentials` + * Changed errors for endpoint `POST /data-integrations/{provider}/token` + * Changed errors for endpoint `GET /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed errors for endpoint `PUT /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed errors for endpoint `DELETE /user_management/users/{user_id}/connected_accounts/{slug}` + * Changed the type of `DataIntegrationInstallation.user_id`